From 8389524f4ceeed6ae04311efd1a17dcff0477244 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sat, 22 Feb 2025 02:44:21 +0100 Subject: [PATCH 001/126] First draft of reorganization by app: - ControlPanel (in progress) - FileStation --- .../DSM/ControlPanel/ApplicationPrivileges.py | 294 ++++ synology_api/DSM/ControlPanel/DomainLDAP.py | 249 ++++ .../DSM/ControlPanel/ExternalAccess.py | 4 + .../DSM/ControlPanel/ExternalDevices.py | 4 + synology_api/DSM/ControlPanel/FileServices.py | 4 + .../DSM/ControlPanel/HardwarePower.py | 4 + .../DSM/ControlPanel/IndexingService.py | 4 + synology_api/DSM/ControlPanel/InfoCenter.py | 4 + synology_api/DSM/ControlPanel/LoginPortal.py | 4 + synology_api/DSM/ControlPanel/Network.py | 4 + .../DSM/ControlPanel/Notifications.py | 4 + .../DSM/ControlPanel/RegionalOptions.py | 4 + synology_api/DSM/ControlPanel/Security.py | 4 + synology_api/DSM/ControlPanel/SharedFolder.py | 841 +++++++++++ .../DSM/ControlPanel/SynologyAccount.py | 4 + .../DSM/ControlPanel/TaskScheduler.py | 4 + synology_api/DSM/ControlPanel/TerminalSNMP.py | 4 + .../DSM/ControlPanel/UpdateRestore.py | 4 + synology_api/DSM/ControlPanel/UserGroup.py | 4 + synology_api/DSM/ControlPanel/__init__.py | 219 +++ synology_api/DSM/FileStation.py | 1287 +++++++++++++++++ synology_api/DSM/__init__.py | 30 + 22 files changed, 2984 insertions(+) create mode 100644 synology_api/DSM/ControlPanel/ApplicationPrivileges.py create mode 100644 synology_api/DSM/ControlPanel/DomainLDAP.py create mode 100644 synology_api/DSM/ControlPanel/ExternalAccess.py create mode 100644 synology_api/DSM/ControlPanel/ExternalDevices.py create mode 100644 synology_api/DSM/ControlPanel/FileServices.py create mode 100644 synology_api/DSM/ControlPanel/HardwarePower.py create mode 100644 synology_api/DSM/ControlPanel/IndexingService.py create mode 100644 synology_api/DSM/ControlPanel/InfoCenter.py create mode 100644 synology_api/DSM/ControlPanel/LoginPortal.py create mode 100644 synology_api/DSM/ControlPanel/Network.py create mode 100644 synology_api/DSM/ControlPanel/Notifications.py create mode 100644 synology_api/DSM/ControlPanel/RegionalOptions.py create mode 100644 synology_api/DSM/ControlPanel/Security.py create mode 100644 synology_api/DSM/ControlPanel/SharedFolder.py create mode 100644 synology_api/DSM/ControlPanel/SynologyAccount.py create mode 100644 synology_api/DSM/ControlPanel/TaskScheduler.py create mode 100644 synology_api/DSM/ControlPanel/TerminalSNMP.py create mode 100644 synology_api/DSM/ControlPanel/UpdateRestore.py create mode 100644 synology_api/DSM/ControlPanel/UserGroup.py create mode 100644 synology_api/DSM/ControlPanel/__init__.py create mode 100644 synology_api/DSM/FileStation.py create mode 100644 synology_api/DSM/__init__.py diff --git a/synology_api/DSM/ControlPanel/ApplicationPrivileges.py b/synology_api/DSM/ControlPanel/ApplicationPrivileges.py new file mode 100644 index 00000000..02900291 --- /dev/null +++ b/synology_api/DSM/ControlPanel/ApplicationPrivileges.py @@ -0,0 +1,294 @@ +from synology_api import base_api +import json + +class ApplicationPrivileges(base_api.BaseApi): + + def list_all(self, offset: int = 0, limit: int = 20) -> dict: + """List applications privileges. + + Parameters + ---------- + offset : int, optional + Offset in the application list. Defaults to `0` + limit : int, optional + Limit the len of the returned list. Defaults to `20` + + Returns + ------- + dict + List of applications privileges. + + Example return + ---------- + ```json + { + "data": { + "applications": [ + { + "app_id": "SYNO.AFP", + "grant_by_default": true, + "grant_type": [ + "local", + "domain", + "ldap" + ], + "isInternal": true, + "name": "AFP", + "service_type": "modules/LegacyApps", + "supportIP": true + }, + { + "app_id": "SYNO.Desktop", + "grant_by_default": true, + "grant_type": [ + "local", + "domain", + "ldap" + ], + "isInternal": true, + "name": "DSM", + "service_type": "modules/LegacyApps", + "supportIP": true + } + ], + "offset": 0, + "total": 2 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.AppPriv.App' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'offset': offset, + 'limit': limit + } + + return self.request_data(api_name, api_path, req_param) + + def list_entities(self, app_id: str, type: str = "local", filter_type: str = "all", rule_type: str = "user", offset: int = 0, limit: int = 50) -> dict: + """List entities of the specify app_id. + + Parameters + ---------- + app_id : str + Application ID + type : str, optional + Type to filter for rule_type. Defaults to `"local"` + Example: for rule_type = "user", type = "local" + All known values are: `["local"]` + filter_type : str, optional + Filter actual rules. Defaults to `"all"` + All known values are: `["all", "allow", "deny", "any", "custom"]` + rule_type : str, optional + Type of the rule. Defaults to `"user"` + All known values are: `["user", "group"]` + offset : int, optional + Offset in entity list. Defaults to `0` + limit : int, optional + Limit the len of the returned list. Defaults to `50` + + Returns + ------- + dict + Return list of entity available + + Example return + ---------- + ```json + { + "data": { + "offset": 0, + "total": 3, + "users": [ + { + "name": "admin" + }, + { + "name": "guest" + }, + { + "name": "test_api" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.AppPriv' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'action': 'list', + 'offset': offset, + 'limit': limit, + 'type': type, + 'app_id': app_id, + 'filter_type': filter_type, + 'rule_type': rule_type + } + + return self.request_data(api_name, api_path, req_param) + + def list_app_rules(self, app_id: str) -> dict: + """Retrieve application rules. + + Parameters + ---------- + app_id : str + Application ID + + Returns + ------- + dict + List of rules + + Example return + ---------- + ```json + "data": { + "rules": [ + { + "allow_ip": [ + "0.0.0.0" + ], + "app_id": "SYNO.AFP", + "deny_ip": [], + "entity_name": "everyone", + "entity_type": "everyone" + }, + { + "allow_ip": [ + "0.0.0.0" + ], + "app_id": "SYNO.AFP", + "deny_ip": [], + "entity_name": "test_api", + "entity_type": "user" + }, + { + "allow_ip": [ + "0.0.0.0" + ], + "app_id": "SYNO.AFP", + "deny_ip": [], + "entity_name": "test_group", + "entity_type": "group" + } + ] + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.AppPriv.Rule' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'app_id': app_id + } + + return self.request_data(api_name, api_path, req_param) + + def set_app_rules(self, app_id: str, rules: list) -> dict: + """Set application rules. + + Parameters + ---------- + app_id : str + Application ID + rules : list + List of rules, a rule is a dict with the following keys: + ```json + { + "entity_type":"user", + "entity_name":"test_api", + "app_id":"SYNO.AFP", + "allow_ip":["0.0.0.0"], + "deny_ip":[] + } + ``` + + Returns + ------- + dict + Success + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.AppPriv.Rule' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'app_id': app_id, + 'rules': json.dumps(rules) + } + + return self.request_data(api_name, api_path, req_param) + + def delete_app_rules(self, app_id: str, rules: list) -> dict: + """Delete application rules. + + Parameters + ---------- + app_id : str + Application ID + rules : list + List of rules, a rule is a dict with the following keys: + ```json + { + "entity_type":"user", + "entity_name":"test_api", + "app_id":"SYNO.AFP", + "allow_ip":["0.0.0.0"], + "deny_ip":[] + } + ``` + + Returns + ------- + dict + Success + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.AppPriv.Rule' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'delete', + 'app_id': app_id, + 'rules': json.dumps(rules) + } + + return self.request_data(api_name, api_path, req_param) + + + \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/DomainLDAP.py b/synology_api/DSM/ControlPanel/DomainLDAP.py new file mode 100644 index 00000000..03d15558 --- /dev/null +++ b/synology_api/DSM/ControlPanel/DomainLDAP.py @@ -0,0 +1,249 @@ +from synology_api import base_api + +class DomainLDAP(base_api.BaseApi): + + def get_ldap_info(self) -> dict: + """Get LDAP information + + Returns + ------- + dict + Informations about LDAP settings + + Example return + ---------- + ```json + { + "data": { + "base_dn": "dc=test_api,dc=dev", + "enable_cifs": false, + "enable_cifs_pam": false, + "enable_client": false, + "enable_client_certificate": false, + "enable_idmap": false, + "encryption": "no", + "error": 2703, + "expand_nested_groups": true, + "is_syno_server": false, + "ldap_schema": "rfc2307bis", + "nested_group_level": 5, + "profile": "standard", + "server_address": "127.0.0.1", + "tls_reqcert": false, + "update_min": 60 + }, + "success": true, + ``` + """ + + api_name = 'SYNO.Core.Directory.LDAP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + def get_domain_info(self) -> dict: + """Get domain info + + Returns + ------- + dict + Informations about domain + + Example return + ---------- + ```json + { + "data": { + "enable_domain": false + }, + "success": true, + } + ``` + """ + + api_name = 'SYNO.Core.Directory.Domain' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + def get_sso_login_settings(self) -> dict: + """Get SSO login settings + + Returns + ------- + dict + Informations about SSO login settings + + Example return + ---------- + ```json + { + "data": { + "sso_default_login": false + }, + "success": true, + } + ``` + """ + + api_name = 'SYNO.Core.Directory.SSO.Setting' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + def get_synology_sso_settings(self) -> dict: + """Get Synology SSO service settings + + Returns + ------- + dict + Informations about Synology SSO service settings + + Example return + ---------- + ```json + { + "data": { + "allow_local_user": true, + "appid": "", + "enable_sso": false, + "host": "", + "name": "Synology SSO", + "pingpong": null, + "sso_default_login": false + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Directory.SSO' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + def get_sso_profile(self) -> dict: + """Get SSO profile + + Returns + ------- + dict + Informations about SSO profile + + Example return + ---------- + ```json + { + "data": { + "sso_enable": false, + "sso_profile": "" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Directory.SSO.Profile' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + def get_sam_sso_settings(self) -> dict: + """Get SAM SSO settings + + Returns + ------- + dict + Informations about SAM SSO settings + + Example return + ---------- + ```json + { + "data": { + "saml_allow_local_user": false, + "saml_cert_detail": "", + "saml_idp_entity_id": "", + "saml_idp_signin_url": "", + "saml_name": "SAML", + "saml_response_signature": "response", + "saml_system_date": "", + "saml_valid_date": "", + "sso_saml_enable": "" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Directory.SSO.SAM' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + def get_cas_sso_settings(self) -> dict: + """Get CAS SSO settings + + Returns + ------- + dict + Informations about CAS SSO settings + + Example return + ---------- + ```json + { + "data": { + "cas_allow_local_user": true, + "cas_auth_url": "", + "cas_name": "CAS", + "cas_service_ids": "", + "cas_validate_url": "", + "sso_cas_enable": "" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Directory.SSO.CAS' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + + return self.request_data(api_name, api_path, req_param) + + \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/ExternalAccess.py b/synology_api/DSM/ControlPanel/ExternalAccess.py new file mode 100644 index 00000000..f078146b --- /dev/null +++ b/synology_api/DSM/ControlPanel/ExternalAccess.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class ExternalAccess(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/ExternalDevices.py b/synology_api/DSM/ControlPanel/ExternalDevices.py new file mode 100644 index 00000000..afe3f1c8 --- /dev/null +++ b/synology_api/DSM/ControlPanel/ExternalDevices.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class ExternalDevices(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/FileServices.py b/synology_api/DSM/ControlPanel/FileServices.py new file mode 100644 index 00000000..6514b1ee --- /dev/null +++ b/synology_api/DSM/ControlPanel/FileServices.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class FileServices(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/HardwarePower.py b/synology_api/DSM/ControlPanel/HardwarePower.py new file mode 100644 index 00000000..5af857e7 --- /dev/null +++ b/synology_api/DSM/ControlPanel/HardwarePower.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class HardwarePower(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/IndexingService.py b/synology_api/DSM/ControlPanel/IndexingService.py new file mode 100644 index 00000000..c8e4f319 --- /dev/null +++ b/synology_api/DSM/ControlPanel/IndexingService.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class IndexingService(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/InfoCenter.py b/synology_api/DSM/ControlPanel/InfoCenter.py new file mode 100644 index 00000000..593b26b6 --- /dev/null +++ b/synology_api/DSM/ControlPanel/InfoCenter.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class InfoCenter(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/LoginPortal.py b/synology_api/DSM/ControlPanel/LoginPortal.py new file mode 100644 index 00000000..6c29bc1f --- /dev/null +++ b/synology_api/DSM/ControlPanel/LoginPortal.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class LoginPortal(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/Network.py b/synology_api/DSM/ControlPanel/Network.py new file mode 100644 index 00000000..f593a6e5 --- /dev/null +++ b/synology_api/DSM/ControlPanel/Network.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class Network(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/Notifications.py b/synology_api/DSM/ControlPanel/Notifications.py new file mode 100644 index 00000000..66074329 --- /dev/null +++ b/synology_api/DSM/ControlPanel/Notifications.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class Notifications(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/RegionalOptions.py b/synology_api/DSM/ControlPanel/RegionalOptions.py new file mode 100644 index 00000000..d6202b2b --- /dev/null +++ b/synology_api/DSM/ControlPanel/RegionalOptions.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class RegionalOptions(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/Security.py b/synology_api/DSM/ControlPanel/Security.py new file mode 100644 index 00000000..ec0aa035 --- /dev/null +++ b/synology_api/DSM/ControlPanel/Security.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class Security(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/SharedFolder.py b/synology_api/DSM/ControlPanel/SharedFolder.py new file mode 100644 index 00000000..d6576ece --- /dev/null +++ b/synology_api/DSM/ControlPanel/SharedFolder.py @@ -0,0 +1,841 @@ +from synology_api import base_api +import json +from typing import List, Any + +class SharedFolder(base_api.BaseApi): + """ + Core Share API implementation. + """ + + def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_compress: bool = False, enable_share_cow: bool = False, enc_passwd: str = "", encryption: bool = False) -> dict: + """Validate set of parameter for a new / modified shared folder + Parameters + ---------- + name : str + Share name. + + vol_path : str + Volume path. + + desc : str, optional + Share description. Defaults to `""`. + + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + + enc_passwd : str, optional + Encrypted password. Defaults to `""`. + + encryption : bool, optional + Enable encryption. Defaults to `False`. + + Returns + ------- + dict + Success. + + Example return + -------------- + ```json + { + "success": true, + } + ``` + """ + api_name = "SYNO.Core.Share" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "validate_set", + "version": info['maxVersion'], + "name": name, + } + + req_param_encrypted = { + "shareinfo": json.dumps({ + "name": name, + "vol_path": vol_path, + "desc": desc, + "enable_share_compress": enable_share_compress, + "enable_share_cow": enable_share_cow, + "enc_passwd": enc_passwd, + "encryption": encryption, + }) + } + + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + + return self.request_data(api_name, api_path, req_param, method="post") + + def list_folders(self, share_type: str = "all", additional: list = []) -> dict: + """List all folders informations + Parameters + ---------- + share_type : str, optional + Share type. Defaults to `all`. + + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `[ + "hidden","encryption","is_aclmode","unite_permission","is_support_acl","is_sync_share","is_force_readonly","force_readonly_reason", + "recyclebin","is_share_moving","is_cluster_share","is_exfat_share","is_c2_share","is_cold_storage_share","is_missing_share", + "is_offline_share","support_snapshot","share_quota","enable_share_compress","enable_share_cow","enable_share_tiering", + "load_worm_attr","include_cold_storage_share","is_cold_storage_share","include_missing_share","is_missing_share", + "include_offline_share","is_offline_share","include_worm_share" + ]`. + + Returns + ------- + dict + A dictionary containing the shared folders information. + + Example return + -------------- + ```json + { + "data": { + "shares": [ + { + "desc": "", + "is_usb_share": false, + "name": "test_shared_folder", + "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", + "vol_path": "/volume1" + } + ], + "total": 1 + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "list", + "version": info['minVersion'], + "shareType": share_type, + "additional": json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def get_folder(self, name: str, additional: list = []) -> dict: + """Get a folder by name + Parameters + ---------- + name : str + Share name. + + additional : list, optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `["disable_list","disable_modify","disable_download","unite_permission","is_aclmode"]`. + + Returns + ------- + dict + A dictionary containing the shared folder information. + + Example return + -------------- + ```json + { + "data": { + "desc": "", + "disable_download": false, + "disable_list": false, + "disable_modify": false, + "is_aclmode": true, + "is_usb_share": false, + "name": "test_shared_folder", + "unite_permission": false, + "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", + "vol_path": "/volume1" + }, + "success": true, + ``` + """ + api_name = "SYNO.Core.Share" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "get", + "version": info['minVersion'], + "name": name, + "additional": json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def create_folder(self, + name: str, vol_path: str, desc: str = "", hidden: bool = False, + enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, + hide_unreadable: bool = False, enable_share_cow: bool = False, + enable_share_compress: bool = False, share_quota: int = 0, name_org: str = "", + ) -> dict: + """Create a new shared folder + Parameters + ---------- + name : str + Share name. + + vol_path : str + Volume path. + + desc : str, optional + Share description. Defaults to `""`. + + hidden : bool, optional + Hide share. Defaults to `False`. + + enable_recycle_bin : bool, optional + Enable recycle bin. Defaults to `True`. + + recycle_bin_admin_only : bool, optional + Recycle bin admin only. Defaults to `True`. + + hide_unreadable : bool, optional + Hide unreadable. Defaults to `False`. + + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + + share_quota : int, optional + Share quota. Defaults to `0`. + + name_org : str, optional + Defaults to `""`. + + Returns + ------- + dict + Name of the created shared folder + + Example return + --------------- + ```json + { + "data": { + "name": "test_shared_folder" + }, + "success": true, + ``` + """ + + api_name = "SYNO.Core.Share" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "create", + "version": info['maxVersion'], + "name": name, + } + req_param_encrypted = { + "shareinfo": json.dumps({ + "desc": desc, + "enable_recycle_bin": enable_recycle_bin, + "enable_share_compress": enable_share_compress, + "enable_share_cow": enable_share_cow, + "name": name, + "name_org": name_org, + "vol_path": vol_path, + "recycle_bin_admin_only": recycle_bin_admin_only, + "hidden": hidden, + "hide_unreadable": hide_unreadable, + "share_quota": share_quota, + }) + } + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + return self.request_data(api_name, api_path, req_param, method="post") + + def delete_folders(self, name: List[str]) -> dict: + """Delete folder(s) by name(s) + Parameters + ---------- + name List[str] + Share names. + + Returns + ------- + dict + Success. + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "delete", + "version": info['minVersion'], + "name": name + } + + return self.request_data(api_name, api_path, req_param) + + def clone(self, + name: str, name_org: str, vol_path: str, desc: str = "", hidden: bool = False, + enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, + hide_unreadable: bool = False, enable_share_cow: bool = False, + enable_share_compress: bool = False, share_quota: int = 0 + ) -> dict: + """Clone existing shared folder. + Parameters + ---------- + name : str + New shared folder name. + + name_org : str + Original shared folder name. + + vol_path : str + Volume path. + + desc : str, optional + Shared folder description. Defaults to `""`. + + hidden : bool, optional + Hide shared folder. Defaults to `False`. + + enable_recycle_bin : bool, optional + Enable recycle bin. Defaults to `True`. + + recycle_bin_admin_only : bool, optional + Recycle bin admin only. Defaults to `True`. + + hide_unreadable : bool, optional + Hide unreadable. Defaults to `False`. + + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + + share_quota : int, optional + Share quota. Defaults to `0`. + + Returns + ------- + dict + Name of the created shared folder + + Example return + -------------- + ```json + { + "data": { + "name": "test_shared_folder" + }, + "success": true, + ``` + """ + api_name = "SYNO.Core.Share" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "clone", + "version": info['maxVersion'], + "name": name, + } + + req_param_encrypted = { + "shareinfo": json.dumps({ + "desc": desc, + "enable_recycle_bin": enable_recycle_bin, + "enable_share_compress": enable_share_compress, + "enable_share_cow": enable_share_cow, + "name": name, + "name_org": name_org, + "vol_path": vol_path, + "recycle_bin_admin_only": recycle_bin_admin_only, + "hidden": hidden, + "hide_unreadable": hide_unreadable, + "share_quota": share_quota, + }) + } + + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + return self.request_data(api_name, api_path, req_param, method="post") + + + def get_folder_permission_by_name(self, + name: str, permission_substr: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, + user_group_type: str = "local_user" + ) -> dict: + """Retrieve share permissions for a given folder filtered by permission name (sub string) + Parameters + ---------- + name : str + The folder name to list permissions for. + + permission_substr : str + The substring to search for in the permissions. + + offset : int, optional + The offset to start at. Defaults to `0`. + + limit : int, optional + The maximum number of results to return. Defaults to `50`. + + is_unite_permission : bool, optional + Whether to return unified permissions. Defaults to `False`. + + with_inherit : bool, optional + Whether to include inherited permissions. Defaults to `False`. + + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + List of permission(s) on the folder + + Example return + -------------- + ```json + { + "data": { + "items": [ + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + } + ], + "total": 1 + }, + "success": true + } + ``` + """ + + api_name = "SYNO.Core.Share.Permission" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["minVersion"], + "method": "list", + "name": name, + "offset": offset, + "limit": limit, + "action": "find", + "substr": permission_substr, + "is_unite_permission": is_unite_permission, + "with_inherit": with_inherit, + "user_group_type": user_group_type, + } + return self.request_data(api_name, api_path, req_param, method="get") + + def get_folder_permissions(self, + name: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, + user_group_type: str = "local_user" + ) -> dict: + """Retrieve share permissions for a given folder. + Parameters + ---------- + name : str + The folder name to list permissions for. + + offset : int, optional + The offset to start at. Defaults to `0`. + + limit : int, optional + The maximum number of results to return. Defaults to `50`. + + is_unite_permission : bool, optional + Whether to return unified permissions. Defaults to `False`. + + with_inherit : bool, optional + Whether to include inherited permissions. Defaults to `False`. + + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + All permissions on the folder + + Example return + ---------- + ```json + { + "data": { + "items": [ + { + "inherit": "rw", + "is_admin": true, + "is_custom": false, + "is_deny": true, + "is_readonly": false, + "is_writable": false, + "name": "admin" + }, + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + }, + { + "inherit": "rw", + "is_admin": true, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": true, + "name": "test_api" + }, + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "test_test" + } + ], + "total": 5 + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Permission" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["minVersion"], + "method": "list", + "name": name, + "offset": offset, + "limit": limit, + "action": "enum", + "is_unite_permission": is_unite_permission, + "with_inherit": with_inherit, + "user_group_type": user_group_type, + } + return self.request_data(api_name, api_path, req_param, method="get") + + def set_folder_permissions(self, name: str, user_group_type: str, permissions: List[dict[str, object]]) -> dict: + """Set folder permissions for a given folder. + Parameters + ---------- + name : str + The folder name to set permissions for. + + user_group_type : str + The type of user group to set permissions for. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + permissions : dict + The permissions to set for the folder. + Example: + ```json + [ + { + "name":"guest", + "is_readonly":false, + "is_writable":true, + "is_deny":false, + "is_custom":false + } + ] + ``` + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Permission" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["minVersion"], + "method": "set", + "name": name, + "user_group_type": user_group_type, + "permissions": json.dumps(permissions), + } + return self.request_data(api_name, api_path, req_param, method="get") + + def get_local_group_permissions(self, group: str) -> dict: + """Retrieve share permissions for a given group. + Parameters + ---------- + group : str + The group to list permissions for. + + Returns + ------- + dict + Permissions of a group on Shared folders + + Example return + -------------- + ```json + { + "data": { + "shares": [ + { + "is_aclmode": true, + "is_custom": false, + "is_deny": true, + "is_mask": false, + "is_readonly": false, + "is_sync_share": false, + "is_unite_permission": false, + "is_writable": false, + "name": "ActiveBackupforBusiness", + "share_path": "/volume3/ActiveBackupforBusiness" + } + ], + "total": 1 + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Permission" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": 1, + "method": "list_by_group", + "name": group, + "user_group_type": "local_group", + "share_type": json.dumps( + ["dec", "local", "usb", "sata", "cluster", "c2", "cold_storage", "worm"] + ), + "additional": json.dumps(["hidden", "encryption", "is_aclmode"]), + } + return self.request_data(api_name, api_path, req_param) + + def set_local_group_permissions( + self, group: str, permissions: list[dict[str, Any]] + ) -> dict: + """Set group permissions for a given share. + Parameters + ---------- + group : str + The group to set the permissions for. + + permissions : list[dict[str, Any]] + The permissions to set for the group. + Example: + ``` + [ + { + "name": "web", + "is_readonly": False, + "is_writable": False, + "is_deny": True + }, + { + "name": "ActiveBackupforBusiness", + "is_readonly": False, + "is_writable": True, + "is_deny": False + } + ] + ``` + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Permission" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["minVersion"], + "method": "set_by_user_group", + "name": group, + "user_group_type": "local_group", + "permissions": json.dumps(permissions), + } + + return self.request_data(api_name, api_path, req_param) + +class KeyManagerStore(base_api.BaseApi): + """ + Core Share KeyManager Store API implementation. + """ + + def init(self) -> dict: + """Initialize KeyManagerStore API. + """ + + raise NotImplementedError("This method is not completly implemented yet. API return error 403") + + api_name = "SYNO.Core.Share.KeyManager.Store" + version = self.core_list[api_name]["maxVersion"] + api_path = self.core_list[api_name]["path"] + req_param = { + "version": version, + "method": "init", + "share_path": "/usr/syno/etc/.encrypt" + } + + req_param_encrypted = { + "passphrase": "", + } + + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + + return self.request_data(api_name, api_path, req_param, method="post") + + def verify(self) -> dict: + + raise NotImplementedError("This method is not implemented yet.") + + api_name = "SYNO.Core.Share.KeyManager.Store" + version = self.core_list[api_name]["maxVersion"] + api_path = self.core_list[api_name]["path"] + req_param = { + "version": version, + "method": "verify", + } + + req_param_encrypted = { + "passphrase": "", + } + + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + + return self.request_data(api_name, api_path, req_param, method="post") + + def explore(self) -> dict: + """Explore KeyManagerStore API. Get list of existing stores + Returns + ------- + dict + List of stores existing on the NAS + + Example return + -------------- + ```json + { + "data": { + "stores": [] + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.KeyManager.Store" + version = self.core_list[api_name]["minVersion"] + api_path = self.core_list[api_name]["path"] + req_param = { + "version": version, + "method": "explore", + } + + return self.request_data(api_name, api_path, req_param) + +class KeyManagerAutoKey(base_api.BaseApi): + """ + Core Share KeyManager AutoKey API implementation. + """ + + def list(self) -> dict: + """List KeyManagerStore API. + Returns + ------- + dict + List of keys in the manager + + Example return + -------------- + ```json + { + "data": { + "keys": [] + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.KeyManager.AutoKey" + version = self.core_list[api_name]["minVersion"] + api_path = self.core_list[api_name]["path"] + req_param = { + "version": version, + "method": "list", + } + + return self.request_data(api_name, api_path, req_param) + diff --git a/synology_api/DSM/ControlPanel/SynologyAccount.py b/synology_api/DSM/ControlPanel/SynologyAccount.py new file mode 100644 index 00000000..ab3084be --- /dev/null +++ b/synology_api/DSM/ControlPanel/SynologyAccount.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class SynologyAccount(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/TaskScheduler.py b/synology_api/DSM/ControlPanel/TaskScheduler.py new file mode 100644 index 00000000..53d4b3de --- /dev/null +++ b/synology_api/DSM/ControlPanel/TaskScheduler.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class TaskScheduler(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/TerminalSNMP.py b/synology_api/DSM/ControlPanel/TerminalSNMP.py new file mode 100644 index 00000000..6070b379 --- /dev/null +++ b/synology_api/DSM/ControlPanel/TerminalSNMP.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class TerminalSNMP(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/UpdateRestore.py b/synology_api/DSM/ControlPanel/UpdateRestore.py new file mode 100644 index 00000000..c0788c45 --- /dev/null +++ b/synology_api/DSM/ControlPanel/UpdateRestore.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class UpdateRestore(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/UserGroup.py b/synology_api/DSM/ControlPanel/UserGroup.py new file mode 100644 index 00000000..16fab3c1 --- /dev/null +++ b/synology_api/DSM/ControlPanel/UserGroup.py @@ -0,0 +1,4 @@ +from synology_api import base_api + +class UserGroup(base_api.BaseApi): + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/__init__.py b/synology_api/DSM/ControlPanel/__init__.py new file mode 100644 index 00000000..b6f1a801 --- /dev/null +++ b/synology_api/DSM/ControlPanel/__init__.py @@ -0,0 +1,219 @@ +from .ApplicationPrivileges import ApplicationPrivileges +from .DomainLDAP import DomainLDAP +from .ExternalAccess import ExternalAccess +from .ExternalDevices import ExternalDevices +from .FileServices import FileServices +from .HardwarePower import HardwarePower +from .IndexingService import IndexingService +from .InfoCenter import InfoCenter +from .LoginPortal import LoginPortal +from .Network import Network +from .Notifications import Notifications +from .RegionalOptions import RegionalOptions +from .Security import Security +from .SharedFolder import SharedFolder +from .SynologyAccount import SynologyAccount +from .TaskScheduler import TaskScheduler +from .Security import Security +from .TerminalSNMP import TerminalSNMP +from .UpdateRestore import UpdateRestore +from .UserGroup import UserGroup + +from synology_api import base_api + +class ControlPanel(base_api.BaseApi): + _app_priv = None + _domain_ldap = None + _ext_access = None + _ext_devices = None + _file_services = None + _hard_power = None + _idx_service = None + _info_center = None + _log_portal = None + _network = None + _notification = None + _region_opt = None + _security = None + _shared_folder = None + _syno_account = None + _task_scheduler = None + _terminal_snmp = None + _update_restore = None + _user_group = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + + @property + def ApplicationPrivileges(self): + if self._app_priv is None: + # Create ApplicationPrivileges instance without calling __init__ + self._app_priv = ApplicationPrivileges.__new__(ApplicationPrivileges) + # Share the state + self._app_priv.__dict__ = self.__dict__ + return self._app_priv + + @property + def DomainLDAP(self): + if self._domain_ldap is None: + # Create DomainLDAP instance without calling __init__ + self._domain_ldap = DomainLDAP.__new__(DomainLDAP) + # Share the state + self._domain_ldap.__dict__ = self.__dict__ + return self._domain_ldap + + @property + def ExternalAccess(self): + if self._ext_access is None: + # Create ExternalAccess instance without calling __init__ + self._ext_access = ExternalAccess.__new__(ExternalAccess) + # Share the state + self._ext_access.__dict__ = self.__dict__ + return self._ext_access + + @property + def ExternalDevices(self): + if self._ext_devices is None: + # Create ExternalDevices instance without calling __init__ + self._ext_devices = ExternalDevices.__new__(ExternalDevices) + # Share the state + self._ext_devices.__dict__ = self.__dict__ + return self._ext_devices + + @property + def FileServices(self): + if self._file_services is None: + # Create FileServices instance without calling __init__ + self._file_services = FileServices.__new__(FileServices) + # Share the state + self._file_services.__dict__ = self.__dict__ + return self._file_services + + @property + def HardwarePower(self): + if self._hard_power is None: + # Create HardwarePower instance without calling __init__ + self._app_priv = HardwarePower.__new__(HardwarePower) + # Share the state + self._hard_power.__dict__ = self.__dict__ + return self._hard_power + + @property + def IndexingService(self): + if self._idx_service is None: + # Create IndexingService instance without calling __init__ + self._idx_service = IndexingService.__new__(IndexingService) + # Share the state + self._idx_service.__dict__ = self.__dict__ + return self._idx_service + + @property + def InfoCenter(self): + if self._info_center is None: + # Create InfoCenter instance without calling __init__ + self._info_center = InfoCenter.__new__(InfoCenter) + # Share the state + self._info_center.__dict__ = self.__dict__ + return self._info_center + + @property + def LoginPortal(self): + if self._log_portal is None: + # Create LoginPortal instance without calling __init__ + self._log_portal = LoginPortal.__new__(LoginPortal) + # Share the state + self._log_portal.__dict__ = self.__dict__ + return self._log_portal + + @property + def Network(self): + if self._network is None: + # Create Network instance without calling __init__ + self._network = Network.__new__(Network) + # Share the state + self._network.__dict__ = self.__dict__ + return self._network + + @property + def Notifications(self): + if self._notification is None: + # Create Notifications instance without calling __init__ + self._notification = Notifications.__new__(Notifications) + # Share the state + self._notification.__dict__ = self.__dict__ + return self._notification + + @property + def RegionalOptions(self): + if self._region_opt is None: + # Create RegionalOptions instance without calling __init__ + self._region_opt = RegionalOptions.__new__(RegionalOptions) + # Share the state + self._region_opt.__dict__ = self.__dict__ + return self._region_opt + + @property + def Security(self): + if self._security is None: + # Create Security instance without calling __init__ + self._app_priv = Security.__new__(Security) + # Share the state + self._security.__dict__ = self.__dict__ + return self._security + + @property + def SharedFolder(self): + if self._shared_folder is None: + # Create SharedFolder instance without calling __init__ + self._shared_folder = SharedFolder.__new__(SharedFolder) + # Share the state + self._shared_folder.__dict__ = self.__dict__ + return self._shared_folder + + @property + def SynologyAccount(self): + if self._syno_account is None: + # Create ApplicationPrivileges instance without calling __init__ + self._syno_account = SynologyAccount.__new__(SynologyAccount) + # Share the state + self._syno_account.__dict__ = self.__dict__ + return self._syno_account + + @property + def TaskScheduler(self): + if self._task_scheduler is None: + # Create TaskScheduler instance without calling __init__ + self._task_scheduler = TaskScheduler.__new__(TaskScheduler) + # Share the state + self._task_scheduler.__dict__ = self.__dict__ + return self._task_scheduler + + @property + def TerminalSNMP(self): + if self._terminal_snmp is None: + # Create TerminalSNMP instance without calling __init__ + self._terminal_snmp = TerminalSNMP.__new__(TerminalSNMP) + # Share the state + self._terminal_snmp.__dict__ = self.__dict__ + return self._terminal_snmp + + @property + def UpdateRestore(self): + if self._update_restore is None: + # Create UpdateRestore instance without calling __init__ + self._update_restore = UpdateRestore.__new__(UpdateRestore) + # Share the state + self._update_restore.__dict__ = self.__dict__ + return self._update_restore + + @property + def UserGroup(self): + if self._user_group is None: + # Create UserGroup instance without calling __init__ + self._user_group = UserGroup.__new__(UserGroup) + # Share the state + self._user_group.__dict__ = self.__dict__ + return self._user_group + \ No newline at end of file diff --git a/synology_api/DSM/FileStation.py b/synology_api/DSM/FileStation.py new file mode 100644 index 00000000..8fc373b8 --- /dev/null +++ b/synology_api/DSM/FileStation.py @@ -0,0 +1,1287 @@ +from __future__ import annotations +from typing import Optional, Any +import os +import io +import time +from datetime import datetime + +import requests +import tqdm +from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor +import sys +from urllib import parse +from treelib import Tree +from synology_api import base_api + + +class FileStation(base_api.BaseApi): + + def __init__(self, + ip_address: str, + port: str, + username: str, + password: str, + secure: bool = False, + cert_verify: bool = False, + dsm_version: int = 7, + debug: bool = True, + otp_code: Optional[str] = None, + device_id: Optional[str] = None, + device_name: Optional[str] = None, + interactive_output: bool = True + ) -> None: + + super(FileStation, self).__init__(ip_address, port, username, password, secure, cert_verify, + dsm_version, debug, otp_code, device_id, device_name, 'FileStation') + + self._dir_taskid: str = '' + self._dir_taskid_list: list[str] = [] + self._md5_calc_taskid: str = '' + self._md5_calc_taskid_list: list[str] = [] + self._search_taskid: str = '' + self._search_taskid_list: list[str] = [] + self._copy_move_taskid: str = '' + self._copy_move_taskid_list: list[str] = [] + self._delete_taskid: str = '' + self._delete_taskid_list: list[str] = [] + self._extract_taskid: str = '' + self._extract_taskid_list: list[str] = [] + self._compress_taskid: str = '' + self._compress_taskid_list: list[str] = [] + + self.session.get_api_list('FileStation') + + self.file_station_list: Any = self.session.app_api_list + + self.interactive_output: bool = interactive_output + + def get_info(self) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Info' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'get'} + + return self.request_data(api_name, api_path, req_param) + + def get_list_share(self, + additional: Optional[str | list[str]] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + onlywritable: bool = False + ) -> dict[str, object] | str: + + api_name = 'SYNO.FileStation.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list_share'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: + if val is not None: + req_param[str(key)] = val + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = ','.join(additional) + + req_param['additional'] = additional + + return self.request_data(api_name, api_path, req_param) + + def get_file_list(self, + folder_path: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + pattern: Optional[str] = None, + filetype: Optional[str] = None, + goto_path: Optional[str] = None, + additional: Optional[str | list[str]] = None) -> dict[str, object] | str: + + api_name = 'SYNO.FileStation.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: + if val is not None: + req_param[str(key)] = val + + if folder_path is None: + return 'Enter a valid folder_path' + + if filetype is not None: + req_param['filetype'] = str(req_param['filetype']).lower() + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = ','.join(additional) + + req_param['additional'] = additional + + return self.request_data(api_name, api_path, req_param) + + def get_file_info(self, + path: Optional[str] = None, + additional: Optional[str | list[str]] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'getinfo'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = str(additional).replace("'", '"') + + req_param['additional'] = additional + + return self.request_data(api_name, api_path, req_param) + + # TODO all working if specify extension check if correct [pattern, extension] + # it works if you put extension='...' + + def search_start(self, + folder_path: Optional[str] = None, + recursive: Optional[bool] = None, + pattern: Optional[str] = None, + extension: Optional[str] = None, + filetype: Optional[str] = None, + size_from: Optional[int] = None, + size_to: Optional[int] = None, + mtime_from: Optional[str | int] = None, + mtime_to: Optional[str | int] = None, + crtime_from: Optional[str | int] = None, + crtime_to: Optional[str | int] = None, + atime_from: Optional[str | int] = None, + atime_to: Optional[str | int] = None, + owner: Optional[str] = None, + group: Optional[str] = None + ) -> dict[str, object] | str: + + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start', 'folder_path': ''} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param'] and 'time' not in key: + if val is not None: + req_param[str(key)] = val + if 'time' in key: + if val is not None: + try: + date = time.strptime(val, "%Y-%m-%d %H:%M:%S") + timestamp = time.mktime(date) + req_param[key] = '"' + str(timestamp) + '"' + except ValueError: + try: + datetime.fromtimestamp(int(val)).strftime('%Y-%m-%d %H:%M:%S') + req_param[key] = '"' + val + '"' + except ValueError: + return 'Enter the correct Date Time format "YYY-MM-DD HH:MM:SS" or Unix timestamp' + + if folder_path is None: + return 'Enter a valid folder_path' + else: + req_param['folder_path'] = '"' + folder_path + '"' + + if filetype is not None: + req_param['filetype'] = '"' + filetype + '"' + + response = self.request_data(api_name, api_path, req_param) + + taskid = response['data']['taskid'] + self._search_taskid = '"{}"'.format(taskid) + self._search_taskid_list.append('"' + response['data']['taskid'] + '"') + + message = ('You can now check the status of request with ' + 'get_search_list() , your id is: ' + self._search_taskid) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": taskid} + + return output + + def get_search_list(self, + task_id: str, + filetype: Optional[str] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + offset: Optional[int] = None, + additional: Optional[str | list[str]] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list', 'taskid': ''} + + if task_id is None: + return 'Enter a correct taskid, choose one of the following: ' + str(self._search_taskid_list) + else: + req_param['taskid'] = task_id + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional', 'task_id']: + if val is not None: + req_param[str(key)] = val + + if filetype is not None: + req_param['filetype'] = str(filetype).lower() + + if additional is None: + additional = ['size', 'owner', 'time'] + + if type(additional) is list: + additional = '","'.join(additional) + + req_param['additional'] = '["' + additional + '"]' + + return self.request_data(api_name, api_path, req_param) + + def stop_search_task(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': self._search_taskid} + + if taskid is None: + return 'Enter a valid taskid, choose between ' + str(self._search_taskid_list) + + self._search_taskid_list.remove(taskid) + + return self.request_data(api_name, api_path, req_param) + + def stop_all_search_task(self) -> str: + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': ''} + + assert len(self._search_taskid_list), 'Task list is empty' + str(self._search_taskid_list) + + for task_id in self._search_taskid_list: + req_param['taskid'] = task_id + self.request_data(api_name, api_path, req_param) + + self._search_taskid_list = [] + + return 'All task are stopped' + + def get_mount_point_list(self, + mount_type: Optional[str] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + additional: Optional[str | list[str]] = None + ) -> dict[str, object] | str: + + api_name = 'SYNO.FileStation.VirtualFolder' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list'} + + if mount_type is not None: + req_param['type'] = mount_type + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional', 'mount_type']: + if val is not None: + req_param[str(key)] = val + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = ','.join(additional) + + req_param['additional'] = additional + + return self.request_data(api_name, api_path, req_param) + + def get_favorite_list(self, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + status_filter: Optional[str] = None, + additional: Optional[str | list[str]] = None + ) -> dict[str, object] | str: + + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: + if val is not None: + req_param[str(key)] = val + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = ','.join(additional) + + req_param['additional'] = additional + + return self.request_data(api_name, api_path, req_param) + + def add_a_favorite(self, + path: str, + name: Optional[str] = None, + index: Optional[int] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'add'} + + if path is None: + return 'Enter a valid path' + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + return self.request_data(api_name, api_path, req_param) + + def delete_a_favorite(self, path: Optional[str] = None) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'delete'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + return self.request_data(api_name, api_path, req_param) + + def clear_broken_favorite(self) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'clear_broken'} + + return self.request_data(api_name, api_path, req_param) + + def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'edit'} + + if path is None: + return 'Enter a valid path' + else: + req_param['path'] = path + + if new_name is None: + return 'Enter a valid new_name' + else: + req_param['new_name'] = new_name + + return self.request_data(api_name, api_path, req_param) + + def replace_all_favorite(self, path: str | list[str], name: str | list[str]): + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'edit'} + + if type(path) is list: + path = ','.join(path) + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid path' + + if type(name) is list: + name = ','.join(name) + req_param['name'] = name + elif name is not None: + req_param['name'] = name + else: + return 'Enter a valid name' + + return self.request_data(api_name, api_path, req_param) + + def start_dir_size_calc(self, path: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid path' + + taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] + + response_id = '"{}"'.format(taskid) + self._dir_taskid = response_id + self._dir_taskid_list.append(response_id) + + message = ('You can now check the status of request ' + 'with get_dir_status() , your id is: ' + + response_id) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": taskid} + + return output + + def stop_dir_size_calc(self, taskid: str) -> str: + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': taskid} + + if taskid is None: + return 'Enter a valid taskid choose between: ' + str(self._dir_taskid_list) + else: + req_param['taskid'] = '"' + taskid + '"' + + self.request_data(api_name, api_path, req_param) + self._dir_taskid_list.remove('"' + taskid + '"') + + return 'The task has been stopped' + + def get_dir_status(self, taskid: Optional[str] = None) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'status', 'taskid': taskid} + + if taskid is None and self._dir_taskid != '': + return 'Choose a taskid from this list: ' + str(self._dir_taskid) + + return self.request_data(api_name, api_path, req_param) + + def start_md5_calc(self, file_path: str) -> str | dict[str, object]: + api_name = 'SYNO.FileStation.MD5' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start'} + + if file_path is None: + return 'Enter a correct file_path' + else: + req_param['file_path'] = file_path + + self._md5_calc_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] + self._md5_calc_taskid_list.append(self._md5_calc_taskid) + + message = ('You can now check the status of request with ' + 'get_md5_status() , your id is: ' + self._md5_calc_taskid) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": self._md5_calc_taskid} + + return output + + def get_md5_status(self, taskid: Optional[str] = None) -> str | dict[str, object]: + api_name = 'SYNO.FileStation.MD5' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'status'} + + if taskid is None and self._md5_calc_taskid != '': + req_param['taskid'] = '"{taskid}"'.format(taskid=self._md5_calc_taskid) + elif taskid is not None: + req_param['taskid'] = '"{taskid}"'.format(taskid=taskid) + else: + return 'Did you run start_md5_calc() first? No task id found! ' + str(self._md5_calc_taskid) + + return self.request_data(api_name, api_path, req_param) + + def stop_md5_calc(self, taskid: str) -> str: + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': taskid} + + if taskid is None: + return 'Enter a valid taskid choose between: ' + str(self._md5_calc_taskid_list) + else: + req_param['taskid'] = '"' + taskid + '"' + + self.request_data(api_name, api_path, req_param) + self._md5_calc_taskid_list.remove(taskid) + + return 'The task has been stopped' + + def check_permissions(self, + path: str, + filename: str, + overwrite: Optional[bool] = None, + create_only: Optional[bool] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.CheckPermission' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'write'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + if path is None: + return 'Enter a valid path' + + if filename is None: + return 'Enter a valid name' + + return self.request_data(api_name, api_path, req_param) + + def upload_file(self, + dest_path: str, + file_path: str, + create_parents: bool = True, + overwrite: bool = True, + verify: bool = False, + progress_bar: bool = True + ) -> str | tuple[int, dict[str, object]]: + api_name = 'SYNO.FileStation.Upload' + info = self.gen_list[api_name] + api_path = info['path'] + filename = os.path.basename(file_path) + + session = requests.session() + + with open(file_path, 'rb') as payload: + url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=upload&_sid=%s' % ( + api_name, info['minVersion'], self._sid) + + encoder = MultipartEncoder({ + 'path': dest_path, + 'create_parents': str(create_parents).lower(), + 'overwrite': str(overwrite).lower(), + 'files': (filename, payload, 'application/octet-stream') + }) + + if progress_bar: + bar = tqdm.tqdm(desc='Upload Progress', + total=encoder.len, + dynamic_ncols=True, + unit='B', + unit_scale=True, + unit_divisor=1024 + ) + + monitor = MultipartEncoderMonitor(encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) + + r = session.post( + url, + data=monitor, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': monitor.content_type} + ) + + else: + r = session.post( + url, + data=encoder, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': encoder.content_type} + ) + + session.close() + if r.status_code != 200 or not r.json()['success']: + return r.status_code, r.json() + + return r.json() + + def get_shared_link_info(self, link_id: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'getinfo'} + + if link_id is None: + return 'Enter a valid id' + else: + req_param['id'] = link_id + + return self.request_data(api_name, api_path, req_param) + + def get_shared_link_list(self, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + force_clean: Optional[bool] = None + ) -> dict[str, object] | str: + + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + return self.request_data(api_name, api_path, req_param) + + def create_sharing_link(self, + path: str, + password: Optional[str] = None, + date_expired: Optional[str | int] = None, + date_available: Optional[str | int] = None, + expire_times: int = 0 + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'create'} + + if date_expired: + if str(date_expired)[0] != '"': + date_expired = '"' + str(date_expired) + '"' + if date_available: + if str(date_available)[0] != '"': + date_available = '"' + str(date_available) + '"' + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + if path is None: + return 'Enter a valid path' + + return self.request_data(api_name, api_path, req_param) + + def delete_shared_link(self, link_id: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'delete'} + + if link_id is None: + return 'Enter a valid id' + else: + req_param['id'] = link_id + + return self.request_data(api_name, api_path, req_param) + + def clear_invalid_shared_link(self) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'clear_invalid'} + + return self.request_data(api_name, api_path, req_param) + + def edit_shared_link(self, + link_id: str, + password: Optional[str] = None, + date_expired: Optional[str | int] = None, + date_available: Optional[str | int] = None, + expire_times: int = 0 + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'edit'} + + if date_expired: + if str(date_expired)[0] != '"': + date_expired = '"' + str(date_expired) + '"' + if date_available: + if str(date_available)[0] != '"': + date_available = '"' + str(date_available) + '"' + + if link_id is None: + return 'Enter a valid id' + else: + req_param['id'] = link_id + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + return self.request_data(api_name, api_path, req_param) + + def create_folder(self, + folder_path: str | list[str], + name: str | list[str], + force_parent: Optional[bool] = None, + additional: Optional[str | list[str]] = None + ) -> str | dict[str, object]: + api_name = 'SYNO.FileStation.CreateFolder' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'create'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'folder_path', 'additional', 'name']: + if val is not None: + req_param[str(key)] = val + + if type(folder_path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in folder_path] + folder_path = new_path + folder_path = '[' + ','.join(folder_path) + ']' + req_param['folder_path'] = folder_path + elif folder_path is not None: + req_param['folder_path'] = folder_path + else: + return 'Enter a valid path' + + if type(name) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in name] + name = new_path + name = '[' + ','.join(name) + ']' + req_param['name'] = name + elif name is not None: + req_param['name'] = '"' + name + '"' + else: + return 'Enter a valid path' + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = ','.join(additional) + + req_param['additional'] = additional + + return self.request_data(api_name, api_path, req_param) + + def rename_folder(self, + path: str | list[str], + name: str | list[str], + additional: Optional[str | list[str]] = None, + search_taskid: Optional[str] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Rename' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'rename'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid folder path (folder path only ex. "/home/Drive/Downloads")' + + if type(name) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in name] + name = new_path + name = '[' + ','.join(name) + ']' + req_param['name'] = name + elif name is not None: + req_param['name'] = name + else: + return 'Enter a valid new folder name (new folder name only ex. "New Folder")' + + if additional is None: + additional = ['real_path', 'size', 'owner', 'time'] + + if type(additional) is list: + additional = ','.join(additional) + + req_param['additional'] = additional + + if search_taskid is not None: + req_param['search_taskid'] = search_taskid + + return self.request_data(api_name, api_path, req_param) + + def start_copy_move(self, + path: str | list[str], + dest_folder_path: str | list[str], + overwrite: Optional[bool] = None, + remove_src: Optional[bool] = None, + accurate_progress: Optional[bool] = None, + search_taskid: Optional[str] = None + ) -> str | dict[str, object]: + api_name = 'SYNO.FileStation.CopyMove' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid path' + + if type(dest_folder_path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in dest_folder_path] + dest_folder_path = new_path + dest_folder_path = '[' + ','.join(dest_folder_path) + ']' + req_param['name'] = dest_folder_path + elif dest_folder_path is not None: + req_param['dest_folder_path'] = dest_folder_path + else: + return 'Enter a valid path' + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'path', 'additional', + 'dest_folder_path', 'new_path']: + if val is not None: + req_param[str(key)] = val + + self._copy_move_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] + self._dir_taskid_list.append(self._copy_move_taskid) + + message = ('You can now check the status of request with ' + 'get_copy_move_status() , your id is: ' + + self._copy_move_taskid) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": self._copy_move_taskid} + + return output + + def get_copy_move_status(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.CopyMove' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'status'} + + if taskid is None: + return 'Enter a valid taskid choose between ' + str(self._copy_move_taskid_list) + else: + req_param['taskid'] = '"' + taskid + '"' + + return self.request_data(api_name, api_path, req_param) + + def stop_copy_move_task(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.CopyMove' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop'} + + if taskid is None: + return 'Enter a valid taskid choose between ' + str(self._copy_move_taskid_list) + else: + req_param['taskid'] = taskid + + self._copy_move_taskid_list.remove(taskid) + + return self.request_data(api_name, api_path, req_param) + + def start_delete_task(self, + path: str | list[str], + accurate_progress: Optional[bool] = None, + recursive: Optional[bool] = None, + search_taskid: Optional[str] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid path' + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'path', 'new_path']: + if val is not None: + req_param[str(key)] = val + + self._delete_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] + self._delete_taskid_list.append(self._delete_taskid) + + message = ('You can now check the status of request with ' + 'get_delete_status() , task id is: ' + + self._delete_taskid) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": self._delete_taskid} + + return output + + def get_delete_status(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'status'} + + if taskid is None: + return 'Enter a valid taskid, choose between ' + str(self._delete_taskid_list) + else: + req_param['taskid'] = taskid + + return self.request_data(api_name, api_path, req_param) + + def stop_delete_task(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop'} + + if taskid is None: + return 'Enter a valid taskid, choose between ' + str(self._delete_taskid_list) + else: + req_param['taskid'] = taskid + + self._delete_taskid_list.remove('"' + taskid + '"') + + return self.request_data(api_name, api_path, req_param) + + def delete_blocking_function(self, + path: str, + recursive: Optional[bool] = None, + search_taskid: Optional[str] = None) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'delete'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid path' + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'path', 'new_path']: + if val is not None: + req_param[str(key)] = val + + 'This function will stop your script until done! Do not interrupt ' + + return self.request_data(api_name, api_path, req_param) + + def start_extract_task(self, + file_path: str, + dest_folder_path: str, + overwrite: Optional[bool] = None, + keep_dir: Optional[bool] = None, + create_subfolder: Optional[bool] = None, + codepage: Optional[str] = None, + password: Optional[str] = None, + item_id: Optional[str] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start', 'file_path': file_path, + 'dest_folder_path': dest_folder_path} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + if file_path is None: + return 'Enter a valid file_path' + + if dest_folder_path is None: + return 'Enter a valid dest_folder_path' + + self._extract_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] + self._extract_taskid_list.append(self._extract_taskid) + + message = ('You can now check the status of request with ' + 'get_extract_status() , your id is: ' + + self._extract_taskid) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": self._extract_taskid} + + return output + + def get_extract_status(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'status'} + + if taskid is None: + return 'Enter a valid taskid, choose between ' + str(self._extract_taskid_list) + else: + req_param['taskid'] = taskid + + return self.request_data(api_name, api_path, req_param) + + def stop_extract_task(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop'} + + if taskid is None: + return 'Enter a valid taskid, choose between ' + str(self._extract_taskid_list) + else: + req_param['taskid'] = taskid + + self._extract_taskid_list.remove(taskid) + + return self.request_data(api_name, api_path, req_param) + + def get_file_list_of_archive(self, + file_path: str, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + codepage: Optional[str] = None, + password: Optional[str] = None, + item_id: Optional[str] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + if file_path is None: + return 'Enter a valid file_path' + + return self.request_data(api_name, api_path, req_param) + + def start_file_compression(self, + path: str | list[str], + dest_file_path: str, + level: Optional[int] = None, + mode: Optional[str] = None, + compress_format: Optional[str] = None, + password: Optional[str] = None + ) -> dict[str, object] | str | tuple[str]: + api_name = 'SYNO.FileStation.Compress' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'start'} + + if type(path) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in path] + path = new_path + path = '[' + ','.join(path) + ']' + req_param['path'] = path + elif path is not None: + req_param['path'] = path + else: + return 'Enter a valid path' + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'compress_format', '_password', '_api_path', + 'req_param', 'path', 'new_path']: + if val is not None: + req_param[str(key)] = val + + if dest_file_path is None: + return 'Enter a valid dest_file_path' + + if compress_format is not None: + req_param['format'] = compress_format + + if password is not None: + req_param['_password'] = password + + self._compress_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] + + message = ('You can now check the status of request with ' + 'get_compress_status() , your id is: ' + + self._compress_taskid) + if self.interactive_output: + output = message + else: + output = {"message": message, "taskid": self._compress_taskid} + + return output + + def get_compress_status(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Compress' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'status'} + + if taskid is None: + return 'Enter a valid taskid' + else: + req_param['taskid'] = taskid + + return self.request_data(api_name, api_path, req_param) + + def stop_compress_task(self, taskid: str) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.Compress' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'stop'} + + if taskid is None: + return 'Enter a valid taskid' + else: + req_param['taskid'] = taskid + + return self.request_data(api_name, api_path, req_param) + + def get_list_of_all_background_task(self, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + api_filter: Optional[str] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.FileStation.BackgroundTask' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'list'} + + for key, val in locals().items(): + if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: + if val is not None: + req_param[str(key)] = val + + if type(api_filter) is list: + new_path = [] + [new_path.append('"' + x + '"') for x in api_filter] + api_filter = new_path + api_filter = '[' + ','.join(api_filter) + ']' + req_param['api_filter'] = api_filter + + return self.request_data(api_name, api_path, req_param) + + def get_file(self, + path: str, + mode: str, + dest_path: str = ".", + chunk_size: int = 8192, + verify: bool = False + ) -> Optional[str]: + + api_name = 'SYNO.FileStation.Download' + info = self.gen_list[api_name] + api_path = info['path'] + + if path is None: + return 'Enter a valid path' + + session = requests.session() + + url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=download&path=%s&mode=%s&_sid=%s' % ( + api_name, info['maxVersion'], parse.quote_plus(path), mode, self._sid) + + if mode is None: + return 'Enter a valid mode (open / download)' + + if mode == r'open': + with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: + r.raise_for_status() + for chunk in r.iter_content(chunk_size=chunk_size): + if chunk: # filter out keep-alive new chunks + sys.stdout.buffer.write(chunk) + + if mode == r'download': + with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: + r.raise_for_status() + if not os.path.isdir(dest_path): + os.makedirs(dest_path) + with open(dest_path + "/" + os.path.basename(path), 'wb') as f: + for chunk in r.iter_content(chunk_size=chunk_size): + if chunk: # filter out keep-alive new chunks + f.write(chunk) + + if mode == r'serve': + with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: + r.raise_for_status() + return io.BytesIO(r.content) + + def generate_file_tree(self, folder_path: str, tree: Tree) -> None: + """Generate the file tree based on the folder path you give, you need to create the root node before call this function + + Parameters + ---------- + folder_path : str + Folder path to generate file tree + tree : Tree + Instance of the Tree of lib "Treelib" + + """ + data: dict = self.get_file_list( + folder_path=folder_path + ).get("data") + + files = data.get("files") + file: dict + for file in files: + file_name: str = file.get("name") + file_path: str = file.get("path") + if file.get("isdir"): + + tree.create_node(file_name, file_path, parent=folder_path) + self.generate_file_tree(file_path, tree) + else: + tree.create_node(file_name, file_path, parent=folder_path) + + +# TODO SYNO.FileStation.Thumb to be done diff --git a/synology_api/DSM/__init__.py b/synology_api/DSM/__init__.py new file mode 100644 index 00000000..ef9ed683 --- /dev/null +++ b/synology_api/DSM/__init__.py @@ -0,0 +1,30 @@ +from .ControlPanel import ControlPanel +from .FileStation import FileStation + +from synology_api import base_api + +class DSM(base_api.BaseApi): + _ctrl_panel = None + _file_station = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + + @property + def ControlPanel(self): + if self._ctrl_panel is None: + # Create ControlPanel instance without calling __init__ + self._ctrl_panel = ControlPanel.__new__(ControlPanel) + # Share the state + self._ctrl_panel.__dict__ = self.__dict__ + return self._ctrl_panel + + @property + def FileStation(self): + if self._file_station is None: + # Create FileStation instance without calling __init__ + self._file_station = FileStation.__new__(FileStation) + # Share the state + self._file_station.__dict__ = self.__dict__ + return self._file_station \ No newline at end of file From d06ea2e10fd4b9c0fe5ee8cd037f5ed65d174276 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 2 Mar 2025 23:38:57 +0100 Subject: [PATCH 002/126] Move packages implementations in folder Package Implementation of FileStation completed with documentation --- synology_api/DSM/ControlPanel/SharedFolder.py | 1 - synology_api/DSM/FileStation.py | 1287 --------- synology_api/DSM/Package/FileStation.py | 2518 +++++++++++++++++ synology_api/DSM/Package/PackageCenter.py | 1078 +++++++ synology_api/DSM/Package/__init__.py | 2 + synology_api/DSM/__init__.py | 15 +- synology_api/__init__.py | 27 +- synology_api/error_codes.py | 31 + 8 files changed, 3668 insertions(+), 1291 deletions(-) delete mode 100644 synology_api/DSM/FileStation.py create mode 100644 synology_api/DSM/Package/FileStation.py create mode 100644 synology_api/DSM/Package/PackageCenter.py create mode 100644 synology_api/DSM/Package/__init__.py diff --git a/synology_api/DSM/ControlPanel/SharedFolder.py b/synology_api/DSM/ControlPanel/SharedFolder.py index d6576ece..632c9a4d 100644 --- a/synology_api/DSM/ControlPanel/SharedFolder.py +++ b/synology_api/DSM/ControlPanel/SharedFolder.py @@ -389,7 +389,6 @@ def clone(self, return self.request_data(api_name, api_path, req_param, method="post") - def get_folder_permission_by_name(self, name: str, permission_substr: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, user_group_type: str = "local_user" diff --git a/synology_api/DSM/FileStation.py b/synology_api/DSM/FileStation.py deleted file mode 100644 index 8fc373b8..00000000 --- a/synology_api/DSM/FileStation.py +++ /dev/null @@ -1,1287 +0,0 @@ -from __future__ import annotations -from typing import Optional, Any -import os -import io -import time -from datetime import datetime - -import requests -import tqdm -from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor -import sys -from urllib import parse -from treelib import Tree -from synology_api import base_api - - -class FileStation(base_api.BaseApi): - - def __init__(self, - ip_address: str, - port: str, - username: str, - password: str, - secure: bool = False, - cert_verify: bool = False, - dsm_version: int = 7, - debug: bool = True, - otp_code: Optional[str] = None, - device_id: Optional[str] = None, - device_name: Optional[str] = None, - interactive_output: bool = True - ) -> None: - - super(FileStation, self).__init__(ip_address, port, username, password, secure, cert_verify, - dsm_version, debug, otp_code, device_id, device_name, 'FileStation') - - self._dir_taskid: str = '' - self._dir_taskid_list: list[str] = [] - self._md5_calc_taskid: str = '' - self._md5_calc_taskid_list: list[str] = [] - self._search_taskid: str = '' - self._search_taskid_list: list[str] = [] - self._copy_move_taskid: str = '' - self._copy_move_taskid_list: list[str] = [] - self._delete_taskid: str = '' - self._delete_taskid_list: list[str] = [] - self._extract_taskid: str = '' - self._extract_taskid_list: list[str] = [] - self._compress_taskid: str = '' - self._compress_taskid_list: list[str] = [] - - self.session.get_api_list('FileStation') - - self.file_station_list: Any = self.session.app_api_list - - self.interactive_output: bool = interactive_output - - def get_info(self) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Info' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'get'} - - return self.request_data(api_name, api_path, req_param) - - def get_list_share(self, - additional: Optional[str | list[str]] = None, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - onlywritable: bool = False - ) -> dict[str, object] | str: - - api_name = 'SYNO.FileStation.List' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list_share'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: - if val is not None: - req_param[str(key)] = val - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = ','.join(additional) - - req_param['additional'] = additional - - return self.request_data(api_name, api_path, req_param) - - def get_file_list(self, - folder_path: Optional[str] = None, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - pattern: Optional[str] = None, - filetype: Optional[str] = None, - goto_path: Optional[str] = None, - additional: Optional[str | list[str]] = None) -> dict[str, object] | str: - - api_name = 'SYNO.FileStation.List' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: - if val is not None: - req_param[str(key)] = val - - if folder_path is None: - return 'Enter a valid folder_path' - - if filetype is not None: - req_param['filetype'] = str(req_param['filetype']).lower() - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = ','.join(additional) - - req_param['additional'] = additional - - return self.request_data(api_name, api_path, req_param) - - def get_file_info(self, - path: Optional[str] = None, - additional: Optional[str | list[str]] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.List' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'getinfo'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = str(additional).replace("'", '"') - - req_param['additional'] = additional - - return self.request_data(api_name, api_path, req_param) - - # TODO all working if specify extension check if correct [pattern, extension] - # it works if you put extension='...' - - def search_start(self, - folder_path: Optional[str] = None, - recursive: Optional[bool] = None, - pattern: Optional[str] = None, - extension: Optional[str] = None, - filetype: Optional[str] = None, - size_from: Optional[int] = None, - size_to: Optional[int] = None, - mtime_from: Optional[str | int] = None, - mtime_to: Optional[str | int] = None, - crtime_from: Optional[str | int] = None, - crtime_to: Optional[str | int] = None, - atime_from: Optional[str | int] = None, - atime_to: Optional[str | int] = None, - owner: Optional[str] = None, - group: Optional[str] = None - ) -> dict[str, object] | str: - - api_name = 'SYNO.FileStation.Search' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start', 'folder_path': ''} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param'] and 'time' not in key: - if val is not None: - req_param[str(key)] = val - if 'time' in key: - if val is not None: - try: - date = time.strptime(val, "%Y-%m-%d %H:%M:%S") - timestamp = time.mktime(date) - req_param[key] = '"' + str(timestamp) + '"' - except ValueError: - try: - datetime.fromtimestamp(int(val)).strftime('%Y-%m-%d %H:%M:%S') - req_param[key] = '"' + val + '"' - except ValueError: - return 'Enter the correct Date Time format "YYY-MM-DD HH:MM:SS" or Unix timestamp' - - if folder_path is None: - return 'Enter a valid folder_path' - else: - req_param['folder_path'] = '"' + folder_path + '"' - - if filetype is not None: - req_param['filetype'] = '"' + filetype + '"' - - response = self.request_data(api_name, api_path, req_param) - - taskid = response['data']['taskid'] - self._search_taskid = '"{}"'.format(taskid) - self._search_taskid_list.append('"' + response['data']['taskid'] + '"') - - message = ('You can now check the status of request with ' - 'get_search_list() , your id is: ' + self._search_taskid) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": taskid} - - return output - - def get_search_list(self, - task_id: str, - filetype: Optional[str] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - offset: Optional[int] = None, - additional: Optional[str | list[str]] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Search' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list', 'taskid': ''} - - if task_id is None: - return 'Enter a correct taskid, choose one of the following: ' + str(self._search_taskid_list) - else: - req_param['taskid'] = task_id - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional', 'task_id']: - if val is not None: - req_param[str(key)] = val - - if filetype is not None: - req_param['filetype'] = str(filetype).lower() - - if additional is None: - additional = ['size', 'owner', 'time'] - - if type(additional) is list: - additional = '","'.join(additional) - - req_param['additional'] = '["' + additional + '"]' - - return self.request_data(api_name, api_path, req_param) - - def stop_search_task(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Search' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': self._search_taskid} - - if taskid is None: - return 'Enter a valid taskid, choose between ' + str(self._search_taskid_list) - - self._search_taskid_list.remove(taskid) - - return self.request_data(api_name, api_path, req_param) - - def stop_all_search_task(self) -> str: - api_name = 'SYNO.FileStation.Search' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': ''} - - assert len(self._search_taskid_list), 'Task list is empty' + str(self._search_taskid_list) - - for task_id in self._search_taskid_list: - req_param['taskid'] = task_id - self.request_data(api_name, api_path, req_param) - - self._search_taskid_list = [] - - return 'All task are stopped' - - def get_mount_point_list(self, - mount_type: Optional[str] = None, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - additional: Optional[str | list[str]] = None - ) -> dict[str, object] | str: - - api_name = 'SYNO.FileStation.VirtualFolder' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list'} - - if mount_type is not None: - req_param['type'] = mount_type - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional', 'mount_type']: - if val is not None: - req_param[str(key)] = val - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = ','.join(additional) - - req_param['additional'] = additional - - return self.request_data(api_name, api_path, req_param) - - def get_favorite_list(self, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - status_filter: Optional[str] = None, - additional: Optional[str | list[str]] = None - ) -> dict[str, object] | str: - - api_name = 'SYNO.FileStation.Favorite' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: - if val is not None: - req_param[str(key)] = val - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = ','.join(additional) - - req_param['additional'] = additional - - return self.request_data(api_name, api_path, req_param) - - def add_a_favorite(self, - path: str, - name: Optional[str] = None, - index: Optional[int] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Favorite' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'add'} - - if path is None: - return 'Enter a valid path' - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - return self.request_data(api_name, api_path, req_param) - - def delete_a_favorite(self, path: Optional[str] = None) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Favorite' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'delete'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - return self.request_data(api_name, api_path, req_param) - - def clear_broken_favorite(self) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Favorite' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'clear_broken'} - - return self.request_data(api_name, api_path, req_param) - - def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Favorite' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'edit'} - - if path is None: - return 'Enter a valid path' - else: - req_param['path'] = path - - if new_name is None: - return 'Enter a valid new_name' - else: - req_param['new_name'] = new_name - - return self.request_data(api_name, api_path, req_param) - - def replace_all_favorite(self, path: str | list[str], name: str | list[str]): - api_name = 'SYNO.FileStation.Favorite' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'edit'} - - if type(path) is list: - path = ','.join(path) - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid path' - - if type(name) is list: - name = ','.join(name) - req_param['name'] = name - elif name is not None: - req_param['name'] = name - else: - return 'Enter a valid name' - - return self.request_data(api_name, api_path, req_param) - - def start_dir_size_calc(self, path: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.DirSize' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid path' - - taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] - - response_id = '"{}"'.format(taskid) - self._dir_taskid = response_id - self._dir_taskid_list.append(response_id) - - message = ('You can now check the status of request ' - 'with get_dir_status() , your id is: ' - + response_id) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": taskid} - - return output - - def stop_dir_size_calc(self, taskid: str) -> str: - api_name = 'SYNO.FileStation.DirSize' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': taskid} - - if taskid is None: - return 'Enter a valid taskid choose between: ' + str(self._dir_taskid_list) - else: - req_param['taskid'] = '"' + taskid + '"' - - self.request_data(api_name, api_path, req_param) - self._dir_taskid_list.remove('"' + taskid + '"') - - return 'The task has been stopped' - - def get_dir_status(self, taskid: Optional[str] = None) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.DirSize' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'status', 'taskid': taskid} - - if taskid is None and self._dir_taskid != '': - return 'Choose a taskid from this list: ' + str(self._dir_taskid) - - return self.request_data(api_name, api_path, req_param) - - def start_md5_calc(self, file_path: str) -> str | dict[str, object]: - api_name = 'SYNO.FileStation.MD5' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start'} - - if file_path is None: - return 'Enter a correct file_path' - else: - req_param['file_path'] = file_path - - self._md5_calc_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] - self._md5_calc_taskid_list.append(self._md5_calc_taskid) - - message = ('You can now check the status of request with ' - 'get_md5_status() , your id is: ' + self._md5_calc_taskid) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": self._md5_calc_taskid} - - return output - - def get_md5_status(self, taskid: Optional[str] = None) -> str | dict[str, object]: - api_name = 'SYNO.FileStation.MD5' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'status'} - - if taskid is None and self._md5_calc_taskid != '': - req_param['taskid'] = '"{taskid}"'.format(taskid=self._md5_calc_taskid) - elif taskid is not None: - req_param['taskid'] = '"{taskid}"'.format(taskid=taskid) - else: - return 'Did you run start_md5_calc() first? No task id found! ' + str(self._md5_calc_taskid) - - return self.request_data(api_name, api_path, req_param) - - def stop_md5_calc(self, taskid: str) -> str: - api_name = 'SYNO.FileStation.DirSize' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': taskid} - - if taskid is None: - return 'Enter a valid taskid choose between: ' + str(self._md5_calc_taskid_list) - else: - req_param['taskid'] = '"' + taskid + '"' - - self.request_data(api_name, api_path, req_param) - self._md5_calc_taskid_list.remove(taskid) - - return 'The task has been stopped' - - def check_permissions(self, - path: str, - filename: str, - overwrite: Optional[bool] = None, - create_only: Optional[bool] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.CheckPermission' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'write'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - if path is None: - return 'Enter a valid path' - - if filename is None: - return 'Enter a valid name' - - return self.request_data(api_name, api_path, req_param) - - def upload_file(self, - dest_path: str, - file_path: str, - create_parents: bool = True, - overwrite: bool = True, - verify: bool = False, - progress_bar: bool = True - ) -> str | tuple[int, dict[str, object]]: - api_name = 'SYNO.FileStation.Upload' - info = self.gen_list[api_name] - api_path = info['path'] - filename = os.path.basename(file_path) - - session = requests.session() - - with open(file_path, 'rb') as payload: - url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=upload&_sid=%s' % ( - api_name, info['minVersion'], self._sid) - - encoder = MultipartEncoder({ - 'path': dest_path, - 'create_parents': str(create_parents).lower(), - 'overwrite': str(overwrite).lower(), - 'files': (filename, payload, 'application/octet-stream') - }) - - if progress_bar: - bar = tqdm.tqdm(desc='Upload Progress', - total=encoder.len, - dynamic_ncols=True, - unit='B', - unit_scale=True, - unit_divisor=1024 - ) - - monitor = MultipartEncoderMonitor(encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) - - r = session.post( - url, - data=monitor, - verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': monitor.content_type} - ) - - else: - r = session.post( - url, - data=encoder, - verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': encoder.content_type} - ) - - session.close() - if r.status_code != 200 or not r.json()['success']: - return r.status_code, r.json() - - return r.json() - - def get_shared_link_info(self, link_id: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Sharing' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'getinfo'} - - if link_id is None: - return 'Enter a valid id' - else: - req_param['id'] = link_id - - return self.request_data(api_name, api_path, req_param) - - def get_shared_link_list(self, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - force_clean: Optional[bool] = None - ) -> dict[str, object] | str: - - api_name = 'SYNO.FileStation.Sharing' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - return self.request_data(api_name, api_path, req_param) - - def create_sharing_link(self, - path: str, - password: Optional[str] = None, - date_expired: Optional[str | int] = None, - date_available: Optional[str | int] = None, - expire_times: int = 0 - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Sharing' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'create'} - - if date_expired: - if str(date_expired)[0] != '"': - date_expired = '"' + str(date_expired) + '"' - if date_available: - if str(date_available)[0] != '"': - date_available = '"' + str(date_available) + '"' - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - if path is None: - return 'Enter a valid path' - - return self.request_data(api_name, api_path, req_param) - - def delete_shared_link(self, link_id: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Sharing' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'delete'} - - if link_id is None: - return 'Enter a valid id' - else: - req_param['id'] = link_id - - return self.request_data(api_name, api_path, req_param) - - def clear_invalid_shared_link(self) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Sharing' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'clear_invalid'} - - return self.request_data(api_name, api_path, req_param) - - def edit_shared_link(self, - link_id: str, - password: Optional[str] = None, - date_expired: Optional[str | int] = None, - date_available: Optional[str | int] = None, - expire_times: int = 0 - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Sharing' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'edit'} - - if date_expired: - if str(date_expired)[0] != '"': - date_expired = '"' + str(date_expired) + '"' - if date_available: - if str(date_available)[0] != '"': - date_available = '"' + str(date_available) + '"' - - if link_id is None: - return 'Enter a valid id' - else: - req_param['id'] = link_id - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - return self.request_data(api_name, api_path, req_param) - - def create_folder(self, - folder_path: str | list[str], - name: str | list[str], - force_parent: Optional[bool] = None, - additional: Optional[str | list[str]] = None - ) -> str | dict[str, object]: - api_name = 'SYNO.FileStation.CreateFolder' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'create'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'folder_path', 'additional', 'name']: - if val is not None: - req_param[str(key)] = val - - if type(folder_path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in folder_path] - folder_path = new_path - folder_path = '[' + ','.join(folder_path) + ']' - req_param['folder_path'] = folder_path - elif folder_path is not None: - req_param['folder_path'] = folder_path - else: - return 'Enter a valid path' - - if type(name) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in name] - name = new_path - name = '[' + ','.join(name) + ']' - req_param['name'] = name - elif name is not None: - req_param['name'] = '"' + name + '"' - else: - return 'Enter a valid path' - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = ','.join(additional) - - req_param['additional'] = additional - - return self.request_data(api_name, api_path, req_param) - - def rename_folder(self, - path: str | list[str], - name: str | list[str], - additional: Optional[str | list[str]] = None, - search_taskid: Optional[str] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Rename' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'rename'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid folder path (folder path only ex. "/home/Drive/Downloads")' - - if type(name) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in name] - name = new_path - name = '[' + ','.join(name) + ']' - req_param['name'] = name - elif name is not None: - req_param['name'] = name - else: - return 'Enter a valid new folder name (new folder name only ex. "New Folder")' - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = ','.join(additional) - - req_param['additional'] = additional - - if search_taskid is not None: - req_param['search_taskid'] = search_taskid - - return self.request_data(api_name, api_path, req_param) - - def start_copy_move(self, - path: str | list[str], - dest_folder_path: str | list[str], - overwrite: Optional[bool] = None, - remove_src: Optional[bool] = None, - accurate_progress: Optional[bool] = None, - search_taskid: Optional[str] = None - ) -> str | dict[str, object]: - api_name = 'SYNO.FileStation.CopyMove' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid path' - - if type(dest_folder_path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in dest_folder_path] - dest_folder_path = new_path - dest_folder_path = '[' + ','.join(dest_folder_path) + ']' - req_param['name'] = dest_folder_path - elif dest_folder_path is not None: - req_param['dest_folder_path'] = dest_folder_path - else: - return 'Enter a valid path' - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'path', 'additional', - 'dest_folder_path', 'new_path']: - if val is not None: - req_param[str(key)] = val - - self._copy_move_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] - self._dir_taskid_list.append(self._copy_move_taskid) - - message = ('You can now check the status of request with ' - 'get_copy_move_status() , your id is: ' - + self._copy_move_taskid) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": self._copy_move_taskid} - - return output - - def get_copy_move_status(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.CopyMove' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'status'} - - if taskid is None: - return 'Enter a valid taskid choose between ' + str(self._copy_move_taskid_list) - else: - req_param['taskid'] = '"' + taskid + '"' - - return self.request_data(api_name, api_path, req_param) - - def stop_copy_move_task(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.CopyMove' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop'} - - if taskid is None: - return 'Enter a valid taskid choose between ' + str(self._copy_move_taskid_list) - else: - req_param['taskid'] = taskid - - self._copy_move_taskid_list.remove(taskid) - - return self.request_data(api_name, api_path, req_param) - - def start_delete_task(self, - path: str | list[str], - accurate_progress: Optional[bool] = None, - recursive: Optional[bool] = None, - search_taskid: Optional[str] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Delete' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid path' - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'path', 'new_path']: - if val is not None: - req_param[str(key)] = val - - self._delete_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] - self._delete_taskid_list.append(self._delete_taskid) - - message = ('You can now check the status of request with ' - 'get_delete_status() , task id is: ' - + self._delete_taskid) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": self._delete_taskid} - - return output - - def get_delete_status(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Delete' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'status'} - - if taskid is None: - return 'Enter a valid taskid, choose between ' + str(self._delete_taskid_list) - else: - req_param['taskid'] = taskid - - return self.request_data(api_name, api_path, req_param) - - def stop_delete_task(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Delete' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop'} - - if taskid is None: - return 'Enter a valid taskid, choose between ' + str(self._delete_taskid_list) - else: - req_param['taskid'] = taskid - - self._delete_taskid_list.remove('"' + taskid + '"') - - return self.request_data(api_name, api_path, req_param) - - def delete_blocking_function(self, - path: str, - recursive: Optional[bool] = None, - search_taskid: Optional[str] = None) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Delete' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'delete'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid path' - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'path', 'new_path']: - if val is not None: - req_param[str(key)] = val - - 'This function will stop your script until done! Do not interrupt ' - - return self.request_data(api_name, api_path, req_param) - - def start_extract_task(self, - file_path: str, - dest_folder_path: str, - overwrite: Optional[bool] = None, - keep_dir: Optional[bool] = None, - create_subfolder: Optional[bool] = None, - codepage: Optional[str] = None, - password: Optional[str] = None, - item_id: Optional[str] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Extract' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start', 'file_path': file_path, - 'dest_folder_path': dest_folder_path} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - if file_path is None: - return 'Enter a valid file_path' - - if dest_folder_path is None: - return 'Enter a valid dest_folder_path' - - self._extract_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] - self._extract_taskid_list.append(self._extract_taskid) - - message = ('You can now check the status of request with ' - 'get_extract_status() , your id is: ' - + self._extract_taskid) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": self._extract_taskid} - - return output - - def get_extract_status(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Extract' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'status'} - - if taskid is None: - return 'Enter a valid taskid, choose between ' + str(self._extract_taskid_list) - else: - req_param['taskid'] = taskid - - return self.request_data(api_name, api_path, req_param) - - def stop_extract_task(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Extract' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop'} - - if taskid is None: - return 'Enter a valid taskid, choose between ' + str(self._extract_taskid_list) - else: - req_param['taskid'] = taskid - - self._extract_taskid_list.remove(taskid) - - return self.request_data(api_name, api_path, req_param) - - def get_file_list_of_archive(self, - file_path: str, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - codepage: Optional[str] = None, - password: Optional[str] = None, - item_id: Optional[str] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Extract' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - if file_path is None: - return 'Enter a valid file_path' - - return self.request_data(api_name, api_path, req_param) - - def start_file_compression(self, - path: str | list[str], - dest_file_path: str, - level: Optional[int] = None, - mode: Optional[str] = None, - compress_format: Optional[str] = None, - password: Optional[str] = None - ) -> dict[str, object] | str | tuple[str]: - api_name = 'SYNO.FileStation.Compress' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'start'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - else: - return 'Enter a valid path' - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'compress_format', '_password', '_api_path', - 'req_param', 'path', 'new_path']: - if val is not None: - req_param[str(key)] = val - - if dest_file_path is None: - return 'Enter a valid dest_file_path' - - if compress_format is not None: - req_param['format'] = compress_format - - if password is not None: - req_param['_password'] = password - - self._compress_taskid = self.request_data(api_name, api_path, req_param)['data']['taskid'] - - message = ('You can now check the status of request with ' - 'get_compress_status() , your id is: ' - + self._compress_taskid) - if self.interactive_output: - output = message - else: - output = {"message": message, "taskid": self._compress_taskid} - - return output - - def get_compress_status(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Compress' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'status'} - - if taskid is None: - return 'Enter a valid taskid' - else: - req_param['taskid'] = taskid - - return self.request_data(api_name, api_path, req_param) - - def stop_compress_task(self, taskid: str) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.Compress' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'stop'} - - if taskid is None: - return 'Enter a valid taskid' - else: - req_param['taskid'] = taskid - - return self.request_data(api_name, api_path, req_param) - - def get_list_of_all_background_task(self, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - api_filter: Optional[str] = None - ) -> dict[str, object] | str: - api_name = 'SYNO.FileStation.BackgroundTask' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'list'} - - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - - if type(api_filter) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in api_filter] - api_filter = new_path - api_filter = '[' + ','.join(api_filter) + ']' - req_param['api_filter'] = api_filter - - return self.request_data(api_name, api_path, req_param) - - def get_file(self, - path: str, - mode: str, - dest_path: str = ".", - chunk_size: int = 8192, - verify: bool = False - ) -> Optional[str]: - - api_name = 'SYNO.FileStation.Download' - info = self.gen_list[api_name] - api_path = info['path'] - - if path is None: - return 'Enter a valid path' - - session = requests.session() - - url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=download&path=%s&mode=%s&_sid=%s' % ( - api_name, info['maxVersion'], parse.quote_plus(path), mode, self._sid) - - if mode is None: - return 'Enter a valid mode (open / download)' - - if mode == r'open': - with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: - r.raise_for_status() - for chunk in r.iter_content(chunk_size=chunk_size): - if chunk: # filter out keep-alive new chunks - sys.stdout.buffer.write(chunk) - - if mode == r'download': - with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: - r.raise_for_status() - if not os.path.isdir(dest_path): - os.makedirs(dest_path) - with open(dest_path + "/" + os.path.basename(path), 'wb') as f: - for chunk in r.iter_content(chunk_size=chunk_size): - if chunk: # filter out keep-alive new chunks - f.write(chunk) - - if mode == r'serve': - with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: - r.raise_for_status() - return io.BytesIO(r.content) - - def generate_file_tree(self, folder_path: str, tree: Tree) -> None: - """Generate the file tree based on the folder path you give, you need to create the root node before call this function - - Parameters - ---------- - folder_path : str - Folder path to generate file tree - tree : Tree - Instance of the Tree of lib "Treelib" - - """ - data: dict = self.get_file_list( - folder_path=folder_path - ).get("data") - - files = data.get("files") - file: dict - for file in files: - file_name: str = file.get("name") - file_path: str = file.get("path") - if file.get("isdir"): - - tree.create_node(file_name, file_path, parent=folder_path) - self.generate_file_tree(file_path, tree) - else: - tree.create_node(file_name, file_path, parent=folder_path) - - -# TODO SYNO.FileStation.Thumb to be done diff --git a/synology_api/DSM/Package/FileStation.py b/synology_api/DSM/Package/FileStation.py new file mode 100644 index 00000000..68f53b56 --- /dev/null +++ b/synology_api/DSM/Package/FileStation.py @@ -0,0 +1,2518 @@ +from __future__ import annotations +from typing import Optional, Any +from datetime import datetime +import requests, tqdm, time, io, json, os, sys +from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor +from urllib import parse +from treelib import Tree +from synology_api import base_api + + +class FileStation(base_api.BaseApi): + """Implementation of FileStation API based on the Synology API documentation [link](https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf) + """ + + def get_info(self) -> dict[str, object]: + """Get info about FileStation + + Returns + ------- + dict[str, object] + List of FileStation info + + Example return + ---------- + ```json + { + "data": { + "allow_normal_disable_html": true, + "enable_list_usergrp": false, + "enable_send_email_attachment": true, + "enable_view_google": true, + "enable_view_microsoft": true, + "hostname": "SYNO-FLORENTB", + "is_manager": true, + "items": [ + { + "gid": 100 + }, + { + "gid": 101 + }, + { + "gid": 1023 + } + ], + "support_file_request": true, + "support_sharing": true, + "support_vfs": true, + "support_virtual": { + "enable_iso_mount": true, + "enable_remote_mount": true + }, + "support_virtual_protocol": [ + "cifs", + "nfs", + "iso" + ], + "system_codepage": "fre", + "uid": 1027 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Info' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'get'} + + return self.request_data(api_name, api_path, req_param) + + def get_list_share(self, + additional: Optional[list[str]] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + onlywritable: bool = False + ) -> dict[str, object]: + """Get list of shared folders + + Parameters + ---------- + additional : Optional[list[str]], optional + Additionnal field to retrieve from shared folder. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","mount_point_type","sync_share","volume_status","indexed","hybrid_share","worm_share"]`. + offset : Optional[int], optional + Offset in the shared folder list. Defaults to `None` + limit : Optional[int], optional + Limit the len of the returned list. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields know are: `["name","user","group","mtime","atime","ctime","crtime","posix"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + onlywritable : bool, optional + Force list of shared folder where the user as write access. Defaults to `False` + + Returns + ------- + dict[str, object] + List of shared folder in FileStation + + Example return + ---------- + ```json + { + "data": { + "offset": 0, + "shares": [ + { + "isdir": true, + "name": "docker", + "path": "/docker" + }, + { + "isdir": true, + "name": "Documents", + "path": "/Documents" + } + ], + "total": 2 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list_share', + 'onlywritable': onlywritable, + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'additional': json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def get_file_list(self, + folder_path: str, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + pattern: Optional[list[str]] = None, + filetype: Optional[str] = None, + goto_path: Optional[str] = None, + additional: Optional[list[str]] = None, + check_dir: Optional[bool] = None + ) -> dict[str, object]: + """Get list of files in a folder + + Parameters + ---------- + folder_path : str + A listed folder path starting with a shared folder. + offset : Optional[int], optional + Specify how many files are skipped before beginning to return listed files. Defaults to `None` + limit : Optional[int], optional + Number of files requested. 0 indicates to list all files with a given folder. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name","size","user","group","mtime","atime","ctime","crtime","posix","type"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + pattern : Optional[list[str]], optional + Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` + Note: + 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. + filetype : Optional[str], optional + "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` + All fields know are: `["file","dir","all"]` + goto_path : Optional[str], optional + Folder path starting with a shared folder. Return all files and sub-folders within folder_path path until goto_path path recursively. Defaults to `None` + Note: + goto_path is only valid with parameter "additional" contains real_path. + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. + check_dir : Optional[bool], optional + _description_. Defaults to `None` + + Returns + ------- + dict[str, object] + _description_ + + Example return + ---------- + ```json + { + "data": { + "files": [ + { + "isdir": false, + "name": "compose.yaml", + "path": "/docker/compose.yaml" + } + ], + "offset": 0, + "total": 1 + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'action': 'list', + 'method': 'list', + 'folder_path': folder_path, + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'pattern': ', '.join(pattern) if isinstance(pattern, list) else pattern if isinstance(pattern, str) else None, + 'filetype': filetype, + 'goto_path': goto_path, + 'additional': json.dumps(additional), + 'check_dir': check_dir + } + + return self.request_data(api_name, api_path, req_param) + + def get_file_info(self, path: list[str], additional: Optional[list[str]] = None) -> dict[str, object]: + """Get information of file(s) / folder(s). + + Parameters + ---------- + path : list[str] + One or more folder/file path(s) starting with a shared folder + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. + + Returns + ------- + dict[str, object] + Information of file(s) / folder(s) + + Example return + ---------- + ```json + { + "data": { + "files": [ + { + "isdir": true, + "name": "Films", + "path": "/Films" + }, + { + "isdir": true, + "name": "Documents", + "path": "/Documents" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'getinfo', + 'path': json.dumps(path), + 'additional': json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def search_start(self, + folder_path: str = None, recursive: Optional[bool] = None, pattern: Optional[list[str]] = None, + extension: Optional[list[str]] = None, filetype: Optional[str] = None, size_from: Optional[int] = None, + size_to: Optional[int] = None, mtime_from: Optional[int] = None, mtime_to: Optional[int] = None, + crtime_from: Optional[int] = None, crtime_to: Optional[int] = None, atime_from: Optional[int] = None, + atime_to: Optional[int] = None, owner: Optional[str] = None, group: Optional[str] = None + ) -> dict[str, object]: + """Start to search files according to given criteria. If more than one criterion is given in different parameters, searched files match all these criteria. + + Parameters + ---------- + folder_path : str, optional + A searched folder path starting with a shared folder. One or more folder paths to be searched, separated by commas "," and around brackets. Defaults to `None` + recursive : Optional[bool], optional + If searching files within a folder and subfolders recursively or not. Defaults to `None` + pattern : Optional[list[str]], optional + Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` + Note: + 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern.. Defaults to `None` + extension : Optional[list[str]], optional + Search for files whose extensions match a file type pattern in a case-insensitive glob pattern. If you give this criterion, folders aren't matched. Defaults to `None` + filetype : Optional[str], optional + "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` + All fields know are: `["file","dir","all"]` + size_from : Optional[int], optional + Search for files whose sizes are greater than the given byte size. Defaults to `None` + size_to : Optional[int], optional + Search for files whose sizes are less than the given byte size. Defaults to `None` + mtime_from : Optional[int], optional + Search for files whose last modified time after the given Linux timestamp (UTC) in second. Defaults to `None` + mtime_to : Optional[int], optional + Search for files whose last modified time before the given Linux timestamp (UTC) in second. Defaults to `None` + crtime_from : Optional[int], optional + Search for files whose create time after the given Linux timestamp (UTC) in second. Defaults to `None` + crtime_to : Optional[int], optional + Search for files whose create time before the given Linux timestamp (UTC) in second. Defaults to `None` + atime_from : Optional[int], optional + Search for files whose last access time after the given Linux timestamp (UTC) in second. Defaults to `None` + atime_to : Optional[int], optional + Search for files whose last access time before the given Linux timestamp (UTC) in second. Defaults to `None` + owner : Optional[str], optional + Search for files whose user name matches this criterion. This criterion is case-insensitive. Defaults to `None` + group : Optional[str], optional + Search for files whose group name matches this criterion. This criterion is case-insensitive. Defaults to `None` + + Returns + ------- + dict[str, object] + A unique ID for the search task + + Example return + ---------- + ```json + { + "data": { + "has_not_index_share": true, + "taskid": "51CE617CF57B24E5" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'folder_path': folder_path, + 'recursive': recursive, + 'pattern': ', '.join(pattern) if isinstance(pattern, list) else pattern if isinstance(pattern, str) else None, + 'extension': ', '.join(extension) if isinstance(extension, list) else extension if isinstance(extension, str) else None, + 'filetype': filetype, + 'size_from': size_from, + 'size_to': size_to, + 'mtime_from': mtime_from, + 'mtime_to': mtime_to, + 'crtime_from': crtime_from, + 'crtime_to': crtime_to, + 'atime_from': atime_from, + 'atime_to': atime_to, + 'owner': owner, + 'group': group + } + + return self.request_data(api_name, api_path, req_param) + + def get_search_list(self, + taskid: str, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + pattern: Optional[list[str]] = None, + filetype: Optional[str] = None, + additional: Optional[list[str]] = None + ) -> dict[str, object]: + """List matched files in a search temporary database. You can check the finished value in response to know if the search operation is processing or has been finished. + + Parameters + ---------- + taskid : str + A unique ID for the search task which is obtained from `search_start` method. + offset : Optional[int], optional + Specify how many files are skipped before beginning to return listed files. Defaults to `None` + limit : Optional[int], optional + Number of files requested. 0 indicates to list all files with a given folder. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name","size","user","group","mtime","atime","ctime","crtime","posix","type"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + pattern : Optional[list[str]], optional + Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` + Note: + 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. + filetype : Optional[str], optional + "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` + All fields know are: `["file","dir","all"]` + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type"]`. + + Returns + ------- + dict[str, object] + Infos about the search and the matched files. + + Example return + ---------- + ```json + { + "data": { + "files": [ + { + "isdir": false, + "name": "compose.yaml", + "path": "/docker/compose.yaml" + } + ], + "finished": true, + "offset": 0, + "total": 1 + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'taskid': taskid, + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'pattern': ', '.join(pattern) if isinstance(pattern, list) else pattern if isinstance(pattern, str) else None, + 'filetype': filetype, + 'additional': json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def stop_search_task(self, taskid: str | list[str]) -> dict[str, object]: + """Stop the searching task(s). The search temporary database won't be deleted, so it's possible to list the search result using list method after stopping it + + Parameters + ---------- + taskid : str | list[str] + Unique ID(s) for the search task which are obtained from `search_start` method. Specify multiple search task IDs by using list type. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': json.dumps(taskid) if isinstance(taskid, list) else taskid, + } + + return self.request_data(api_name, api_path, req_param) + + def clean_search_task(self, taskid: str | list[str]) -> dict[str, object]: + """ Delete search temporary database(s). + + Parameters + ---------- + taskid : str | list[str] + Unique ID(s) for the search task which are obtained from `search_start` method. Specify multiple search task IDs by using list type. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Search' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'clean', + 'taskid': json.dumps(taskid) if isinstance(taskid, list) else taskid, + } + + return self.request_data(api_name, api_path, req_param) + + def get_mount_point_list(self, mount_type: str, offset: Optional[int] = None, limit: Optional[int] = None, + sort_by: Optional[str] = None, sort_direction: Optional[str] = None, additional: Optional[list[str]] = None + ) -> dict[str, object]: + """List all mount point folders on one given type of virtual file system. + + Parameters + ---------- + mount_type : str + A type of virtual file systems. + All fields known are: `["cifs","nfs","iso"]` + offset : Optional[int], optional + Specify how many mount point folders are skipped before beginning to return listed files. Defaults to `None` + limit : Optional[int], optional + Number of mount point folders requested. 0 indicates to list all files with a given folder. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name",,"user","group","mtime","atime","ctime","crtime","posix"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","volume_status"]`. + + Returns + ------- + dict[str, object] + List of mount point folders + + Example return + ---------- + ```json + { + "data": { + "folders": [ + { + "additional": { + "mount_point_type": "remote", + "owner": { + "gid": 100, + "group": "users", + "uid": 1024, + "user": "admin" + }, + "perm": { + "acl": { + "append": true, + "del": true, + "exec": true, + "read": true, + "write": true + }, + "is_acl_mode": false, + "posix": 777 + }, + "real_path": "/volume1/vidoe/remote", + "time": { + "atime": 1372313445, + "crtime": 1320204670, + "ctime": 1371206944, + "mtime": 1371206944 + }, + "volume_status": { + "freespace": 12282422599680, + "readonly": false, + "totalspace": 801958928384 + } + }, + "isdir": true, + "name": "remote", + "path": "/video/remote" + } + ], + "offset": 0, + "total": 0 + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.VirtualFolder' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'type': mount_type, + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'additional': json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def get_favorite_list(self, + offset: Optional[int] = None, + limit: Optional[int] = None, + status_filter: Optional[str] = None, + additional: Optional[str | list[str]] = None + ) -> dict[str, object]: + """List user's favorites. + + Parameters + ---------- + offset : Optional[int], optional + Specify how many favorites are skipped before beginning to return user's favorites. Defaults to `None` + limit : Optional[int], optional + Number of favorites requested. 0 indicates to list all favorites. Defaults to `None` + status_filter : Optional[str], optional + Show favorites with a given favorite status. Defaults to `None` + All fields known are: `["valid","broken","all"]` + additional : Optional[str | list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","owner","time","perm","mount_point_type"]`. + + Returns + ------- + dict[str, object] + List of user's favorites + + Example return + ---------- + ```json + { + "data": { + "favorites": [ + { + "isdir": true, + "name": "My Video Shared folder", + "path": "/video", + "status": "valid" + }, + { + "isdir": false, + "name": "deletedfolder", + "path": "/share/deletedfolder", + "status": "broken" + } + ], + "offset": 0, + "total": 2 + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'offset': offset, + 'limit': limit, + 'status_filter': status_filter, + 'additional': json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def add_a_favorite(self, path: str, name: Optional[str] = None, index: Optional[int] = -1) -> dict[str, object]: + """ Add a folder to user's favorites. + + Parameters + ---------- + path : str + A folder path starting with a shared folder is added to the user's favorites. + name : Optional[str], optional + A favorite name. Defaults to `None` + index : Optional[int], optional + Index of location of an added favorite. Defaults to `-1` + If it's equal to -1, the favorite will be added to the last one in user's favorite. + If it's between 0 ~ total number of favorites-1, the favorite will be inserted into user's favorites by the index. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'add', + 'path': path, + 'name': name, + 'index': index + } + + return self.request_data(api_name, api_path, req_param) + + def delete_a_favorite(self, path: str) -> dict[str, object]: + """Delete a favorite in user's favorites. + + Parameters + ---------- + path : str + A folder path starting with a shared folder is deleted from a user's favorites. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'delete', + 'path': path + } + + return self.request_data(api_name, api_path, req_param) + + def clear_broken_favorite(self) -> dict[str, object]: + """ Delete all broken statuses of favorites. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'clear_broken' + } + + return self.request_data(api_name, api_path, req_param) + + def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object]: + """Edit a favorite name. + + Parameters + ---------- + path : str + A folder path starting with a shared folder is edited from a user's favorites. + new_name : str + New favorite name. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'edit', + 'path': path, + 'new_name': new_name + } + + return self.request_data(api_name, api_path, req_param) + + def replace_all_favorite(self, path: str | list[str], name: str | list[str]) -> dict[str, object]: + """ Replace multiple favorites of folders to the existing user's favorites. + + Parameters + ---------- + path : str | list[str] + One or more folder paths starting with a shared folder is added to the user's favorites. + The number of paths must be the same as the number of favorite names in the name parameter. + The first path parameter corresponds to the first name parameter. + name : str | list[str] + One or more new favorite names. The number of favorite names must be the same as the number of folder paths in the path parameter. + The first name parameter corresponding to the first path parameter. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.Favorite' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'edit', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'name': json.dumps(name) if isinstance(name, list) else name + } + + return self.request_data(api_name, api_path, req_param) + + def get_thumbnail(self, path: str, size: Optional[str] = "small", rotate: Optional[int] = None) -> bytes: + """Get a thumbnail of a file. + + Parameters + ---------- + path : str + A file path starting with a shared folder. + size : str + The size of the thumbnail. Defaults to `None` + All fields known are: `["small","medium","large","original"]` + rotate : Optional[int], optional + The angle of the thumbnail. Defaults to `None` + All fields known are: `[0,1,2,3,4] = ["0°","90°","180°","270°","360°"]` + + Returns + ------- + bytes + The thumbnail of the file. If the file is not found, it will raise an exception. + + Example return + ---------- + ```json + b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR + ``` + """ + api_name = 'SYNO.FileStation.Thumb' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': "get", + 'path': path, + 'size': size, + 'rotate': rotate + } + response = self.request_data(api_name, api_path, req_param, response_json=False) + match response.status_code: + case 200: + return response.content + case 404: + raise Exception("File not found") + case _: + raise Exception(f"HTTP Status error : {response.status_code}") + + def start_dir_size_calc(self, path: str | list[str]) -> dict[str, object]: + """Start to calculate size for one or more file/folder paths. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder for calculating cumulative size + + Returns + ------- + dict[str, object] + Task ID for the size calculation request + + Example return + ---------- + ```json + { + "data": { + "taskid": "51CBD7CD5C76E461" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'path': json.dumps(path) if isinstance(path, list) else path + } + return self.request_data(api_name, api_path, req_param)['data']['taskid'] + + def get_dir_status(self, taskid: str) -> dict[str, object]: + """Get the status of the size calculating task. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_dir_size_calc` method. + + Returns + ------- + dict[str, object] + Infos about the size calculating task + + Example return + ---------- + ```json + { + "data": { + "finished": true, + "num_dir": 3, + "num_file": 104, + "total_size": 29973265 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status', + 'taskid': taskid + } + + return self.request_data(api_name, api_path, req_param) + + def stop_dir_size_calc(self, taskid: str) -> dict[str, object]: + """Stop the calculation. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_dir_size_calc` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def start_md5_calc(self, file_path: str) -> dict[str, object]: + """Start to get MD5 of a file. + + Parameters + ---------- + file_path : str + A file path starting with a shared folder for calculating MD5 value. + + Returns + ------- + dict[str, object] + Task ID for the size calculation request + + Example return + ---------- + ```json + { + "data": { + "taskid": "51CBD7CD5C76E461" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.MD5' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'file_path': file_path + } + return self.request_data(api_name, api_path, req_param) + + def get_md5_status(self, taskid: str) -> dict[str, object]: + """ Get the status of the MD5 calculation task. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_md5_status` method. + + Returns + ------- + dict[str, object] + Finished status of the MD5 calculation task and the md5 of requested file + + Example return + ---------- + ```json + { + "data": { + "finished": true, + "md5": "6336c5a59aa63dd2042783f88e15410a" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.MD5' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def stop_md5_calc(self, taskid: str) -> dict[str, object]: + """Stop calculating the MD5 of a file. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_md5_status` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.DirSize' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def check_permissions(self, + path: str, + filename: str, + overwrite: Optional[bool] = False, + create_only: Optional[bool] = True + ) -> dict[str, object]: + """Check if a logged-in user has write permission to create new files/folders in a given folder + + Parameters + ---------- + path : str + A folder path starting with a shared folder to check write permission + filename : str + A filename you want to write to given path + overwrite : Optional[bool], optional + The value could be one of following: Defaults to `False` + - "true": overwrite the destination file if one exists. + - "false": skip if the destination file exists. + + Note: when it's not specified as true or false, it will be responded with error when the destination file exists. + + create_only : Optional[bool], optional + If set to "true", the permission will be allowed when there is non-existent file/folder. Defaults to `True` + + Returns + ------- + dict[str, object] + The request will get error response if no write permission for the specified path. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.CheckPermission' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'write', + 'path': path, + 'filename': filename, + 'overwrite': overwrite, + 'create_only': create_only + } + return self.request_data(api_name, api_path, req_param) + + def upload_file(self, + dest_path: str, + file_path: str, + create_parents: bool = True, + overwrite: bool = True, + verify: bool = False, + progress_bar: bool = True + ) -> tuple[int, dict[str, object]]: + """Upload a file to a given destination path. + + Parameters + ---------- + dest_path : str + A destination folder path starting with a shared folder. + file_path : str + A file path to be uploaded. + create_parents : bool, optional + Create parent folder(s) if none exist. Defaults to `True` + overwrite : bool, optional + If `True` overwrite the destination file if one exist else skip the upload if the destination file exist. Defaults to `True` + verify : bool, optional + If `True` use HTTPS else use HTTP. Defaults to `False` + progress_bar : bool, optional + Enable or note the progress bar in the stdout. Defaults to `True` + + Returns + ------- + tuple[int, dict[str, object]] + If failed return a tuple with the status code and the error message + else return the response json + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Upload' + info = self.gen_list[api_name] + api_path = info['path'] + filename = os.path.basename(file_path) + + session = requests.session() + + with open(file_path, 'rb') as payload: + url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=upload&_sid=%s' % ( + api_name, info['minVersion'], self._sid) + + encoder = MultipartEncoder({ + 'path': dest_path, + 'create_parents': str(create_parents).lower(), + 'overwrite': str(overwrite).lower(), + 'files': (filename, payload, 'application/octet-stream') + }) + + if progress_bar: + bar = tqdm.tqdm(desc='Upload Progress', + total=encoder.len, + dynamic_ncols=True, + unit='B', + unit_scale=True, + unit_divisor=1024 + ) + + monitor = MultipartEncoderMonitor(encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) + + r = session.post( + url, + data=monitor, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': monitor.content_type} + ) + + else: + r = session.post( + url, + data=encoder, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': encoder.content_type} + ) + + session.close() + if r.status_code != 200 or not r.json()['success']: + return r.status_code, r.json() + + return r.json() + + def get_shared_link_info(self, link_id: str) -> dict[str, object]: + """ Get information of a sharing link by the sharing link ID + + Parameters + ---------- + link_id : str + A unique ID of a sharing link. + + Returns + ------- + dict[str, object] + Information about the sharing link + + Example return + ---------- + ```json + { + "data": { + "date_available": "0", + "date_expired": "0", + "has_password": false, + "id": "pHTBKQf9", + "isFolder": false, + "link_owner": "admin", + "name": "ITEMA_20448251-0.mp3", + "path": "/test/ITEMA_20448251-0.mp3", + "status": "valid", + "url": "http://myds.com:5000/fbsharing/pHTBKQf9" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'getinfo', + 'id': link_id + } + return self.request_data(api_name, api_path, req_param) + + def get_shared_link_list(self, offset: Optional[int] = None, limit: Optional[int] = None, sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, force_clean: Optional[bool] = None + ) -> dict[str, object]: + """List user's file sharing links + + Parameters + ---------- + offset : Optional[int], optional + Specify how many sharing links are skipped before beginning to return listed sharing links. Defaults to `None` + limit : Optional[int], optional + Number of sharing links requested. 0 means to list all sharing links. Defaults to `None` + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name","isFolder","path","date_expired","date_available","status","has_password","id","url","link_owner"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + force_clean : Optional[bool], optional + If set to false, the data will be retrieved from cache database rapidly. If set to true, all sharing information including sharing statuses and user name of sharing owner will be synchronized. It consumes some time. Defaults to `None` + + Returns + ------- + dict[str, object] + Information about the sharing links + + Example return + ---------- + ```json + { + "data": { + "links": [ + { + "date_available": "0", + "date_expired": "0", + "has_password": false, + "id": "pHTBKQf9", + "isFolder": false, + "link_owner": "admin", + "name": "ITEMA_20448251-0.mp3", + "path": "/test/ITEMA_20448251-0.mp3", + "status": "valid", + "url": "http://myds.com:5000/fbsharing/pHTBKQf9" + } + ], + "offset": 0, + "total": 1 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'force_clean': force_clean + } + return self.request_data(api_name, api_path, req_param) + + def create_sharing_link(self, path: str | list[str], password: Optional[str] = None, date_expired: Optional[str | int] = None, + date_available: Optional[str | int] = None + ) -> dict[str, object]: + """Generate one or more sharing link(s) by file/folder path(s). + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths with which to generate sharing links. + password : Optional[str], optional + The password for the sharing link when accessing it. The max password length are 16 characters. Defaults to `None` + date_expired : Optional[str | int], optional + The expiration date for the sharing link, written in the format YYYYMM-DD. When set to 0 (default), the sharing link is permanent. Defaults to `None` + + Note: SHOULD put the double quote outside expiration date and is based on user's DS date. + + date_available : Optional[str | int], optional + The available date for the sharing link to become effective, written in the format YYYY-MM-DD. When set to 0 (default), the sharing link is valid immediately after creation. Defaults to `None` + + Note: SHOULD put the double quote outside available date and is based on user's DS date. + + Returns + ------- + dict[str, object] + Information about the sharing link(s) generated + + Example return + ---------- + ```json + { + "data": { + "links": [ + { + "error": 0, + "id": "y4LmvpaX", + "path": "/test/ITEMA_20445972-0.mp3", + "qrcode": "iVBORw0KGgoAAAANSUh...", + "url": "http://myds.com:5000/fbsharing/y4LmvpaX" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'create', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'password': password, + 'date_expired': date_expired, + 'date_available': date_available + } + + return self.request_data(api_name, api_path, req_param) + + def delete_shared_link(self, link_id: str | list[str]) -> dict[str, object]: + """Delete one or more sharing links. + + Parameters + ---------- + link_id : str | list[str] + Unique IDs of file sharing link(s) to be deleted + + Returns + ------- + dict[str, object] + Returns an empty success response if completed without error; otherwise returns error object array contains failed IDs + + Example return + ---------- + ```json + {, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'delete', + 'id': json.dumps(link_id) if isinstance(link_id, list) else link_id + } + + return self.request_data(api_name, api_path, req_param) + + def clear_invalid_shared_link(self) -> dict[str, object]: + """Remove all expired and broken sharing links. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'clear_invalid' + } + + return self.request_data(api_name, api_path, req_param) + + def edit_shared_link(self, link_id: str | list[str], password: Optional[str] = None, date_expired: Optional[str | int] = None, + date_available: Optional[str | int] = None + ) -> dict[str, object]: + """Edit sharing link(s). + + Parameters + ---------- + link_id : str | list[str] + Unique ID(s) of sharing link(s) to edit. + password : Optional[str], optional + The password for the sharing link when accessing it. The max password length are 16 characters. Defaults to `None` + date_expired : Optional[str | int], optional + The expiration date for the sharing link, written in the format YYYYMM-DD. When set to 0 (default), the sharing link is permanent. Defaults to `None` + + Note: SHOULD put the double quote outside expiration date and is based on user's DS date. + + date_available : Optional[str | int], optional + The available date for the sharing link to become effective, written in the format YYYY-MM-DD. When set to 0 (default), the sharing link is valid immediately after creation. Defaults to `None` + + Note: SHOULD put the double quote outside available date and is based on user's DS date. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Sharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'edit', + 'id': json.dumps(link_id) if isinstance(link_id, list) else link_id, + 'password': password, + 'date_expired': date_expired, + 'date_available': date_available + } + return self.request_data(api_name, api_path, req_param) + + def create_folder(self, folder_path: str | list[str], name: str | list[str], + force_parent: Optional[bool] = False, additional: Optional[str | list[str]] = None + ) -> dict[str, object]: + """Create folders. + + Parameters + ---------- + folder_path : str | list[str] + One or more shared folder paths, separated by commas and around brackets. + If `force_parent` is `true`, and `folder_path` does not exist, the `folder_path` will be created. + If `force_parent` is `false`, `folder_path` must exist or a false value will be returned. + The number of paths must be the same as the number of names in the name parameter. + The first `folder_path` parameter corresponds to the first name parameter. + name : str | list[str] + One or more new folder names. + The number of names must be the same as the number of folder_paths paths in the `folder_path` parameter. + The first `name` parameter corresponding to the first `folder_path` parameter. + force_parent : Optional[bool], optional + Defaults to `False`. + If `true` : no error occurs if a folder exists and create parent folders as needed. + If `false` : parent folders are not created. + additional : Optional[str | list[str]], optional + Additionnal field to retrieve from folder. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type"]`. + + Returns + ------- + dict[str, object] + List of folder(s) created informations. + + Example return + ---------- + ```json + { + "data": { + "folders": [ + { + "isdir": true, + "name": "test", + "path": "/video/test" + } + ] + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.CreateFolder' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'create', + 'folder_path': json.dumps(folder_path) if isinstance(folder_path, list) else folder_path, + 'name': json.dumps(name) if isinstance(name, list) else name, + 'force_parent': force_parent + } + return self.request_data(api_name, api_path, req_param) + + def rename_folder(self, path: str | list[str], name: str | list[str], additional: Optional[str | list[str]] = None, search_taskid: Optional[str] = None) -> dict[str, object]: + """Rename folders. + + Parameters + ---------- + path : str | list[str] + One or more paths of files/folders to be renamed. + The number of paths must be the same as the number of names in the `name` parameter. + The first `path` parameter corresponds to the first `name` parameter. + name : str | list[str] + One or more new folder names. + The number of names must be the same as the number of paths paths in the `path` parameter. + The first `name` parameter corresponding to the first `path` parameter. + additional : Optional[str | list[str]], optional + Defaults to `None` + Additionnal field to retrieve from folder. + All fields known are: `["real_path","size","owner","time","perm","type"]`. + search_taskid : Optional[str], optional + The task ID of the `search_start` method. Defaults to `None` + + Returns + ------- + dict[str, object] + List of folder(s) renamed informations. + + Example return + ---------- + ```json + { + "data": { + "files": [ + { + "isdir": true, + "name": "test", + "path": "/video/test" + } + ] + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.Rename' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'rename', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'name': json.dumps(name) if isinstance(name, list) else name, + 'search_taskid': search_taskid + } + return self.request_data(api_name, api_path, req_param) + + def start_copy_move(self, + path: str | list[str], + dest_folder_path: str, + overwrite: Optional[bool] = None, + remove_src: Optional[bool] = False, + accurate_progress: Optional[bool] = True, + search_taskid: Optional[str] = None + ) -> dict[str, object]: + """Start to copy/move files. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to copy/move. + dest_folder_path : str + A destination folder path where files/folders are copied/moved. + overwrite : Optional[bool], optional + Defaults to `None`. + If `true` : overwrite all existing files with the same name. + If `false` : skip all existing files with the same name. + + Note: do not overwrite or skip existed files. If there is any existing files, an error occurs (error code: 1003). + + remove_src : Optional[bool], optional + Defaults to `False`. + If `true`: move files/folders. If `false`: copy files/folders. + accurate_progress : Optional[bool], optional + Defaults to `True`. + If `true` : calculate the progress by each moved/copied file within sub-folder. + If `false` : calculate the progress by files which you give in path parameters. This calculates the progress faster, but is less precise. + search_taskid : Optional[str], optional + The task ID of the `search_start` method. Defaults to `None`. + + Returns + ------- + dict[str, object] + Return unique task ID for the copy/move task. + + Example return + ---------- + ```json + { + "data": { + "taskid": "FileStation_51D00B7912CDE0B0" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.FileStation.CopyMove' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'dest_folder_path': dest_folder_path, + 'overwrite': overwrite, + 'remove_src': remove_src, + 'accurate_progress': accurate_progress, + 'search_taskid': search_taskid + } + + return self.request_data(api_name, api_path, req_param) + + def get_copy_move_status(self, taskid: str) -> dict[str, object]: + """ Get the copying/moving status. + + Parameters + ---------- + taskid : str + A unique ID for the copy/move task which is obtained from `start_copy_move` method + + Returns + ------- + dict[str, object] + Infos about the copy/move task + + Example return + ---------- + ```json + { + "data": { + "dest_folder_path": "/video/test", + "finished": false, + "path": "/video/test.avi", + "processed_size": 1057, + "progress": 0.01812258921563625, + "total": 58325 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.CopyMove' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def stop_copy_move_task(self, taskid: str) -> dict[str, object]: + """ Stop a copy/move task + + Parameters + ---------- + taskid : str + A unique ID for the copy/move task which is obtained from `start_copy_move` method + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.CopyMove' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def start_delete_task(self, + path: str | list[str], + accurate_progress: Optional[bool] = True, + recursive: Optional[bool] = True, + search_taskid: Optional[str] = None + ) -> dict[str, object]: + """ Delete file(s)/folder(s). This is a non-blocking method. You should poll a request with `get_delete_status` method to get the task status or stop the task with `stop_delete_task` method. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to delete. + accurate_progress : Optional[bool], optional + Defaults to `True` + If `true` : calculates the progress of each deleted file with the sub-folder recursively. + If `false` : calculates the progress of files which you give in `path` parameters. The latter is faster than recursively, but less precise. + Note: Only non-blocking methods suits using the `get_delete_status` method to get progress. + recursive : Optional[bool], optional + Defaults to `True`. + If `true` : delete files/folders recursively. + If `false` : Only delete first-level file/folder. If a deleted folder contains any file, an error occurs because the folder can't be directly deleted. + search_taskid : Optional[str], optional + A unique ID for the search task which is obtained from `search_start` method. It's used to delete the file in the search result. Defaults to `None` + + Returns + ------- + dict[str, object] + A unique task ID for the delete task. + + Example return + ---------- + ```json + { + "data": { + "taskid": "FileStation_51CEC9C979340E5A" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'accurate_progress': accurate_progress, + 'recursive': recursive, + 'search_taskid': search_taskid + } + return self.request_data(api_name, api_path, req_param) + + def get_delete_status(self, taskid: str) -> dict[str, object]: + """ Get the deleting status. + + Parameters + ---------- + taskid : str + A unique ID for the delete task which is obtained from `start_delete_task` method. + + Returns + ------- + dict[str, object] + Infos about the delete task. + + Example return + ---------- + ```json + { + "data": { + "finished": false, + "path": "/video/1000", + "processed_num": 193, + "processing_path": "/video/1000/509", + "progress": 0.03199071809649467, + "total": 6033 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def stop_delete_task(self, taskid: str) -> dict[str, object]: + """Stop a delete task. + + Parameters + ---------- + taskid : str + A unique ID for the delete task which is obtained from `start_delete_task` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def delete_delete_task(self, path: str | list[str], recursive: Optional[bool] = True, search_taskid: Optional[str] = None) -> dict[str, object]: + """ Delete files/folders. This is a blocking method. The response is not returned until the deletion operation is completed. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to delete. + recursive : Optional[bool], optional + Defaults to `True`. + If `true` : Recursively delete files within a folder. + If `false` : Only delete first-level file/folder. If a deleted folder contains any file, an error occurs because the folder can't be directly deleted. + search_taskid : Optional[str], optional + A unique ID for the search task which is obtained from `search_start` method. It's used to delete the file in the search result. Defaults to `None` + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Delete' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'delete', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'recursive': recursive, + 'search_taskid': search_taskid + } + return self.request_data(api_name, api_path, req_param) + + def start_extract_task(self, file_path: str, dest_folder_path: str, overwrite: Optional[bool] = False, + keep_dir: Optional[bool] = True, create_subfolder: Optional[bool] = False, codepage: Optional[str] = None, + password: Optional[str] = None, item_id: Optional[str | list[str]] = None + ) -> dict[str, object]: + """Start to extract an archive. This is a non-blocking method. You should poll a request with `get_extract_status` method to get the task status or stop the task with `stop_extract_task` method. + + Parameters + ---------- + file_path : str + A file path of an archive to be extracted, starting with a shared folder + dest_folder_path : str + A destination folder path starting with a shared folder to which the archive will be extracted. + overwrite : Optional[bool], optional + Whether or not to overwrite if the extracted file exists in the destination folder. Defaults to `False` + keep_dir : Optional[bool], optional + Whether to keep the folder structure within an archive. Defaults to `True` + create_subfolder : Optional[bool], optional + Whether to create a subfolder with an archive name which archived files are extracted to. Defaults to `False` + codepage : Optional[str], optional + The language codepage used for decoding file name with an archive. Defaults to `None` + All fields known are: `["enu","cht","chs","krn","ger","fre","ita","spn","jpn","dan","nor","sve","nld","rus","plk","ptb","ptg","hun","trk","csy"]` + password : Optional[str], optional + The password for extracting the file. Defaults to `None` + item_id : Optional[str | list[str]], optional + Item IDs of archived files used for extracting files within an archive. Item IDs could be listed by requesting the `get_file_list_of_archive` method. Defaults to `None` + + Returns + ------- + dict[str, object] + Unique task ID for the extract task. + + Example return + ---------- + ```json + { + "data": { + "taskid": "FileStation_51CBB59C68EFE6A3" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'file_path': file_path, + 'dest_folder_path': dest_folder_path, + 'overwrite': overwrite, + 'keep_dir': keep_dir, + 'create_subfolder': create_subfolder, + 'codepage': codepage, + 'password': password, + 'item_id': json.dumps(item_id) if isinstance(item_id, list) else item_id + } + return self.request_data(api_name, api_path, req_param)['data']['taskid'] + + def get_extract_status(self, taskid: str) -> dict[str, object]: + """Get the extract task status + + Parameters + ---------- + taskid : str + A unique ID for the extract task which is obtained from `start_extract_task` method + + Returns + ------- + dict[str, object] + Information about the extract task + + Example return + ---------- + ```json + { + "data": { + "dest_folder_path": "/download/download", + "finished": false, + "progress": 0.1 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def stop_extract_task(self, taskid: str) -> dict[str, object]: + """Stop the extract task + + Parameters + ---------- + taskid : str + A unique ID for the extract task which is obtained from `start_extract_task` method + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def get_file_list_of_archive(self, file_path: str, offset: Optional[int] = 0, limit: Optional[int] = -1, + sort_by: Optional[str] = 'name', sort_direction: Optional[str] = 'asc', codepage: Optional[str] = None, + password: Optional[str] = None, item_id: Optional[str] = None + ) -> dict[str, object]: + """ List archived files contained in an archive + + Parameters + ---------- + file_path : str + An archive file path starting with a shared folder to list. + offset : Optional[int], optional + Specify how many archived files are skipped before beginning to return listed archived files in an archive. Defaults to `0`. + limit : Optional[int], optional + Number of archived files requested. -1 indicates in an archive to list all archived files. Defaults to `-1`. + sort_by : Optional[str], optional + Specify which archived file information to sort on. Defaults to `'name'` + All fields known are: `["name","size","pack_size","mtime"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `'asc'` + All possible direction are: `["asc","desc"]`. + codepage : Optional[str], optional + The language codepage used for decoding file name with an archive. Defaults to `None` + All fields known are: `["enu","cht","chs","krn","ger","fre","ita","spn","jpn","dan","nor","sve","nld","rus","plk","ptb","ptg","hun","trk","csy"]` + password : Optional[str], optional + The password for extracting the file.. Defaults to `None` + item_id : Optional[str], optional + Item ID of an archived folder to be listed within an archive. (None) or -1 will list archive files in a root folder within an archive. Defaults to `None` + + Returns + ------- + dict[str, object] + Information about the archived files + + Example return + ---------- + ```json + { + "data": { + "items": [ + { + "is_dir": false, + "item_id": 1, + "mtime": "2013-02-03 00:17:12", + "name": "ITEMA_20445972-0.mp3", + "pack_size": 51298633, + "path": "ITEMA_20445972-0.mp3", + "size": 51726464 + }, + { + "is_dir": false, + "item_id": 0, + "mtime": "2013-03-03 00:18:12", + "name": "ITEMA_20455319-0.mp3", + "pack_size": 51434239, + "path": "ITEMA_20455319-0.mp3", + "size": 51896448 + } + ], + "total":2 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Extract' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'file_path': file_path, + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'codepage': codepage, + 'password': password, + 'item_id': item_id + } + return self.request_data(api_name, api_path, req_param) + + def start_file_compression(self, path: str | list[str], dest_file_path: str, level: Optional[int] = 'moderate', + mode: Optional[str] = 'add', format: Optional[str] = 'zip', password: Optional[str] = None + ) -> dict[str, object] | tuple[str]: + """Start to compress file(s)/folder(s). + + Parameters + ---------- + path : str | list[str] + One or more file paths to be compressed, starting with a shared folder. + dest_file_path : str + A destination file path (including file name) of an archive for the compressed archive. + level : Optional[int], optional + Defaults to `'moderate'`. + Compress level used, could be one of following values: + - `moderate`: moderate compression and normal compression speed. + - `store`: pack files with no compress. fastest: fastest compression speed but less compression. + - `best`: slowest compression speed but optimal compression. + mode : Optional[str], optional + Defaults to `'add'` + Compress mode used, could be one of following values: + - `add`: Update existing items and add new files. If an archive does not exist, a new one is created. + - `update`: Update existing items if newer on the file system and add new files. If the archive does not exist create a new archive. + - `refreshen`: Update existing items of an archive if newer on the file system. Does not add new files to the archive. + - `synchronize`: Update older files in the archive and add files that are not already in the archive. + format : Optional[str], optional + The compress format, ZIP or 7z format. Defaults to `'zip'` + All fields known are: `["zip","7z"]` + password : Optional[str], optional + The password for the archive. Defaults to `None` + + Returns + ------- + dict[str, object] | tuple[str] + Unique task ID for the compress task. + + Example return + ---------- + ```json + { + "data": { + "taskid": "FileStation_51CBB25CC31961FD" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Compress' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'start', + 'path': json.dumps(path) if isinstance(path, list) else path, + 'dest_file_path': dest_file_path, + 'level': level, + 'mode': mode, + 'format': format, + 'password': password + } + return self.request_data(api_name, api_path, req_param) + + def get_compress_status(self, taskid: str) -> dict[str, object]: + """ Get the compress task status + + Parameters + ---------- + taskid : str + A unique ID for the compress task. This is obtained from `start_file_compression` method. + + Returns + ------- + dict[str, object] + Information about the compress task + + Example return + ---------- + ```json + { + "data": { + "dest_file_path": "/download/download.zip", + "finished": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Compress' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def stop_compress_task(self, taskid: str) -> dict[str, object]: + """Stop the compress task. + + Parameters + ---------- + taskid : str + A unique ID for the compress task. This is obtained from `start_file_compression` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Compress' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'stop', + 'taskid': taskid + } + return self.request_data(api_name, api_path, req_param) + + def get_list_of_all_background_task(self, offset: Optional[int] = 0, limit: Optional[int] = 0, + sort_by: Optional[str] = 'crtime', sort_direction: Optional[str] = 'asc', api_filter: Optional[str | list[str]] = None + ) -> dict[str, object]: + """List all background tasks including copy, move, delete, compress and extract tasks. + + Parameters + ---------- + offset : Optional[int], optional + Specify how many background tasks are skipped before beginning to return listed background tasks. Defaults to `0` + limit : Optional[int], optional + Number of background tasks requested. 0 indicates to list all background tasks. Defaults to `0` + sort_by : Optional[str], optional + Specify which information of the background task to sort on. Defaults to `'crtime'` + All fields known are: `["crtime","finished"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `'asc'` + All possible direction are: `["asc","desc"]` + api_filter : Optional[str | list[str]], optional + List background tasks with one or more given API name(s). If not given, all background tasks are listed. Defaults to `None` + All fields known are: `["SYNO.FileStation.CopyMove","SYNO.FileStation.Delete","SYNO.FileStation.Compress","SYNO.FileStation.Extract"]` + + Returns + ------- + dict[str, object] + List of background tasks + + Example return + ---------- + ```json + { + "data": { + "tasks": [ + { + "api": "SYNO.FileStation.CopyMove", + "crtime": 1372926088, + "finished": true, + "method": "start", + "params": { + "accurate_progress": true, + "dest_folder_path": "/video/test", + "overwrite": true, + "path": [ + "/video/test2/test.avi" + ], + "remove_src": false + }, + "path": "/video/test2/test.avi", + "processed_size": 12800, + "processing_path": "/video/test2/test.avi", + "progress": 1, + "taskid": "FileStation_51D53088860DD653", + "total": 12800, + "version": 1 + }, + { + "api": "SYNO.FileStation.Compress", + "crtime": 1372926097, + "finished": true, + "method": "start", + "params": { + "dest_file_path": "/video/test/test.zip", + "format": "zip", + "level": "", + "mode": "", + "password": "", + "path": [ + "/video/test/test.avi" + ] + }, + "progress": 0, + "taskid": "FileStation_51D53091A82CD948", + "total": -1, + "version": 1 + }, + { + "api": "SYNO.FileStation.Extract", + "crtime": 1372926103, + "finished": true, + "method": "start", + "params": { + "create_subfolder": false, + "dest_folder_path": "/video/test", + "file_path": [ + "/video/test/test.zip" + ], + "keep_dir": true, + "overwrite": false + }, + "progress": 1, + "taskid": "FileStation_51D530978633C014", + "total": -1, + "version": 1 + }, + { + "api": "SYNO.FileStation.Delete", + "crtime": 1372926110, + "finished": true, + "method": "start", + "params": { + "accurate_progress": true, + "path": [ + "/video/test/test.avi" + ] + }, + "path": "/video/test/test.avi", + "processed_num": 1, + "processing_path": "/video/test/test.avi", + "progress": 1, + "taskid": "FileStation_51D5309EE1E10BD9", + "total": 1, + "version": 1 + } + ], + "offset": 0, + "total": 4 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.BackgroundTask' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'offset': offset, + 'limit': limit, + 'sort_by': sort_by, + 'sort_direction': sort_direction, + 'filter': json.dumps(api_filter) if isinstance(api_filter, list) else api_filter + } + return self.request_data(api_name, api_path, req_param) + + def clear_all_finished_background_task(self, taskid: Optional[str | list[str]] = None) -> dict[str, object]: + """Delete all finished background tasks. + + Parameters + ---------- + taskid : Optional[str | list[str]], optional + Unique IDs of finished copy, move, delete, compress or extract tasks. If it's not given, all finished tasks are deleted. Defaults to `None` + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.BackgroundTask' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'clear_finished', + 'taskid': json.dumps(taskid) if isinstance(taskid, list) else taskid + } + return self.request_data(api_name, api_path, req_param) + + def get_file(self, path: str | list[str], mode: str, dest_path: str = ".", chunk_size: int = 8192, verify: bool = False) -> Optional[io.BytesIO]: + """Download a file + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to be downloaded. When more than one file is to be downloaded, files/folders will be compressed as a zip file. + mode : str + Mode used to download files/folders, value could be: + - `open`: print the file content to stdout + - `download`: write the file content to a file based on the `dest_path` parameter + - `serve`: return the file content as a stream + dest_path : str, optional + Destination folder where the file is downloaded, if mode is `download`. Defaults to `"."` + chunk_size : int, optional + Size of chunk to download. Defaults to `8192` + verify : bool, optional + If `True` use HTTPS else use HTTP. Defaults to `False` + + Returns + ------- + Optional[io.BytesIO] + If mode is `serve`, return the file content as a stream + + """ + api_name = 'SYNO.FileStation.Download' + info = self.gen_list[api_name] + api_path = info['path'] + + session = requests.session() + str_path: str = json.dumps(path) if isinstance(path, list) else path + url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=download&path=%s&mode=%s&_sid=%s' % ( + api_name, info['maxVersion'], str_path, mode, self._sid) + + if mode == r'open': + with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: + r.raise_for_status() + for chunk in r.iter_content(chunk_size=chunk_size): + if chunk: # filter out keep-alive new chunks + sys.stdout.buffer.write(chunk) + + if mode == r'download': + with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: + r.raise_for_status() + if not os.path.isdir(dest_path): + os.makedirs(dest_path) + + if isinstance(path, list): + if len(path) > 1: + file_name = f"{os.path.splitext(os.path.basename(path[0]))[0]}.zip" + else: + file_name = os.path.basename(path[0]) + else: + file_name = os.path.basename(path) + with open(dest_path + "/" + file_name, 'wb') as f: + for chunk in r.iter_content(chunk_size=chunk_size): + if chunk: # filter out keep-alive new chunks + f.write(chunk) + + if mode == r'serve': + with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: + r.raise_for_status() + return io.BytesIO(r.content) + + def generate_file_tree(self, folder_path: str, tree: Tree) -> None: + """Generate the file tree based on the folder path you give, you need to create the root node before call this function + + Parameters + ---------- + folder_path : str + Folder path to generate file tree + tree : Tree + Instance of the Tree of lib "Treelib", this will be modified by the method + + """ + data: dict = self.get_file_list( + folder_path=folder_path + ).get("data") + + files = data.get("files") + file: dict + for file in files: + file_name: str = file.get("name") + file_path: str = file.get("path") + if file.get("isdir"): + + tree.create_node(file_name, file_path, parent=folder_path) + self.generate_file_tree(file_path, tree) + else: + tree.create_node(file_name, file_path, parent=folder_path) + diff --git a/synology_api/DSM/Package/PackageCenter.py b/synology_api/DSM/Package/PackageCenter.py new file mode 100644 index 00000000..bae577a8 --- /dev/null +++ b/synology_api/DSM/Package/PackageCenter.py @@ -0,0 +1,1078 @@ +import json +from typing import List +from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor +import os, requests, tqdm, time +from synology_api import base_api + +class PackageCenter(base_api.BaseApi): + """ + Core Package API implementation. Implementation of the PackageCenter application APIs + """ + + def get_package(self, package_id: str, additional: List[str] = []) -> dict: + """Get infos of a package + + Parameters + ---------- + package_id : str + Package ID + additional : List[str], optional + Additional field to retrieves. Defaults to `[]` + All filed known are: + `["status","dsm_apps"]` + + Returns + ------- + dict + Informations about the package + + Example return + ---------- + ```json + { + "data": { + "additional": { + "dsm_apps": " com.plexapp.plexmediaserver", + "status": "running", + "status_code": 0, + "status_description": "retrieve from status script", + "status_origin": "running" + }, + "id": "PlexMediaServer", + "name": "Plex Media Server", + "timestamp": 1739228562839, + "version": "1.41.3.9314-72009314" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "get", + "version": info['minVersion'], + "id": package_id, + "additional": json.dumps(additional) + } + return self.request_data(api_name, api_path, req_param) + + def list_installed(self, additional: list = [], ignore_hidden: bool = False) -> dict: + """List installed packages + Parameters + ---------- + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: + `["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url", + "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", + "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages","install_type", + "autoupdate", "silent_upgrade", "installing_progress", "ctl_uninstall", "updated_at", "status", + "url","available_operation"]`. + ignore_hidden : bool + TODO: Write description + + Returns + ------- + dict + List of packages installed on the NAS + + Example return + -------------- + ```json + { + "data": { + "packages": [ + { + "additional": { + "install_type": "" + }, + "id": "ActiveBackup-Office365", + "name": "Active Backup for Microsoft 365", + "timestamp": 1738880043640, + "version": "2.5.5-14034" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "list", + "version": info['maxVersion'], + "ignore_hidden": ignore_hidden, + "additional": json.dumps(additional) + } + + return self.request_data(api_name, api_path, req_param) + + def list_installable(self) -> dict: + """List installable packages + Returns + ------- + dict + List of beta_package, categories and packages available + + Example return + -------------- + ```json + { + "data": { + "banners": [], + "beta_packages": [...], + "categories": [...], + "packages": [...] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Server' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "list", + "version": info['maxVersion'], + "blforcereload": False, + "blloadothers": False + } + + return self.request_data(api_name, api_path, req_param) + + def get_package_center_settings(self) -> dict: + """Get package center settings + Returns + ------- + dict + List settings of the Package center + + Example return + -------------- + ```json + { + "data": { + "autoupdateall": false, + "autoupdateimportant": true, + "default_vol": "/volume1", + "enable_autoupdate": true, + "enable_dsm": true, + "enable_email": false, + "mailset": true, + "trust_level": 0, + "update_channel": true, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 184.72 GB )", + "mount_point": "/volume1", + "size_free": "198336327680", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.14 GB )", + "mount_point": "/volume2", + "size_free": "2567467421696", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Setting' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "get", + "version": info['maxVersion'], + } + + return self.request_data(api_name, api_path, req_param) + + def set_package_center_settings(self, + enable_email: bool, enable_dsm: bool, enable_autoupdate: bool, + autoupdateall: bool, autoupdateimportant: bool, + default_vol: str, update_channel: str + ) -> dict: + """Set settings of the package center + Parameters + ---------- + enable_email : bool + Enable email notification + + enable_dsm : bool + Enable desktop notification + + enable_autoupdate: bool + Update packages automatically + + autoupdateall : bool + Auto update all packages + + autoupdateimportant : bool + Auto update "important" packages + + default_vol : str + Default volume for installation, all your volumes or `"no_default_vol" = Always ask me` + + udpate_channel : str + "stable" => Disable beta packages + "beta" => Enable beta packages + + Returns + ------- + dict + Return some settings + + Example return + -------------- + ```json + { + "data": { + "enable_dsm": true, + "enable_email": false, + "update_channel": "stable" + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Package.Setting' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "set", + "version": info['maxVersion'], + "enable_email": enable_email, + "enable_dsm": enable_dsm, + "enable_autoupdate": enable_autoupdate, + "autoupdateall": autoupdateall, + "autoupdateimportant": autoupdateimportant, + "default_vol": default_vol, + "update_channel": update_channel + } + + return self.request_data(api_name, api_path, req_param) + + def get_package_center_infos(self) -> dict: + """Get package center informations + Returns + ------- + dict + List of configs + + Return example + -------------- + ```json + { + "data": { + "config": { + "auth_key": "------------------------------", + "blBetaChannel": false, + "blOtherServer": false, + "def_void": "", + "ds_build": "72806", + "ds_major": "7", + "ds_minor": "2", + "ds_timezone": "Amsterdam", + "ds_unique": "synology_r1000_723+", + "myPayBaseURL": "https://payment.synology.com", + "myds_id": "7886858", + "serial": "2260TPR7X30E6", + "success": true + }, + "prerelease": { + "agreed": true, + "success": true + }, + "term": { + "agreed_term_version": "0003", + "curr_term_version": "0003", + "success": true + } + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Info' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "get", + "version": info['maxVersion'], + } + return self.request_data(api_name, api_path, req_param) + + def feasibility_check_install(self, packages: List[str]) -> dict: + """Check if installation is possible + + Parameters + ---------- + packages : List[str] + List of package IDs to check for feasibility + + Returns + ------- + dict + _description_ + + Example return + ---------- + ```json + { + "data": { + "template": "data" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Setting' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "feasibility_check", + "version": info['maxVersion'], + "type": "install_check", + "packages": json.dumps(packages) + } + + return self.request_data(api_name, api_path, req_param) + + def download_package(self, url: str, package_id: str, checksum: str, filesize: str) -> dict: + """Start download of the package, return a taskId for check status + + Parameters + ---------- + url : str + Url that can be retrieve from package info using `get_installable` function, in the `link` field + package_id : str + Package ID that can be retrieve from package info using `get_installable` function, in the `id` field + checksum : str + Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field + filesize : str + Filesize that can be retrieve from package info using `get_installable` function, in the `size` field + + Returns + ------- + dict + Retreive first progress of the download and the taskid used to check download status with `get_dowload_package_status` function + + Example return + ---------- + ```json + { + "data": { + "progress": 1.0000000000000001e-05, + "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Installation' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "install", + "version": info['minVersion'], + "operation": "install", + "type": 0, + "blqinst": False, + "url": url, + "name": package_id, + "checksum": checksum, + "filesize": filesize + } + return self.request_data(api_name, api_path, req_param) + + def get_dowload_package_status(self, task_id: str) -> dict: + """Get current download status of the package + + Parameters + ---------- + task_id : str + task ID retrieve from response of `download_package` function + + Returns + ------- + dict + Retrieve informations about the download, important info is the `progress` field + + Example return + ---------- + ```json + { + "data": { + "beta": false, + "blqinst": false, + "finished": false, + "id": "DhcpServer", + "installing": false, + "name": "DhcpServer", + "pid": 27844, + "progress": 1.0000000000000001e-05, + "remote_link": "https://global.synologydownload.com/download/Package/spk/DhcpServer/1.0.2-0046/DhcpServer-x86_64-1.0.2-0046.spk", + "size": "1378697", + "success": true, + "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer", + "tmp_folder": "/volume1/@tmp/synopkg/download.esnnkb" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Installation' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "status", + "version": info['minVersion'], + "task_id": task_id + } + return self.request_data(api_name, api_path, req_param) + + def check_installation_from_download(self, task_id: str) -> dict: + """Get info about downloaded package file, response field is used for `check_installation` and `install_package` function + + Parameters + ---------- + task_id : str + task ID retrieve from response of `download_package` function + + Returns + ------- + dict + Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function + + Example return + ---------- + ```json + { + "data": { + "description": "DHCP Server turns your DiskStation into a DHCP server within LAN to assign dynamic IP addresses and manage DHCP clients.", + "distributor": "", + "dsm_apps": "SYNO.SDS.DHCP.Instance", + "filename": "/volume1/@tmp/synopkg/download.esnnkb/@SYNOPKG_DOWNLOAD_DhcpServer", + "id": "DhcpServer", + "install_on_cold_storage": false, + "install_reboot": false, + "install_type": "system", + "maintainer": "Synology Inc.", + "name": "DHCP Server", + "startable": true, + "status": "non_installed", + "status_code": 255, + "status_description": "failed to locate given package", + "status_origin": "non_installed", + "version": "1.0.2-0046" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Installation.Download' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "check", + "version": info['minVersion'], + "taskid": task_id + } + return self.request_data(api_name, api_path, req_param) + + def upload_package_file(self, file_path: str, verify: bool = False, progress_bar: bool = True, additional: list = []) -> dict: + """Upload a file for install a package + + Parameters + ---------- + file_path : str + File path + verify : bool, optional + Use https. Defaults to `False` + progress_bar : bool, optional + Enable progress bar in the terminal. Defaults to `True` + additional : list, optional + Additional field to retrieves. Defaults to `[]` + All fields know are: + `["description","maintainer","distributor","startable","dsm_apps","status","install_reboot", + "install_type","install_on_cold_storage","break_pkgs","replace_pkgs"]`. + + Returns + ------- + dict + Informations about the uploaded file for installation + + Example return + ---------- + ```json + { + "data": { + "additional": { + "break_pkgs": null, + "description": "Plex organizes all of your personal media so you can easily access and enjoy it.", + "distributor": "", + "dsm_apps": " com.plexapp.plexmediaserver", + "install_on_cold_storage": false, + "install_reboot": false, + "install_type": "", + "maintainer": "Plex Inc", + "replace_pkgs": { "Plex Media Server": "" }, + "startable": true, + "status": "running", + "status_code": 0, + "status_description": "retrieve from status script", + "status_origin": "running" + }, + "codesign_error": 4532, + "id": "PlexMediaServer", + "name": "Plex Media Server", + "task_id": "@SYNOPKG_UPLOAD_17392283048566DD3", + "version": "1.41.3.9314-72009314" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Installation' + info = self.core_list[api_name] + api_path = info['path'] + filename = os.path.basename(file_path) + + session = requests.session() + + with open(file_path, 'rb') as payload: + url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=upload&_sid=%s' % ( + api_name, info['minVersion'], self._sid) + + encoder = MultipartEncoder({ + 'additional': json.dumps(additional), + 'file': (filename, payload, 'application/octet-stream') + }) + + if progress_bar: + bar = tqdm.tqdm(desc='Upload Progress', + total=encoder.len, + dynamic_ncols=True, + unit='B', + unit_scale=True, + unit_divisor=1024 + ) + + monitor = MultipartEncoderMonitor(encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) + + r = session.post( + url, + data=monitor, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': monitor.content_type} + ) + + else: + r = session.post( + url, + data=encoder, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': encoder.content_type} + ) + + session.close() + if r.status_code != 200 or not r.json()['success']: + return r.status_code, r.json() + + return r.json() + + def get_default_install_volume(self) -> dict: + """Get default install volume for package + + Returns + ------- + dict + Return default volume, if default volume is set to `Always ask me` it return error 4501 + + Example return + ---------- + ```json + { + "data": { + "default_vol": "/volume1" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Setting.Volume' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "get", + "version": info['maxVersion'], + } + + return self.request_data(api_name, api_path, req_param) + + def check_installation(self, + package_id: str, install_type: str = "", install_on_cold_storage: bool = False, + blCheckDep: bool = False, replacepkgs: dict = {} + ) -> dict: + """Check installation of the package on the default volume + + Parameters + ---------- + package_id : str + Id of the package to install + install_type : str, optionnal + Installation type, Defaults to `""`. TODO: Add description and possible types + install_on_cold_storage : bool, optional + Defaults to `False`. TODO: Add description + blCheckDep : bool, optional + Defaults to `False`. TODO: Add description + replacepkgs : dict, optional + Defaults to `{}`. TODO: Add description + + Returns + ------- + dict + List of usefull informations about volumes + + Example return + ---------- + ```json + { + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 184.52 GB )", + "mount_point": "/volume1", + "size_free": "198126022656", + "size_total": "206158430208", + "vol_desc": "vol1", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.16 GB )", + "mount_point": "/volume2", + "size_free": "2567484923904", + "size_total": "3623234412544", + "vol_desc": "vol2", + "volume_features": [] + } + ], + "volume_path": "/volume1" + }, + "success": true, + } + ``` + """ + + api_name = 'SYNO.Core.Package.Installation' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "check", + "version": info['maxVersion'], + "id": package_id, + "install_type": install_type, + "install_on_cold_storage": install_on_cold_storage, + "breakpkgs": None, + "blCheckDep": blCheckDep, + "replacepkgs": json.dumps(replacepkgs) + } + + return self.request_data(api_name, api_path, req_param) + + def upgrade_package(self, task_id: str, check_codesign: bool = False, force: bool = False, installrunpackage: bool = True, extra_values: dict = {}) -> dict: + """Upgrade an existing package + + Parameters + ---------- + task_id : str + Task id of the download or the upload file + check_codesign : bool, optional + Check signature of the source code of the package (is it a Synology one). Defaults to `False` + force : bool, optional + Force installation. Defaults to `False` + installrunpackage : bool, optional + Run package after installation. Defaults to `True` + extra_values : dict, optional + Extra values due to some package installation. Defaults to `{}` + All known extra values are: + - Surveillance station + ```json + { + "chkSVS_Alias": true, + "strSVS_Alias": "cam", + "chkSVS_HTTP": true, + "strSVS_HTTP": "9900", + "chkSVS_HTTPS": true, + "strSVS_HTTPS": "9901" + } + ``` + + Returns + ------- + dict + Message and some info about installation + + Example return + ---------- + ```json + { + "data": { + "message": "

Installation Successful!

\n

Note: If Plex cannot access your media, verify user PlexMediaServer is granted permission in Control Panel.


\nSet access to your media share(s) by performing the following steps:

\n1. Open Control Panel and select Shared Folder
\n2. Select the share which contains your media and click Edit
\n3. Click the Permissions tab
\n4. Change the dropdown from Local Users to System internal user
\n5. Check the Read/Write checkbox for the PlexMediaServer user
\n6. Click Save to confirm the new permissions
\n7. Repeat steps 2-6 for each share you want Plex Media Server to access
\n", + "packageName": "Plex Media Server", + "worker_message": [] + }, + "success": true, + } + ``` + """ + + api_name = 'SYNO.Core.Package.Installation' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method":"upgrade", + "version":info['minVersion'], + "type":0, + "check_codesign": check_codesign, + "force": force, + "installrunpackage": installrunpackage, + "task_id": task_id, + "extra_values": json.dumps(extra_values), + } + return self.request_data(api_name, api_path, req_param) + + def install_package(self, package_id:str, volume_path: str, file_path: str, check_codesign: bool = True, force: bool = True, installrunpackage: bool = True, extra_values: dict = {}) -> dict: + """Install a package that is already downloaded + + Parameters + ---------- + package_id : str + Id of the package to install + volume_path : str + Volume path of the installation, can get from `check_installation` function + file_path : str + File path of the installation, can get from `check_installation_from_download` function + check_codesign : bool, optional + Check signature of the source code of the package (is it a Synology one). Defaults to `False` + force : bool, optional + Force installation. Defaults to `False` + installrunpackage : bool, optional + Run package after installation. Defaults to `True` + extra_values : dict, optional + Extra values due to some package installation. Defaults to `{}` + All known extra values are: + - Surveillance station + ```json + { + "chkSVS_Alias": true, + "strSVS_Alias": "cam", + "chkSVS_HTTP": true, + "strSVS_HTTP": "9900", + "chkSVS_HTTPS": true, + "strSVS_HTTPS": "9901" + } + ``` + Returns + ------- + dict + Message and some info about installation + + Example return + ---------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Package.Installation", + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 185.09 GB )", + "mount_point": "/volume1", + "size_free": "198739943424", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.17 GB )", + "mount_point": "/volume2", + "size_free": "2567495630848", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ], + "volume_path": "/volume1" + }, + "method": "check", + "success": true, + "version": 1 + }, + { + "api": "SYNO.Core.Package.Installation", + "data": { + "packageName": "Text Editor", + "worker_message": [] + }, + "method": "install", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` + """ + compound = [ + { + "api": "SYNO.Core.Package.Installation", + "method": "check", + "version": self.core_list['SYNO.Core.Package.Installation']['minVersion'], + "id": package_id, + "install_type": "", + "install_on_cold_storage": False, + "breakpkgs": None, + "blCheckDep": False, + "replacepkgs": None + }, + { + "api": "SYNO.Core.Package.Installation", + "method":"install", + "version":self.core_list["SYNO.Core.Package.Installation"]['minVersion'], + "type":0, + "volume_path": volume_path, + "path": file_path, + "check_codesign": check_codesign, + "force": force, + "installrunpackage": installrunpackage, + "extra_values": json.dumps(extra_values), + } + ] + return self.batch_request(compound=compound) + + def uninstall_package(self, package_id: str) -> dict: + """Uninstall a package + + Parameters + ---------- + package_id : str + Id of the package to uninstall + + Returns + ------- + dict + Possible message to the user + + Example return + ---------- + ```json + { + "data": { + "message": "", + "worker_message": [] + }, + "success": true + } + ``` + """ + + if not self._is_package_already_installed(package_id=package_id): + raise Exception(f"""Package "{package_id}" is not installed, it cannot be uninstalled""") + + api_name = 'SYNO.Core.Package.Uninstallation' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + "method": "uninstall", + "version": info['minVersion'], + "id": package_id, + "dsm_apps": "" + } + + return self.request_data(api_name, api_path, req_param) + + def _is_package_already_installed(self, package_id: str) -> bool: + response: dict = self.list_installed() + data: dict = response.get("data") + installed_packages = data.get("packages") + package_infos: dict = next((package for package in installed_packages if package["id"] == package_id), None) + return package_infos != None + + def easy_install(self, package_id: str, volume_path: str, install_dependencies: bool = True) -> dict: + """Execute an "easy" installation process of the package + + Parameters + ---------- + package_id : str + Package ID to install + volume_path : str + Volume path where you want to install the package + install_dependencies : bool, optional + If you want to install dependencies. Defaults to `True` + + Returns + ------- + dict + Information about installation, same as `install_package` function + + Example return + ---------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Package.Installation", + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 185.11 GB )", + "mount_point": "/volume1", + "size_free": "198759485440", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.17 GB )", + "mount_point": "/volume2", + "size_free": "2567495565312", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ], + "volume_path": "/volume1" + }, + "method": "check", + "success": true, + "version": 1 + }, + { + "api": "SYNO.Core.Package.Installation", + "data": { + "packageName": "Text Editor", + "worker_message": [] + }, + "method": "install", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` + """ + + # Package already installed + if self._is_package_already_installed(package_id): + raise Exception(f"""Package "{package_id}" already installed""") + + response: dict = self.list_installable() + data: dict = response.get("data") + installable_packages = data.get("packages") + package_infos: dict = next((package for package in installable_packages if package["id"] == package_id), None) + # Package not found + if package_infos == None: + raise Exception(f"""Package "{package_id}" not found in installable list, installation not possible""") + + + # Check dependencies + deppkgs = package_infos.get("deppkgs") + if deppkgs: + if not install_dependencies: + raise Exception(f"""Package "{package_id}" has dependencies that needs to be installed but "install_dependencies" is set to "False" """) + deppkg: str + for deppkg in deppkgs: + if not self._is_package_already_installed(deppkg): + print(f"""Installation of dependency "{deppkg}" for "{package_id}" started""") + self.easy_install(package_id=deppkg, volume_path=volume_path) + print(f"""Installation of dependency "{deppkg}" for "{package_id}" done""") + + # Store information of the package + url = package_infos.get("link") + filesize = package_infos.get("size") + version = package_infos.get("version") + checksum = package_infos.get("md5") + + ## Start installation sequence + + # Start download the package installation file + response: dict = self.download_package(url=url, package_id=package_id, checksum=checksum, filesize=filesize) + data: dict = response.get("data") + task_id = data.get("taskid") + + # Create progress bar of the status + response: dict = self.get_dowload_package_status(task_id=task_id) + data: dict = response.get("data") + progress = data.get("progress") + if not data.get("finished"): + with tqdm.tqdm(total=100) as pbar: + while not data.get("finished"): + response: dict = self.get_dowload_package_status(task_id=task_id) + data: dict = response.get("data") + progress: float = data.get("progress") + if progress: + pbar.update(int(progress*100)) + time.sleep(0.500) + pbar.update(100) + + print(f"""Download of "{package_id}" done""") + + # Check downloaded file + response: dict = self.check_installation_from_download(task_id=task_id) + data: dict = response.get("data") + status = data.get("status") + file_path = data.get("filename") + print(f"""Downloaded file status : {status}""") + + # Check installation + response = self.check_installation(package_id=package_id) + + # Install package + extra_values = {} + if package_id == "SurveillanceStation": + extra_values = { + "chkSVS_Alias": True, + "strSVS_Alias": "cam", + "chkSVS_HTTP": True, + "strSVS_HTTP": "9900", + "chkSVS_HTTPS": True, + "strSVS_HTTPS": "9901" + } + + return self.install_package(package_id=package_id, volume_path=volume_path, file_path=file_path, extra_values=extra_values) diff --git a/synology_api/DSM/Package/__init__.py b/synology_api/DSM/Package/__init__.py new file mode 100644 index 00000000..b624c349 --- /dev/null +++ b/synology_api/DSM/Package/__init__.py @@ -0,0 +1,2 @@ +from .FileStation import FileStation +from .PackageCenter import PackageCenter \ No newline at end of file diff --git a/synology_api/DSM/__init__.py b/synology_api/DSM/__init__.py index ef9ed683..433754c4 100644 --- a/synology_api/DSM/__init__.py +++ b/synology_api/DSM/__init__.py @@ -1,11 +1,13 @@ from .ControlPanel import ControlPanel -from .FileStation import FileStation +from .Package.FileStation import FileStation +from .Package.PackageCenter import PackageCenter from synology_api import base_api class DSM(base_api.BaseApi): _ctrl_panel = None _file_station = None + _package_center = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -27,4 +29,13 @@ def FileStation(self): self._file_station = FileStation.__new__(FileStation) # Share the state self._file_station.__dict__ = self.__dict__ - return self._file_station \ No newline at end of file + return self._file_station + + @property + def PackageCenter(self): + if self._package_center is None: + # Create PackageCenter instance without calling __init__ + self._package_center = PackageCenter.__new__(PackageCenter) + # Share the state + self._package_center.__dict__ = self.__dict__ + return self._package_center \ No newline at end of file diff --git a/synology_api/__init__.py b/synology_api/__init__.py index 93c91250..2c0f8104 100755 --- a/synology_api/__init__.py +++ b/synology_api/__init__.py @@ -27,4 +27,29 @@ virtualization, \ universal_search, \ snapshot, \ - surveillancestation \ No newline at end of file + surveillancestation + +from .DSM import DSM +from .DSM.ControlPanel import \ + ControlPanel, \ + ApplicationPrivileges, \ + DomainLDAP, \ + ExternalAccess, \ + ExternalDevices, \ + FileServices, \ + HardwarePower, \ + IndexingService, \ + InfoCenter, \ + LoginPortal, \ + Network, \ + Notifications, \ + RegionalOptions, \ + Security, \ + SharedFolder, \ + SynologyAccount, \ + TaskScheduler, \ + TerminalSNMP, \ + UpdateRestore, \ + UserGroup +from .DSM.Package import \ + FileStation \ No newline at end of file diff --git a/synology_api/error_codes.py b/synology_api/error_codes.py index fe83f9d8..7e27239e 100644 --- a/synology_api/error_codes.py +++ b/synology_api/error_codes.py @@ -124,6 +124,37 @@ 420: 'Illegal file name on FAT file system', 421: 'Device or resource busy', 599: 'No such task of the file operation', + 800: 'A folder path of favorite folder is already added to user\'s favorites', + 801: 'A name of favorite folder conflicts with an existing folder path in the user\'s favorties', + 802: 'There are too many favorites to be added', + 900: 'Failed to delete file(s)/folder(s). More information in object', + 1000: 'Failed to copy files/folders. More information in object.', + 1001: 'Failed to move files/folders. More information in object.', + 1002: 'An error occurred at the destination. More information in object.', + 1003: 'Cannot overwrite or skip the existing file because no overwrite parameter is given.', + 1004: 'File cannot overwrite a folder with the same name, or folder cannot overwrite a file with the same name.', + 1006: 'Cannot copy/move file/folder with special characters to a FAT32 file system.', + 1007: 'Cannot copy/move a file bigger than 4G to a FAT32 file system.', + 1100: 'Failed to create a folder. More information in object.', + 1101: 'The number of folders to the parent folder would exceed the system limitation.', + 1200: 'Failed to rename it. more information in object.', + 1300: 'Failed to compress files/folders.', + 1301: ' Cannot create the archive because the given archive name is too long.', + 1400: 'Failed to extract files.', + 1401: 'Cannot open the file as archive.', + 1402: 'Failed to read archive data error', + 1403: 'Wrong password.', + 1404: 'Failed to get the file and dir list in an archive.', + 1405: 'Failed to find the item ID in an archive file.', + 1800: 'There is no Content-Length information in the HTTP header or the received size doesn\'t match the value of Content-Length information in the HTTP header', + 1801: 'Wait too long, no date can be received from client (Default maximum wait time is 3600 seconds)', + 1802: 'No filename information in the last part of file content', + 1803: 'Upload connection is cancelled', + 1804: 'Failed to upload oversized file to FAT file system', + 1805: 'Can\'t overwrite or skip the existing file, if no overwrite parameter is given', + 2000: 'Sharing link does not exist.', + 2001: 'Cannot generate sharing link because too many sharing links exist', + 2002: 'Failed to access sharing links', } # Source: https://global.synologydownload.com/download/Document/Software/DeveloperGuide/Package/Virtualization/All From be4749289c9643f617943a8ff163cf6fe52f100d Mon Sep 17 00:00:00 2001 From: fboissadier Date: Mon, 3 Mar 2025 00:05:38 +0100 Subject: [PATCH 003/126] Update "note" in docstring of FileStation.py --- synology_api/DSM/Package/FileStation.py | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/synology_api/DSM/Package/FileStation.py b/synology_api/DSM/Package/FileStation.py index 68f53b56..e843572b 100644 --- a/synology_api/DSM/Package/FileStation.py +++ b/synology_api/DSM/Package/FileStation.py @@ -172,15 +172,13 @@ def get_file_list(self, All possible direction are: `["asc","desc"]` pattern : Optional[list[str]], optional Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` - Note: - 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. + Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. filetype : Optional[str], optional "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` All fields know are: `["file","dir","all"]` goto_path : Optional[str], optional Folder path starting with a shared folder. Return all files and sub-folders within folder_path path until goto_path path recursively. Defaults to `None` - Note: - goto_path is only valid with parameter "additional" contains real_path. + Note: goto_path is only valid with parameter "additional" contains real_path. additional : Optional[list[str]], optional Additionnal field to retrieve from file. Defaults to `None` All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. @@ -300,8 +298,7 @@ def search_start(self, If searching files within a folder and subfolders recursively or not. Defaults to `None` pattern : Optional[list[str]], optional Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` - Note: - 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern.. Defaults to `None` + Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern.. Defaults to `None` extension : Optional[list[str]], optional Search for files whose extensions match a file type pattern in a case-insensitive glob pattern. If you give this criterion, folders aren't matched. Defaults to `None` filetype : Optional[str], optional @@ -399,8 +396,7 @@ def get_search_list(self, All possible direction are: `["asc","desc"]` pattern : Optional[list[str]], optional Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` - Note: - 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. + Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. filetype : Optional[str], optional "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` All fields know are: `["file","dir","all"]` @@ -854,14 +850,14 @@ def replace_all_favorite(self, path: str | list[str], name: str | list[str]) -> return self.request_data(api_name, api_path, req_param) def get_thumbnail(self, path: str, size: Optional[str] = "small", rotate: Optional[int] = None) -> bytes: - """Get a thumbnail of a file. + """ Get a thumbnail of a file. Parameters ---------- path : str A file path starting with a shared folder. size : str - The size of the thumbnail. Defaults to `None` + The size of the thumbnail. Defaults to `small` All fields known are: `["small","medium","large","original"]` rotate : Optional[int], optional The angle of the thumbnail. Defaults to `None` @@ -872,12 +868,8 @@ def get_thumbnail(self, path: str, size: Optional[str] = "small", rotate: Option bytes The thumbnail of the file. If the file is not found, it will raise an exception. - Example return - ---------- - ```json - b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR - ``` """ + api_name = 'SYNO.FileStation.Thumb' info = self.gen_list[api_name] api_path = info['path'] From 6420f9a9cba61be467f115c388c16b63ac3b19ff Mon Sep 17 00:00:00 2001 From: fboissadier Date: Fri, 25 Apr 2025 18:19:46 +0200 Subject: [PATCH 004/126] Enhance docstring in SharedFolder class to detail supported methods and actions Add Network classes of ControlPanel --- synology_api/DSM/ControlPanel/Network.py | 882 ++++++++++++++++++ synology_api/DSM/ControlPanel/SharedFolder.py | 21 +- 2 files changed, 901 insertions(+), 2 deletions(-) diff --git a/synology_api/DSM/ControlPanel/Network.py b/synology_api/DSM/ControlPanel/Network.py index f593a6e5..338685fa 100644 --- a/synology_api/DSM/ControlPanel/Network.py +++ b/synology_api/DSM/ControlPanel/Network.py @@ -1,4 +1,886 @@ from synology_api import base_api +import json class Network(base_api.BaseApi): + """ + Network class for interacting with Synology DSM network settings. + + Supported methods: + - Getters: + - Get general settings + - Get proxy settings + - Get list of gateways + - Get list of network interfaces + - Get OVS status + - Get list of bond interfaces + - Get list of ethernet interfaces + - Get list of PPPoE interfaces + - Get list of PPTP VPN interfaces + - Get list of OpenVPN with conf file VPN interfaces + - Get list of OpenVPN VPN interfaces + - Get list of L2TP VPN interfaces + - Get traffic control rules + - Get port list per service + + - Setters: + - Set general settings + - Set proxy settings + - Set ethernet interfaces + """ + + def get_general_settings(self) -> dict: + """Get general network settings. + + Returns + ------- + dict + General network settings. + + Example return + ---------- + ```json + { + "data": { + "arp_ignore": true, + "dns_manual": true, + "dns_primary": "103.86.96.100", + "dns_secondary": "192.168.1.1", + "enable_ip_conflict_detect": true, + "enable_windomain": false, + "gateway": "192.168.1.1", + "gateway_info": { + "ifname": "ovs_eth0", + "ip": "192.168.1.14", + "mask": "255.255.255.0", + "status": "connected", + "type": "ovseth", + "use_dhcp": true + }, + "ipv4_first": false, + "multi_gateway": false, + "server_name": "SERVER-NAME", + "use_dhcp_domain": true, + "v6gateway": "fe80::670:56ff:fe48:1f94" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_general_settings( + self, server_name: str, dns_manual: bool, dns_primary: str, + dns_secondary: str, arp_ignore: bool, multi_gateway: bool, + ipv4_first: bool, enable_ip_conflict_detect: bool, use_dhcp_domain: bool + ) -> dict: + """Set general network settings. + + Parameters + ---------- + server_name : str + Server name. + dns_manual : bool + Whether to set DNS manually. + dns_primary : str + Primary DNS server. + dns_secondary : str + Secondary DNS server. + arp_ignore : bool + Whether to ignore ARP. + multi_gateway : bool + Whether to enable multiple gateways. + ipv4_first : bool + Whether to prioritize IPv4. + enable_ip_conflict_detect : bool + Whether to enable IP conflict detection. + use_dhcp_domain : bool + Whether to use DHCP domain. + + Returns + ------- + dict + Result of setting general network settings. + + Example return + ---------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Network", + "data": { + "hostname_changed_and_join_domain": false + }, + "method": "set", + "success": true, + "version": 2 + } + ] + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Network' + info = self.gen_list[api_name] + compound = [ + { + 'api': api_name, + 'version': info['maxVersion'], + 'method': 'set', + 'server_name': server_name, + 'dns_manual': dns_manual, + 'dns_primary': dns_primary, + 'dns_secondary': dns_secondary, + 'arp_ignore': arp_ignore, + 'multi_gateway': multi_gateway, + 'ipv4_first': ipv4_first, + 'enable_ip_conflict_detect': enable_ip_conflict_detect, + 'use_dhcp_domain': use_dhcp_domain + } + ] + return self.batch_request(compound=compound) + + def get_proxy_settings(self) -> dict: + """Get proxy settings. + + Returns + ------- + dict + Proxy settings. + + Example return + ---------- + ```json + { + "data": { + "enable": false, + "enable_auth": false, + "enable_bypass": true, + "enable_different_host": false, + "http_host": "", + "http_port": "80", + "https_host": "", + "https_port": "80", + "password": "\t\t\t\t\t\t\t\t", + "username": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.Proxy' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_proxy_settings( + self, enable: bool, enable_auth: bool, enable_bypass: bool, + enable_different_host: bool, http_host: str, http_port: str, + https_host: str, https_port: str, username: str = None, password: str = None + ) -> dict: + """Set proxy settings. + + Parameters + ---------- + enable : bool + Whether to enable proxy. + enable_auth : bool + Whether to enable authentication. + enable_bypass : bool + Whether to enable bypass. + enable_different_host : bool + Whether to enable different host. + http_host : str + HTTP host. + http_port : str + HTTP port. + https_host : str + HTTPS host. + https_port : str + HTTPS port. + username : str, optional + Username for authentication. Default is None. + password : str, optional + Password for authentication. Default is None. + + Returns + ------- + dict + Result of setting proxy settings. + + Example return + ---------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Network.Proxy", + "method": "set", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Network.Proxy' + info = self.gen_list[api_name] + compound = [ + { + 'api': api_name, + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'enable_auth': enable_auth, + 'enable_bypass': enable_bypass, + 'enable_different_host': enable_different_host, + 'http_host': http_host, + 'http_port': http_port, + 'https_host': https_host, + 'https_port': https_port + } + ] + + if username and password: + if self.session._secure: + compound[0]['username'] = username + compound[0]['password'] = password + else: + params_enc = { + 'username': username, + 'password': password + } + compound[0].update(self.session.encrypt_params(params_enc)) + + + return self.batch_request(compound=compound) + + def get_gateway_list(self) -> dict: + """Get list of gateways. + + Returns + ------- + dict + List of gateways. + + Example return + ---------- + ```json + { + "data": { + "configs": [ + { + "class": "ethernet", + "dns": "192.168.1.1", + "gateway": "192.168.1.1", + "ifname": "ovs_eth0", + "priority": 0, + "slave": false + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.Gateway.List' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_interfaces_list(self) -> dict: + """Get list of network interfaces. + + Returns + ------- + dict + List of network interfaces. + + Example return + ---------- + ```json + { + "data": [ + { + "ifname": "ovs_eth0", + "ip": "192.168.1.14", + "mask": "255.255.255.0", + "speed": 1000, + "status": "connected", + "type": "ovseth", + "use_dhcp": true + }, + { + "ifname": "ovs_eth1", + "ip": "169.254.183.6", + "mask": "255.255.0.0", + "speed": -1, + "status": "disconnected", + "type": "ovseth", + "use_dhcp": true + }, + { + "ifname": "pppoe", + "ip": "", + "mask": "", + "speed": 0, + "status": "disconnected", + "type": "pppoe", + "use_dhcp": true + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.Interface' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_ovs_status(self) -> dict: + """Get infos if ovs is enabled or not. + + Returns + ------- + dict + Infos about ovs status. + + Example return + ---------- + ```json + { + "data": { + "enable_ovs": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.OVS' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_bond_list(self) -> dict: + """Get list of bond interfaces. + + Returns + ------- + dict + List of bond interfaces. + + Example return + ---------- + ```json + { + "data": [ + { + "block": 0, + "dns": "192.168.1.1", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "enabled": true, + "error": false, + "gateway": "192.168.1.1", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "ovs_bond0", + "ip": "192.168.1.14", + "ipv6": [ + "2a01:cb05:814e:7d00:9209:d0ff:fe25:7371/64", + "fe80::9209:d0ff:fe25:7371/64" + ], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "255.255.255.0", + "max_supported_speed": -1, + "mode": "balance-slb", + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "slaves": [ + { + "block": 0, + "dns": "", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "eth0", + "ip": "", + "ipv6": [], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": 1000, + "status": "connected", + "type": "lan", + "use_dhcp": true, + "vlan_id": 0 + }, + { + "block": 0, + "dns": "", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "eth1", + "ip": "", + "ipv6": [], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": -1, + "status": "disconnected", + "type": "lan", + "use_dhcp": true, + "vlan_id": 0 + } + ], + "speed": 1000, + "status": "connected", + "type": "ovsbond", + "use_dhcp": true, + "vlan_id": 0 + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.Bond' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_ethernet_interface_list(self) -> dict: + """Get list of ethernet interfaces. + + Returns + ------- + dict + List of ethernet interfaces. + + Example return + ---------- + ```json + { + "data": [ + { + "block": 0, + "dns": "192.168.1.1", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "192.168.1.1", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "ovs_eth0", + "ip": "192.168.1.14", + "ipv6": [ + "2a01:cb05:814e:7d00:9209:d0ff:fe25:7371/64", + "fe80::9209:d0ff:fe25:7371/64" + ], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "255.255.255.0", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": 1000, + "status": "connected", + "type": "ovseth", + "use_dhcp": true, + "vlan_id": 0 + }, + { + "block": 0, + "dns": "", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "ovs_eth1", + "ip": "169.254.183.6", + "ipv6": [], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "255.255.0.0", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": -1, + "status": "disconnected", + "type": "ovseth", + "use_dhcp": true, + "vlan_id": 0 + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.Ethernet' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def set_ethernet_interfaces(self, configs: list) -> dict: + """Set ethernet interfaces. + + Parameters + ---------- + configs : list + List of configurations for ethernet interfaces. Each configuration is a dictionary with the following keys: + - ifname : str + Interface name. + - use_dhcp : bool + Whether to use DHCP. + - enable_ha_ip : bool, optional + Whether to enable HA IP. + - is_default_gateway : bool, optional + Whether this interface is the default gateway. + - mtu : int, optional + MTU size. + - enable_vlan : bool, optional + Whether to enable VLAN. + - ip : str, optional + IP address. + - mask : str, optional + Subnet mask. + - gateway : str, optional + Gateway address. + - dns : str, optional + DNS server address. + + Returns + ------- + dict + Result of setting ethernet interfaces. + + Example return + ---------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Network.Ethernet", + "method": "set", + "success": true, + "version": 2 + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.Ethernet' + info = self.gen_list[api_name] + compound = [ + { + 'api': api_name, + 'version': info['maxVersion'], + 'method': 'set', + 'configs': configs + } + ] + return self.batch_request(compound=compound) + + def get_pppoe_interface_list(self) -> dict: + """Get list of pppoe interfaces. + + Returns + ------- + dict + List of pppoe interfaces. + + Example return + ---------- + ```json + { + "data": [ + { + "devs": [ + "ovs_eth0", + "ovs_eth1" + ], + "guest_enabled": false, + "ifname": "pppoe", + "ip": "", + "is_default_gateway": 1, + "mask": "", + "mtu_config": "1492", + "password": "", + "real_ifname": "ovs_eth0", + "status": "disconnected", + "type": "pppoe", + "use_dhcp": true, + "username": "" + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.PPPoE' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_vpn_pptp_list(self) -> dict: + """Get list of pptp vpn interfaces. + + Returns + ------- + dict + List of pptp vpn interfaces. + + Example return + ---------- + ```json + { + "data": [], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.VPN.PPTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_vpn_openvpn_with_conf_list(self) -> dict: + """Get list of openvpn with conf file vpn interfaces. + + Returns + ------- + dict + List of openvpn with conf file vpn interfaces. + + Example return + ---------- + ```json + { + "data": [], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.VPN.OpenVPNWithConf' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_vpn_openvpn_list(self) -> dict: + """Get list of openvpn vpn interfaces. + + Returns + ------- + dict + List of openvpn vpn interfaces. + + Example return + ---------- + ```json + { + "data": [], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.VPN.OpenVPN' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_vpn_l2tp_list(self) -> dict: + """Get list of l2tp vpn interfaces. + + Returns + ------- + dict + List of l2tp vpn interfaces. + + Example return + ---------- + ```json + { + "data": [], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.VPN.L2TP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_traffic_control_rules(self, adapter: str) -> dict: + """Get traffic control rules. + + Parameters + ---------- + adapter : str + Adapter name, e.g. 'ovs_eth0'. + + Returns + ------- + dict + _description_ + + Example return + ---------- + ```json + { + "data": { + "rules": [], + "total": 0 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Network.TrafficControl.Rules' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'load', + 'adapter': adapter + } + return self.request_data(api_name, api_path, req_param) + + def get_port_list_per_service(self) -> dict: + """Get port list per service. + + Returns + ------- + dict + Port list per service. + + Example return + ---------- + ```json + { + "data": { + "port_info": [ + { + "desc": "rsync", + "dst_port": [ + "873" + ], + "name": "rsync", + "port_id": "netbkp", + "protocol": "tcp", + "src_port": null + }, + { + "desc": "Network MFP", + "dst_port": [ + "3240-3259" + ], + "name": "Network MFP", + "port_id": "mfp", + "protocol": "tcp", + "src_port": null + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Service.PortInfo' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'load', + 'target': json.dumps(["traffic_control"]) + } + return self.request_data(api_name, api_path, req_param) + + pass \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/SharedFolder.py b/synology_api/DSM/ControlPanel/SharedFolder.py index 632c9a4d..46659df1 100644 --- a/synology_api/DSM/ControlPanel/SharedFolder.py +++ b/synology_api/DSM/ControlPanel/SharedFolder.py @@ -3,8 +3,25 @@ from typing import List, Any class SharedFolder(base_api.BaseApi): - """ - Core Share API implementation. + """Core Share API implementation. + + Supported methods: + - Getters: + - Validate set of parameters for a new/modified shared folder + - List all folders information + - Get a folder by name + - Retrieve share permissions for a given folder filtered by permission name (sub string) + - Retrieve share permissions for a given folder + - Retrieve share permissions for a given group + + - Setters: + - Create a new shared folder + - Set folder permissions for a given folder + - Set group permissions for a given share + + - Actions: + - Delete folder(s) by name(s) + - Clone existing shared folder """ def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_compress: bool = False, enable_share_cow: bool = False, enc_passwd: str = "", encryption: bool = False) -> dict: From becb257b344f1e9249249dfc9f2b42f7937f1956 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Thu, 1 May 2025 23:29:10 +0200 Subject: [PATCH 005/126] Integration external access of the control panel --- .../DSM/ControlPanel/ExternalAccess.py | 856 ++++++++++++++++++ 1 file changed, 856 insertions(+) diff --git a/synology_api/DSM/ControlPanel/ExternalAccess.py b/synology_api/DSM/ControlPanel/ExternalAccess.py index f078146b..95d61d3a 100644 --- a/synology_api/DSM/ControlPanel/ExternalAccess.py +++ b/synology_api/DSM/ControlPanel/ExternalAccess.py @@ -1,4 +1,860 @@ from synology_api import base_api class ExternalAccess(base_api.BaseApi): + """ + External access class for interacting with Synology DSM External Access settings. + + Supported methods: + - Getters: + - get_ddns_provider_list + - get_ddns_record_list + - get_external_ip_list + - get_ddns_synology_account + - get_certificate_list + - get_ethernet_port_list + - get_quickconnect_info + - get_quickconnect_status + - get_quickconnect_permission + - check_quickconnect_availability + - get_quickconnect_misc_config + - get_detect_router_information_task + - get_detect_router_information_status + - get_router_list + - get_port_forwarding_rule_list + - get_services_port_info + - get_advanced_external_access + + - Setters: + - set_quickconnect_server_alias + - set_quickconnect_enable + - set_router_config + - set_advanced_external_access + + """ + + def get_ddns_provider_list(self) -> dict: + """Get the list of DDNS providers. + + Returns + ------- + dict + List of ddns provider. + + Example return + ---------- + ```json + { + "data": { + "providers": + [ + { + "id": "Synology", + "provider": "Synology", + "website": "https://account.synology.com" + }, + { + "id": "Oray.com", + "provider": "Oray.com", + "website": "" + } + ] + } + }, + "success": true + ``` + """ + api_name = 'SYNO.Core.DDNS.Provider' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_ddns_record_list(self) -> dict: + """Get the list of DDNS records. + + Returns + ------- + dict + List of ddns record. + + Example return + ---------- + ```json + { + "data": { + "next_update_time": "", + "records": [] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.DDNS.Record' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_external_ip_list(self) -> dict: + """Get the list of external IP addresses. + + Returns + ------- + dict + List of external IP addresses. + + Example return + ---------- + ```json + { + "data": [ + { + "ip": "XXX.XXX.XXX.XXX", + "ipv6": "cf92:1469:123f:219f:73af:319a:1c77:181e", + "type": "WAN" + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.DDNS.ExtIP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_ddns_synology_account(self) -> dict: + """Get the Synology DDNS account email. + + Returns + ------- + dict + Synology DDNS account email. + + Example return + ---------- + ```json + { + "data": { + "email": "YOUR_EMAIL", + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.DDNS.Synology' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get_myds_account' + } + return self.request_data(api_name, api_path, req_param) + + def get_certificate_list(self) -> dict: + """Get the list of certificates. + + Returns + ------- + dict + List of certificates. + + Example return + ---------- + ```json + { + "data": { + "certificates": [ + { + "desc": "", + "id": "C6meKD", + "is_broken": false, + "is_default": false, + "issuer": { + "city": "Taipel", + "common_name": "Synology Inc. CA", + "country": "TW", + "organization": "Synology Inc." + }, + "key_types": "", + "renewable": false, + "self_signed_cacrt_info": { + "issuer": { + "city": "Taipel", + "common_name": "Synology Inc. CA", + "country": "TW", + "organization": "Synology Inc." + }, + "subject": { + "city": "Taipel", + "common_name": "Synology Inc. CA", + "country": "TW", + "organization": "Synology Inc." + } + }, + "services": [], + "signature_algorithm": "sha256WithRSAEncryption", + "subject": { + "city": "Taipel", + "common_name": "synology", + "country": "TW", + "organization": "Synology Inc.", + "sub_alt_name": [ + "synology" + ] + }, + "user_deletable": true, + "valid_from": "Nov 4 12:33:40 2024 GMT", + "valid_till": "Nov 5 12:33:40 2025 GMT" + } + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Certificate.CRT' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_ethernet_port_list(self) -> dict: + """Get the list of ethernet ports. + + Returns + ------- + dict + List of ethernet ports. + + Example return + ---------- + ```json + { + "data": [ + { + "ifname": "ovs_eth0", + "ip": "XXX.XXX.XXX.XXX", + "ipv6": [ + "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX" + ] + }, + { + "ifname": "ovs_eth1", + "ip": "XXX.XXX.XXX.XXX", + "ipv6": [] + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.DDNS.Ethernet' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_quickconnect_info(self) -> dict: + """Get the QuickConnect information. + + Returns + ------- + dict + QuickConnect information. + + Example return + ---------- + ```json + { + "data": { + "ddns_domain": "direct.quickconnect.to", + "domain": "quickconnect.to", + "enabled": false, + "myds_account": "YOUR_MYDS_ACCOUNT", + "region": "fr", + "server_alias": "YOUR_SERVER_ALIAS", + "server_id": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_quickconnect_status(self) -> dict: + """Get the QuickConnect status. + + Returns + ------- + dict + QuickConnect status. + + Example return + ---------- + ```json + { + "data": { + "alias_status": "success", + "status": "not_running" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status' + } + return self.request_data(api_name, api_path, req_param) + + def get_quickconnect_permission(self) -> dict: + """Get the QuickConnect permission. + + Returns + ------- + dict + QuickConnect permission. + + Example return + ---------- + ```json + { + "data": { + "services": [ + { + "enabled": true, + "id": "mobile_apps" + }, + { + "enabled": true, + "id": "cloudstation" + }, + { + "enabled": true, + "id": "file_sharing" + }, + { + "enabled": true, + "id": "dsm_portal" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect.Permission' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def check_quickconnect_availability(self) -> dict: + """Check the availability of QuickConnect. + + Returns + ------- + dict + Availability status of QuickConnect. + + Example return + ---------- + ```json + { + "data": { + "available": true, + "code": 2908, + "country": "FR" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'check_availability' + } + return self.request_data(api_name, api_path, req_param) + + def get_quickconnect_misc_config(self) -> dict: + """Get the QuickConnect miscellaneous configuration. + + Returns + ------- + dict + QuickConnect miscellaneous configuration. + + Example return + ---------- + ```json + { + "data": { + "relay_enabled": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get_misc_config' + } + return self.request_data(api_name, api_path, req_param) + + def set_quickconnect_server_alias(self, server_alias: str) -> dict: + """Set the QuickConnect server alias. + + Parameters + ---------- + server_alias : str + The server alias to set. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set_server_alias', + 'server_alias': server_alias + } + return self.request_data(api_name, api_path, req_param) + + def set_quickconnect_enable(self, enable: bool) -> dict: + """Enable or disable QuickConnect. + + Parameters + ---------- + enable : bool + True to enable, False to disable. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.QuickConnect' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable + } + return self.request_data(api_name, api_path, req_param) + + def get_detect_router_information_task(self) -> dict: + """Get the task information for detecting router. + + Returns + ------- + dict + Task information for detecting router. + + Example return + ---------- + ```json + { + "data": { + "task_id": "@administrators/SYNO.Core.PortForwarding.detect174570013646DCEDAC" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.PortForwarding' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'detect' + } + return self.request_data(api_name, api_path, req_param) + + def get_detect_router_information_status(self, task_id: str) -> dict: + """Get the status of the task for detecting router. + + Parameters + ---------- + task_id : str + The task ID to check the status of. + + Returns + ------- + dict + Status of the task for detecting router. + + Example return + ---------- + ```json + { + "data": { + "percentage": 30, + "progress": { + "check_connect_wan_step": { + "check_id": 3, + "status": "initial" + }, + "check_dns_setting_step": { + "check_id": 5, + "status": "initial" + }, + "check_gateway_setting_step": { + "check_id": 2, + "status": "processing" + }, + "check_hops_lan2wan_step": { + "check_id": 4, + "status": "initial" + }, + "check_interface_enable_step": { + "check_id": 1, + "network_interface": "ovs_eth0", + "status": "success" + }, + "detect_router_step": { + "check_id": 6, + "status": "initial" + } + } + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.PortForwarding' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'detect_status', + 'task_id': task_id + } + return self.request_data(api_name, api_path, req_param) + + def get_router_list(self) -> dict: + """Get the list of routers. + + Returns + ------- + dict + List of routers. + + Example return + ---------- + ```json + { + "data": { + "routers":[ + { + "generic": false, + "router_brand": "3rd Party", + "router_model": "DD-WRT", + "router_version": "v24-sp1 micro" + }, + { + "generic": false, + "router_brand": "3rd Party", + "router_model": "DD-WRT", + "router_version": "v24-sp2 std - build 14896" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.PortForwarding.RouterList' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def set_router_config(self, + router_brand: str, router_model: str, router_version: str, router_protocol: str, router_port: int, + support_upnp: bool = False, support_natpmp: bool = False + ) -> dict: + """Set the router configuration. + + Parameters + ---------- + router_brand : str + The brand of the router. + router_model : str + The model of the router. + router_version : str + The version of the router. + router_protocol : str + The protocol used by the router. + router_port : int + The port used by the router. + support_upnp : bool, optional + Whether UPnP is supported (default is False). + support_natpmp : bool, optional + Whether NAT-PMP is supported (default is False). + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.PortForwarding.RouterConf' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'router_brand': router_brand, + 'router_model': router_model, + 'router_version': router_version, + 'router_protocol': router_protocol, + 'router_port': router_port, + 'support_upnp': "yes" if support_upnp else "no", + 'support_natpmp': "yes" if support_natpmp else "no" + } + return self.request_data(api_name, api_path, req_param) + + def get_port_forwarding_rule_list(self) -> dict: + """Get the list of port forwarding rules. + + Returns + ------- + dict + List of port forwarding rules. + + Example return + ---------- + ```json + { + "data": [ + { + "ds_port": "873", + "enable": true, + "router_port": "873", + "router_protocol": "tcp", + "rule_id": "1", + "service_name": "", + "serviceid": "netbkp" + } + ], + "success": true + } + ``` + """ + api_name = 'SYNO.Core.PortForwarding.Rules' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'load' + } + return self.request_data(api_name, api_path, req_param) + + def get_services_port_info(self) -> dict: + """Get the port information of services. + + Returns + ------- + dict + Port information of services. + + Example return + ---------- + ```json + { + "data": { + "service": [ + { + "additional": { + "port_info": [ + { + "desc": "Share files with Mac", + "dst_port": [ + "548" + ], + "name": "AFP", + "port_id": "afp", + "protocol": "tcp", + "src_port": null + } + ] + }, + "display_name": "AFP", + "enable_status": "disabled", + "service_id": "atalk" + }, + { + "additional": { + "port_info": [ + { + "desc": "Bonjour", + "dst_port": [ + "5353" + ], + "name": "Bonjour Service", + "port_id": "bonjour", + "protocol": "udp", + "src_port": null + } + ] + }, + "display_name": "Bonjour Printer Broadcast", + "enable_status": "disabled", + "service_id": "bonjour" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Service' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get', + 'additional': ["port_info"] + } + return self.request_data(api_name, api_path, req_param) + + def get_advanced_external_access(self) -> dict: + """Get the advanced external access settings. + + Returns + ------- + dict + Advanced external access settings: + - `hostname`: The hostname of the DSM. + - `http_port`: The HTTP port of the DSM. + - `https_port`: The HTTPS port of the DSM. + + Example return + ---------- + ```json + { + "data": { + "hostname": "HOSTNAME", + "http_port": 5000, + "https_port": 5001 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Web.DSM.External' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_advanced_external_access(self, hostname: str, http_port: int, https_port: int) -> dict: + """Set the advanced external access settings. + + Parameters + ---------- + hostname : str + The hostname of the DSM. + http_port : int + The HTTP port of the DSM. + https_port : int + The HTTPS port of the DSM. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.Web.DSM.External' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'hostname': hostname, + 'http_port': http_port, + 'https_port': https_port + } + return self.request_data(api_name, api_path, req_param) + + pass \ No newline at end of file From 8fdad48c9ee19f3ed123013f25dca7f00e0171c9 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Thu, 1 May 2025 23:50:27 +0200 Subject: [PATCH 006/126] Implementation of External devices --- .../DSM/ControlPanel/ExternalDevices.py | 386 +++++++++++++++++- 1 file changed, 385 insertions(+), 1 deletion(-) diff --git a/synology_api/DSM/ControlPanel/ExternalDevices.py b/synology_api/DSM/ControlPanel/ExternalDevices.py index afe3f1c8..cbcf775f 100644 --- a/synology_api/DSM/ControlPanel/ExternalDevices.py +++ b/synology_api/DSM/ControlPanel/ExternalDevices.py @@ -1,4 +1,388 @@ from synology_api import base_api - +from typing import List class ExternalDevices(base_api.BaseApi): + """ + External devices class for interacting with Synology DSM External devices settings. + + Supported methods: + - Getters: + - get_printer_driver_list() + - get_printer_bonjour_enabled() + - get_storage_settings() + - get_list_usb_devices() + - get_list_esata_devices() + - get_list_of_printer() + - get_permissions() + - Setters: + - set_printer_bonjour_enabled() + - set_permissions() + + """ + + def get_printer_driver_list(self) -> dict: + """Get the list of printer driver. + + Returns + ------- + dict + List of printer driver. + + Example return + ---------- + ```json + { + "data": { + "Apollo": [ + [ + "Apollo P-2100", + "stp-pcl-apollo-p2100.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2150", + "stp-pcl-apollo-p2150.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2200", + "stp-pcl-apollo-p2200.5.2.ppd.tgz", + "EPSON", + "Stylus DX4800" + ], + [ + "Apollo P-2250", + "stp-pcl-apollo-p2250.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2500", + "stp-pcl-apollo-p2500.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2550", + "stp-pcl-apollo-p2550.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2600", + "stp-pcl-apollo-p2600.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2650", + "stp-pcl-apollo-p2650.5.2.ppd.tgz", + "", + "" + ] + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Printer.Driver' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_printer_bonjour_enabled(self) -> dict: + """Get the printer bonjour enabled status. + + Returns + ------- + dict + Printer bonjour enabled status. + + Example return + ---------- + ```json + { + "data": { + "enable_bonjour_support": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Printer.BonjourSharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_printer_bonjour_enabled(self, enable: bool) -> dict: + """Set the printer bonjour enabled status. + + Parameters + ---------- + enable : bool + Printer bonjour enabled status. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Printer.BonjourSharing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable_bonjour_support': enable + } + return self.request_data(api_name, api_path, req_param) + + + def get_storage_settings(self) -> dict: + """Get the external devices storage settings. + + Returns + ------- + dict + External devices storage settings. + + Example return + ---------- + ```json + { + "data": { + "delalloc": false, + "forbid_usb": false, + "needReboot": false, + "non_admin_eject": false, + "setting": false, + "support_exfat_mkfs": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Storage.Setting' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_list_usb_devices(self) -> dict: + """Get the list of USB devices. + + Returns + ------- + dict + List of USB devices. + + Example return + ---------- + ```json + { + "data": { + "devices": [] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Storage.USB' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'additional': ["all"], + } + return self.request_data(api_name, api_path, req_param) + + def get_list_esata_devices(self) -> dict: + """Get the list of eSATA devices. + + Returns + ------- + dict + List of eSATA devices. + + Example return + ---------- + ```json + { + "data": { + "devices": [] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Storage.eSATA' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'additional': ["all"], + } + return self.request_data(api_name, api_path, req_param) + + def get_list_of_printer(self) -> dict: + """Get the list of printers. + + Returns + ------- + dict + List of printers. + + Example return + ---------- + ```json + { + "data": { + "printers": [] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.Printer' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'additional': ["all"], + } + return self.request_data(api_name, api_path, req_param) + + def get_permissions(self, + offset: int = 0, limit: int = 50, + user_group_type: str = "local_user" + ) -> dict: + """Get the permissions of the external devices + + Parameters + ---------- + offset : int, optional + The offset for pagination. Defaults to `0`. + limit : int, optional + The limit for pagination. Defaults to `50`. + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + Permissions of the external devices. + + Example return + ---------- + ```json + { + "data": { + "items": [ + { + "is_admin": true, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "admin" + }, + { + "is_admin": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + } + ], + "total": 2 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.DefaultPermission' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list', + 'action': 'enum', + 'offset': offset, + 'limit': limit, + 'user_group_type': user_group_type + } + return self.request_data(api_name, api_path, req_param) + + def set_permissions(self, user_group_type: str, permissions: List[dict[str, object]]) -> dict: + """Set the permissions of the external devices. + + Parameters + ---------- + user_group_type : str + The type of user group to set permissions for. All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + permissions : List[dict[str, object]] + List of permissions to set. Each permission is a dictionary. + Example: + ```json + [ + { + "name":"guest", + "is_readonly":false, + "is_writable":true, + "is_deny":false, + "is_custom":false + } + ] + ``` + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.DefaultPermission' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'user_group_type': user_group_type, + 'permissions': permissions + } + return self.request_data(api_name, api_path, req_param) + + + pass \ No newline at end of file From 5f553f35aee0411ca205169e052b42e49a2c884c Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sat, 3 May 2025 17:36:53 +0200 Subject: [PATCH 007/126] Implementation of FileServices in ControlPanel --- synology_api/DSM/ControlPanel/FileServices.py | 822 ++++++++++++++++++ 1 file changed, 822 insertions(+) diff --git a/synology_api/DSM/ControlPanel/FileServices.py b/synology_api/DSM/ControlPanel/FileServices.py index 6514b1ee..94e84710 100644 --- a/synology_api/DSM/ControlPanel/FileServices.py +++ b/synology_api/DSM/ControlPanel/FileServices.py @@ -1,4 +1,826 @@ from synology_api import base_api class FileServices(base_api.BaseApi): + """ + File services class for interacting with Synology DSM File services settings. + + Supported methods: + - Getters: + + - Setters: + + """ + + def get_smb_settings(self): + """Get SMB settings + + Returns + ------- + dict + SMB settings data. + + Example return + ---------- + ```json + { + "data": { + "disable_shadow_copy": false, + "disable_strict_allocate": false, + "enable_access_based_share_enum": false, + "enable_adserver": null, + "enable_aio_read": false, + "enable_delete_vetofiles": false, + "enable_dirsort": false, + "enable_durable_handles": false, + "enable_enhance_log": false, + "enable_fruit_locking": false, + "enable_local_master_browser": false, + "enable_mask": false, + "enable_msdfs": false, + "enable_multichannel": false, + "enable_ntlmv1_auth": false, + "enable_op_lock": true, + "enable_perf_chart": false, + "enable_reset_on_zero_vc": false, + "enable_samba": true, + "enable_server_signing": 0, + "enable_smb2_leases": true, + "enable_smb3_directory_leasing": true, + "enable_strict_sync": false, + "enable_symlink": true, + "enable_syno_catia": true, + "enable_synotify": true, + "enable_vetofile": false, + "enable_widelink": false, + "offline_files_support": false, + "smb3_directory_leasing_scope": "home_only", + "smb_encrypt_transport": 1, + "smb_max_protocol": 3, + "smb_min_protocol": 1, + "syno_wildcard_search": false, + "vetofile": "", + "wins": "", + "workgroup": "WORKGROUP" + } + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.SMB' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_afp_settings(self) -> dict: + """Get AFP settings + + Returns + ------- + dict + AFP settings data. + + Example return + ---------- + ```json + { + "data": { + "enable_afp": false, + "enable_disconnect_quick": false, + "enable_umask": false, + "time_machine": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.AFP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_nfs_settings(self) -> dict: + """Get NFS settings + + Returns + ------- + dict + NFS settings data. + + Example return + ---------- + ```json + { + "data": { + "enable_nfs": false, + "enable_nfs_v4": false, + "enabled_minor_ver": 0, + "nfs_v4_domain": "", + "read_size": 8192, + "support_encrypt_share": 1, + "support_major_ver": 4, + "support_minor_ver": 1, + "unix_pri_enable": true, + "write_size": 8192 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.NFS' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_ftp_settings(self) -> dict: + """Get FTP settings + + Returns + ------- + dict + FTP settings data. + + Example return + ---------- + ```json + { + "data": { + "custom_port": "55536:55899", + "custom_port_range": false, + "enable_ascii": false, + "enable_fips": false, + "enable_flow_ctrl": false, + "enable_ftp": false, + "enable_ftps": false, + "enable_fxp": false, + "ext_ip": "", + "max_conn_per_ip": 0, + "maxdownloadrate": 0, + "maxuploadrate": 0, + "modify_time_std": "utc", + "portnum": 21, + "timeout": 300, + "use_ext_ip": false, + "utf8_mode": 1, + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.FTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_sftp_settings(self) -> dict: + """Get SFTP settings + + Returns + ------- + dict + SFTP settings data. + + Example return + ---------- + ```json + { + "data": { + "enable": false, + "portnum": 22, + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.FTP.SFTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_bandwidth_control_protocol_settings(self, protocol: str, schedule_plan: str) -> dict: + """Get bandwidth control protocol settings + + Parameters + ---------- + protocol : str + Protocol name, here are the known protocols: + - "FTP" + - "NetworkBackup" + + schedule_plan : str + Schedule plan, a 128-bit binary string. + + Returns + ------- + dict + Bandwidth control protocol settings data. + + Example return + ---------- + ```json + { + "data": { + "policy": "disabled", + "protocol": "FTP", + "schedule_plan": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.BandwidthControl.Protocol' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get', + 'protocol': protocol + } + return self.request_data(api_name, api_path, req_param) + + def get_network_backup_settings(self) -> dict: + """Get network backup settings + + Returns + ------- + dict + Network backup settings data. + + Example return + ---------- + ```json + { + "data": { + "enable": false, + "enable_custom_config": false, + "enable_rsync_account": false, + "rsync_sshd_port": "22" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Backup.Service.NetworkBackup' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_domain_settings(self) -> dict: + """Get domain settings + + Returns + ------- + dict + Domain settings data. + + Example return + ---------- + ```json + { + "data": { + "enable_domain": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Directory.Domain' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_service_discovery_settings(self) -> dict: + """Get service discovery settings + + Returns + ------- + dict + Service discovery settings data. + + Example return + ---------- + ```json + { + "data": { + "enable_afp_time_machine": false, + "enable_smb_time_machine": false, + "time_machine_disable_shares": [], + "time_machine_shares": [] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.ServiceDiscovery' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_wstransfer_settings(self) -> dict: + """Get WSTransfer settings + + Returns + ------- + dict + WSTransfer settings data. + + Example return + ---------- + ```json + { + "data": { + "enable_wstransfer": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.ServiceDiscovery.WSTransfer' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_reflink_copy_settings(self) -> dict: + """Get reflink copy settings + + Returns + ------- + dict + Reflink copy settings data. + + Example return + ---------- + ```json + { + "data": { + "reflink_copy_enable": false, + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.ReflinkCopy' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_tftp_settings(self) -> dict: + """Get TFTP settings + + Returns + ------- + dict + TFTP settings data. + + Example return + ---------- + ```json + { + "data": { + "enable": false, + "enable_log": false, + "endip": "255.255.255.255", + "permission": "r", + "root_path": "", + "startip": "0.0.0.0", + "timeout": 3 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.TFTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def clean_smb_cache(self) -> dict: + """Clean SMB cache + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.SMB' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'clean_cache' + } + return self.request_data(api_name, api_path, req_param) + + def set_afp_settings(self, enable: bool, enable_transfer_log: bool, enable_umask: bool, enable_disconnect_quick: bool) -> dict: + """Set AFP settings + + Parameters + ---------- + enable : bool + Enable or disable AFP. + + enable_transfer_log : bool + Enable or disable transfer log. + + enable_umask : bool + Enable or disable umask. + + enable_disconnect_quick : bool + Enable or disable quick disconnect. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.AFP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'enable_transfer_log': enable_transfer_log, + 'enable_umask': enable_umask, + 'enable_disconnect_quick': enable_disconnect_quick + } + return self.request_data(api_name, api_path, req_param) + + def set_nfs_settings(self, enable: bool, max_protocol: int, enable_v4: bool, enabled_minor_ver: int) -> dict: + """Set NFS settings + + Parameters + ---------- + enable : bool + Enable or disable NFS. + + max_protocol : int + Maximum NFS protocol version. + + enalbe_v4 : bool + Enable or disable NFSv4. + + enabled_minor_ver : int + Enabled minor version. + + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.NFS' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'max_protocol': max_protocol, + 'enable_v4': enable_v4, + 'enabled_minor_ver': enabled_minor_ver + } + return self.request_data(api_name, api_path, req_param) + + def get_ftp_security_settings(self) -> dict: + """Get FTP security settings + + Returns + ------- + dict + FTP security settings data. + + Example return + ---------- + ```json + { + "data": { + "anonymous": false, + "anonymous_chroot": false, + "anonymous_chroot_share": "", + "enable_umask": false, + "user_chroot": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.FTP.Security' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_ftp_security_share_list(self) -> dict: + """Get FTP security share list + + Returns + ------- + dict + FTP security share list data. + + Example return + ---------- + ```json + { + "data":{ + "share": [ + "docker" + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.FTP.Security.ShareList' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_ftp_settings(self, enable_ftp: bool, enable_ftps: bool, + timeout: int = 300, portnum: int = 21, custom_port_range: bool = False, + use_ext_ip: bool = False, enable_fxp: bool = True, enable_ascii: bool = True, + utf8_mode: int = 1, modify_time_std: str = "utc", custom_port: str = "55536:55899", + external_ip: str = "default" + ) -> dict: + """Set FTP settings + + Parameters + ---------- + enable_ftp : bool + Enable or disable FTP. + + enable_ftps : bool + Enable or disable FTPS. + + timeout : int + Timeout in seconds. Default to `300`. + + portnum : int + Port number. Default to `21`. + + custom_port_range : bool + Enable or disable custom port range. Default to `False`. + + use_ext_ip : bool + Enable or disable external IP. Default to `False`. + + enable_fxp : bool + Enable or disable FXP. Default to `True`. + + enable_ascii : bool + Enable or disable ASCII mode. Default to `True`. + + utf8_mode : int + UTF-8 mode (0: disable, 1: Auto, 2: Force). Default to `1`. + + modify_time_std : str + Modify time standard ("utc", "local"). Default to `"utc"`. + + custom_port : str + Custom port range. Default to `"55536:55899"`. + + external_ip : str + External IP address. Default to `"default"`. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.FTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable_ftp': enable_ftp, + 'enable_ftps': enable_ftps, + 'timeout': timeout, + 'portnum': portnum, + 'custom_port_range': custom_port_range, + 'use_ext_ip': use_ext_ip, + 'enable_fxp': enable_fxp, + 'enable_ascii': enable_ascii, + 'utf8_mode': utf8_mode, + 'modify_time_std': modify_time_std, + 'custom_port': custom_port, + 'external_ip': external_ip + } + return self.request_data(api_name, api_path, req_param) + + def set_sftp_settings(self, enable: bool, portnum: int = 22) -> dict: + """Set SFTP settings + + Parameters + ---------- + enable : bool + Enable or disable SFTP. + + portnum : int + Port number. Default to `22`. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.FTP.SFTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'portnum': portnum, + 'sftp_portnum': portnum + } + return self.request_data(api_name, api_path, req_param) + + def set_rsync_settings(self, enable: bool, port: int = 22) -> dict: + """Set rsync settings + + Parameters + ---------- + enable : bool + Enable or disable rsync. + + port : int + Rsync SSHD port. Default to `22`. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Backup.Service.NetworkBackup' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'rsync_sshd_port': port + } + return self.request_data(api_name, api_path, req_param) + + def set_reflink_copy_settings(self, reflink_copy_enable: bool) -> dict: + """Set reflink copy settings + + Parameters + ---------- + reflink_copy_enable : bool + Enable or disable reflink copy. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.FileServ.ReflinkCopy' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'reflink_copy_enable': reflink_copy_enable + } + return self.request_data(api_name, api_path, req_param) + + def set_tftp_settings(self, enable: bool, root_path: str) -> dict: + """Set TFTP settings + + Parameters + ---------- + enable : bool + Enable or disable TFTP. + + root_path : str + Root path for TFTP. Path must be a valid directory. + + Returns + ------- + dict + Result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.TFTP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'root_path': root_path + } + return self.request_data(api_name, api_path, req_param) + pass \ No newline at end of file From 7b46fba3ab3ae78f22b6062ca50ed87cdb0d80ad Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 11 May 2025 01:04:15 +0200 Subject: [PATCH 008/126] Implementation of Hardware & Power in the Control panel --- .../DSM/ControlPanel/HardwarePower.py | 802 +++++++++++++++++- 1 file changed, 801 insertions(+), 1 deletion(-) diff --git a/synology_api/DSM/ControlPanel/HardwarePower.py b/synology_api/DSM/ControlPanel/HardwarePower.py index 5af857e7..dae0510a 100644 --- a/synology_api/DSM/ControlPanel/HardwarePower.py +++ b/synology_api/DSM/ControlPanel/HardwarePower.py @@ -1,4 +1,804 @@ from synology_api import base_api - +import json +from typing import List class HardwarePower(base_api.BaseApi): + """ + Hardware power class for interacting with Synology DSM Hardware & Power settings. + + Supported methods: + - Getters: + + - Setters: + + """ + + def need_reboot(self) -> dict: + """TODO: Determine usage of this method. + + Returns + ------- + dict + Return boolean value indicating if a reboot is needed. + + Example return + ---------- + ```json + { + "data": { + "need_reboot": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.NeedReboot' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_need_reboot(self) -> dict: + """TODO: Determine usage of this method. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.NeedReboot' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set' + } + return self.request_data(api_name, api_path, req_param) + + def get_led_brightness_stats(self) -> dict: + """Get LED brightness stats. + + Returns + ------- + dict + Return LED brightness default settigns and min / max. + + Example return + ---------- + ```json + { + "data": { + "default": 3, + "max": 3, + "min": 0 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.Led.Brightness' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get_static_data' + } + return self.request_data(api_name, api_path, req_param) + + def get_zram_settings(self) -> dict: + """Get ZRAM settings. + + Returns + ------- + dict + Return ZRAM settings. + + Example return + ---------- + ```json + { + "data": { + "enable_zram": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.ZRAM' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_power_recovery_settings(self) -> dict: + """Get power recovery settings. + + Returns + ------- + dict + Return power recovery settings. + + Example return + ---------- + ```json + { + "data": { + "internal_lan_num": 2, + "rc_power_config": true, + "wol": [ + { + "enable": false, + "idx": 1 + }, + { + "enable": false, + "idx": 2 + } + ], + "wol1": false, + "wol2": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.PowerRecovery' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_beep_control_settings(self) -> dict: + """Get beep control settings. + + Returns + ------- + dict + Return beep control settings. + + Example return + ---------- + ```json + { + "data": { + "enc_module_fail": true, + "eunit_redundant_power_fail": true, + "fan_fail": true, + "poweroff_beep": true, + "poweron_beep": true, + "redundant_power_fail": true, + "reset_beep": true, + "sas_link_fail": true, + "support_fan_fail": true, + "support_poweroff_beep": true, + "support_poweron_beep": true, + "support_redundant_power_fail": false, + "support_reset_beep": false, + "support_volume_or_cache_crash": true, + "volume_or_cache_crash": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.BeepControl' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_fan_speed_settings(self) -> dict: + """Get fan speed settings. + + Returns + ------- + dict + Return fan speed settings. + + Example return + ---------- + ```json + { + "data": { + "enc_module_fail": true, + "eunit_redundant_power_fail": true, + "fan_fail": true, + "poweroff_beep": true, + "poweron_beep": true, + "redundant_power_fail": true, + "reset_beep": true, + "sas_link_fail": true, + "support_fan_fail": true, + "support_poweroff_beep": true, + "support_poweron_beep": true, + "support_redundant_power_fail": false, + "support_reset_beep": false, + "support_volume_or_cache_crash": true, + "volume_or_cache_crash": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.FanSpeed' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_led_brightness_schedule(self) -> dict: + """Get LED brightness settings. + + Returns + ------- + dict + Return LED brightness settings. Schedule is a 144 character string. + 1 character = 1 hour. Start from Sunday 00:00 to Saturday 23:00. + 0 = Default, 1= Ajusted, 2 = Off + + Example return + ---------- + ```json + { + "data": { + "led_brightness": 3, + "schedule": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.Led.Brightness' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_power_schedule_settings(self) -> dict: + """Get power schedule settings. + + Returns + ------- + dict + Return power schedule settings. + + Example return + ---------- + ```json + { + "data": { + "poweroff_tasks": [], + "poweron_tasks": [] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.PowerSchedule' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'load' + } + return self.request_data(api_name, api_path, req_param) + + def get_hibernation_settings(self) -> dict: + """Get hibernation settings. + + Returns + ------- + dict + Return hibernation settings. + + Example return + ---------- + ```json + { + "data": { + "auto_poweroff_enable": false, + "enable_log": false, + "eunit_deep_sleep": 0, + "eunit_dsleep_blacklist": "none", + "hibernation_blacklist": "none", + "ignore_netbios_broadcast": false, + "internal_hd_idletime": 20, + "sata_deep_sleep": 1, + "sata_dsleep_blacklist": "none", + "support_esata": "yes", + "support_eunit_deep_sleep": false, + "support_eunit_switch_mode": true, + "usb_idletime": 0 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.Hibernation' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_ups_settings(self) -> dict: + """Get UPS settings. + + Returns + ------- + dict + Return UPS settings. + + Example return + ---------- + ```json + { + "data": { + "ACL_enable": false, + "ACL_list": [], + "charge": 0, + "delay_time": -1, + "enable": false, + "manufacture": "", + "mode": "SLAVE", + "model": "", + "net_server_ip": "", + "runtime": 0, + "shutdown_device": false, + "snmp_auth": false, + "snmp_auth_key": false, + "snmp_auth_type": "", + "snmp_community": "", + "snmp_mib": "", + "snmp_privacy": false, + "snmp_privacy_key": false, + "snmp_privacy_type": "", + "snmp_server_ip": "", + "snmp_user": "", + "snmp_version": "", + "status": "usb_ups_status_unknown", + "usb_ups_connect": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.UPS' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_led_brightness(self, brightness: int = 3) -> dict: + """Set LED brightness. + + Parameters + ---------- + brightness : int + LED brightness level (0-3). Default is `3`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.Led.Brightness' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'brightness': brightness + } + return self.request_data(api_name, api_path, req_param) + + def set_zram_settings(self, enable_zram: bool = False) -> dict: + """Set ZRAM settings. + + Parameters + ---------- + enable_zram : bool + Enable or disable ZRAM. Default is `False`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.ZRAM' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable_zram': enable_zram + } + return self.request_data(api_name, api_path, req_param) + + def set_power_recovery_settings(self, + enable: bool = False, wol1: bool = False, wol2: bool = False, wol3: bool = False + ) -> dict: + """Set power recovery settings. Note if a wol option is enabled, the enable option will be forced to `True`. + + Parameters + ---------- + enable : bool + Enable or disable power recovery configuration. Default is `False`. + wol1 : bool + Enable or disable Wake on LAN for port 1. Default is `False`. + wol2 : bool + Enable or disable Wake on LAN for port 2. Default is `False`. + wol3 : bool + Enable or disable Wake on LAN for port 3. Default is `False`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.PowerRecovery' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'wol1': wol1, + 'wol2': wol2, + 'wol3': wol3 + } + return self.request_data(api_name, api_path, req_param) + + def set_beep_control_settings(self, + fan_fail: bool = True, volume_or_cache_crash: bool = True, + poweroff_beep: bool = True, poweron_beep: bool = True + ) -> dict: + """Set beep control settings. + + Parameters + ---------- + fan_fail : bool + Enable or disable fan failure beep. Default is `True`. + volume_or_cache_crash : bool + Enable or disable volume or cache crash beep. Default is `True`. + poweroff_beep : bool + Enable or disable power off beep. Default is `True`. + poweron_beep : bool + Enable or disable power on beep. Default is `True`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.BeepControl' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'fan_fail': fan_fail, + 'volume_or_cache_crash': volume_or_cache_crash, + 'poweroff_beep': poweroff_beep, + 'poweron_beep': poweron_beep + } + return self.request_data(api_name, api_path, req_param) + + def set_fan_speed_settings(self, fan_speed: str = "coolfan") -> dict: + """Set fan speed settings. + + Parameters + ---------- + fan_speed : str + Fan speed level (0-2). Default is `quietfan`. + Known values are `quietfan`, `coolfan`, and `fullspeed`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.FanSpeed' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'dual_fan_speed': fan_speed + } + return self.request_data(api_name, api_path, req_param) + + def set_led_brightness_schedule(self, + led_brightness: int = 3, schedule: str = "1"*144 + ) -> dict: + """Set LED brightness schedule. + + Parameters + ---------- + led_brightness : int + LED brightness level (0-3). Default is `3`. + schedule : str + Schedule string for LED brightness. 1 character = 1 hour. Start from Sunday 00:00 to Saturday 23:00. + Default is `1` for all hours. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.Led.Brightness' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'led_brightness': led_brightness, + 'schedule': schedule + } + return self.request_data(api_name, api_path, req_param) + + def set_hibernation_settings(self, + internal_hd_idletime: int = 20, stat_deep_sleep: bool = True, + ignore_netbios_broadcast: bool = False, usb_idletime: int = 0, + enable_log: bool = False + ) -> dict: + """Set hibernation settings. + + Parameters + ---------- + internal_hd_idletime : int + Internal hard drive idle time in minutes. Default is `20`. + stat_deep_sleep : bool + Enable or disable SATA deep sleep. Default is `True`. + ignore_netbios_broadcast : bool + Enable or disable ignoring NetBIOS broadcast. Default is `False`. + usb_idletime : int + USB idle time in minutes. Default is `0`. + enable_log : bool + Enable or disable logging. Default is `False`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.Hibernation' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'internal_hd_idletime': internal_hd_idletime, + 'stat_deep_sleep': stat_deep_sleep, + 'ignore_netbios_broadcast': ignore_netbios_broadcast, + 'usb_idletime': usb_idletime, + 'enable_log': enable_log + } + return self.request_data(api_name, api_path, req_param) + + def set_ups_settings(self, + enable: bool = False, mode: str = "SLAVE", delay_time: str = "-1", + snmp_auth_key_dirty: bool = False, snmp_privacy_key_dirty: bool = False, + ) -> dict: + """Set UPS settings. + + Parameters + ---------- + enable : bool + Enable or disable UPS. Default is `False`. + mode : str + UPS mode. Default is `SLAVE`. + TODO: Determine valid values for this parameter. + delay_time : str + Delay time in seconds. Default is `-1`. + TODO: Determine valid values for this parameter. + snmp_auth_key_dirty : bool + SNMP authentication key dirty flag. Default is `False`. + snmp_privacy_key_dirty : bool + SNMP privacy key dirty flag. Default is `False`. + + Returns + ------- + dict + Return success status. + + Example return + ---------- + ```json + { + "data": { + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.ExternalDevice.UPS' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable, + 'mode': mode, + 'delay_time': delay_time, + 'snmp_auth_key_dirty': snmp_auth_key_dirty, + 'snmp_privacy_key_dirty': snmp_privacy_key_dirty + } + return self.request_data(api_name, api_path, req_param) + + def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: List[dict] = []) -> dict: + """Set the power schedule, poweron tasks and poweroff tasks + + Parameters + ---------- + poweron_tasks : List[dict], optional + List of tasks for power on. Defaults to `[]` + Example of a task: + ```python + { + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) + } + ``` + poweroff_tasks : List[dict], optional + List of tasks for power off. Defaults to `[]` + Example of a task: + ```python + { + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) + } + ``` + Returns + ------- + dict + List of tasks in power schedule + + Example return + ---------- + ```json + { + "data": { + "poweroff_tasks": [], + "poweron_tasks": [ + { + "enabled": true, + "hour": 0, + "min": 0, + "weekdays": "1,2,3,4,5" + } + ] + }, + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Hardware.PowerSchedule' + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "save", + "poweron_tasks": json.dumps(poweron_tasks), + "poweroff_tasks": json.dumps(poweroff_tasks) + } + + return self.request_data(api_name, api_path, req_param) + pass \ No newline at end of file From 71e4b366592928ceac7b49d451624a903336ff9f Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 18 May 2025 10:39:09 +0200 Subject: [PATCH 009/126] Start implementation of Indexing Service --- .../DSM/ControlPanel/IndexingService.py | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) diff --git a/synology_api/DSM/ControlPanel/IndexingService.py b/synology_api/DSM/ControlPanel/IndexingService.py index c8e4f319..99ab5b41 100644 --- a/synology_api/DSM/ControlPanel/IndexingService.py +++ b/synology_api/DSM/ControlPanel/IndexingService.py @@ -1,4 +1,118 @@ from synology_api import base_api class IndexingService(base_api.BaseApi): + """ + Indexing service class for interacting with Synology DSM Indexing service settings. + + Supported methods: + - Getters: + + - Setters: + + """ + + def get_indexed_folders(self) -> dict: + """Get indexed folders. + + Returns + ------- + dict + Return list of folders indexed by the indexing service. + + Example return + ---------- + ```json + { + "data": { + "folders": [ + { + "default": false, + "exist": true, + "name": "Films", + "path": "/Films", + "types": [ + "video" + ] + }, + { + "default": false, + "exist": true, + "name": "Series", + "path": "/Series", + "types": [ + "video" + ] + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.MediaIndexing.IndexFolder' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_media_indexing_status(self) -> dict: + """Get media indexing status. + + Returns + ------- + dict + Return the status of the media indexing service. + + Example return + ---------- + ```json + { + "data": { + "reindexing": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.MediaIndexing' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status' + } + return self.request_data(api_name, api_path, req_param) + + def get_thumbnail_quality_settings(self) -> dict: + """Get thumbnail quality settings. + + Returns + ------- + dict + Return the thumbnail quality settings. + + Example return + ---------- + ```json + { + "data": { + "packages": [], + "thumbnail_quality": "normal" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.MediaIndexing.ThumbnailQuality' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + pass \ No newline at end of file From 2c93deecaf12554d0aa4515c068b0eb2acd85358 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 6 Jul 2025 00:23:09 +0200 Subject: [PATCH 010/126] Implementation of Indexin Service --- .../DSM/ControlPanel/IndexingService.py | 189 ++++++++++++++++++ 1 file changed, 189 insertions(+) diff --git a/synology_api/DSM/ControlPanel/IndexingService.py b/synology_api/DSM/ControlPanel/IndexingService.py index 99ab5b41..1ef88ba5 100644 --- a/synology_api/DSM/ControlPanel/IndexingService.py +++ b/synology_api/DSM/ControlPanel/IndexingService.py @@ -115,4 +115,193 @@ def get_thumbnail_quality_settings(self) -> dict: } return self.request_data(api_name, api_path, req_param) + def get_shuduler_settings(self) -> dict: + """Get scheduler settings. + + Returns + ------- + dict + Return the scheduler settings of the indexing service. + + Example return + ---------- + ```json + { + "data": { + "duration": 1, + "manual_action_by_user": "none", + "mode": "schedule", + "start": { + "hour": 0 + }, + "week": [ + true, + true, + true, + true, + true, + true, + true + ] + }, + "success": true, + ``` + """ + api_name = 'SYNO.Core.MediaIndexing.Scheduler' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def set_indexed_folders(self, folders: list) -> dict: + """Set indexed folders. + + Parameters + ---------- + folders : list + A list of dictionaries representing the folders to be indexed. Each dictionary should contain: + - `path`: The path of the folder to be indexed. + - `name`: The name of the folder. + - `default`: A boolean indicating if this is a default folder. Should be `False` + - `types`: A list of media types to index in the folder (e.g., `["video"]`). Fiels are `photo`, `video`, `music`. + + example: + ```json + [ + { + "path": "/Films", + "name": "Films", + "default": false, + "types": ["video"] + }, + { + "path": "/Series", + "name": "Series", + "default": false, + "types": ["video"] + } + ] + ``` + + Returns + ------- + dict + Return the result of the operation. + + Example return + ---------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.MediaIndexing.IndexFolder' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'folders': folders + } + return self.request_data(api_name, api_path, req_param) + + def set_thumbnail_quality_settings(self, quality: str = "normal") -> dict: + """Set thumbnail quality settings. + + Parameters + ---------- + quality : str + The desired thumbnail quality setting. Options are `normal`, `high`. Default to `normal`. + + Returns + ------- + dict + Return the result of the operation. + + Example return + ---------- + ```json + { + "data": { + "thumbnail_quality": "normal" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.MediaIndexing.ThumbnailQuality' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'quality': quality + } + return self.request_data(api_name, api_path, req_param) + + def set_shudler_settings(self, mode: str = "always", start_hour: int = 0, duration: int = 1, week: list = [True, True, True, True, True, True, True]) -> dict: + """Set scheduler settings. + + Parameters + ---------- + mode : str + The scheduling mode. Options are `schedule`, `always`. Default to `always`. + start_hour : int + The hour to start the indexing service. Default to `0`. Not used if `mode` is set to `always`. + duration : int + The duration in hours for the indexing service. Default to `1`. Not used if `mode` is set to `always`. + week : list + A list of booleans indicating which days of the week the service should run. Default to `[True, True, True, True, True, True, True]`. Not used if `mode` is set to `always`. + + Returns + ------- + dict + Return the result of the operation. + + Example return + ---------- + ```json + { + "data": { + "duration": 1, + "manual_action_by_user": "none", + "mode": "schedule", + "start": { + "hour": 0 + }, + "week": [ + true, + true, + true, + true, + true, + true, + true + ] + }, + "success": true + } + ``` + """ + if week is None: + week = [True] * 7 + + api_name = 'SYNO.Core.MediaIndexing.Scheduler' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'mode': mode, + 'start': {'hour': start_hour}, + 'duration': duration, + 'week': week + } + return self.request_data(api_name, api_path, req_param) + + pass \ No newline at end of file From c1a328df23004349a482fb432f606377e261baa2 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 6 Jul 2025 00:38:46 +0200 Subject: [PATCH 011/126] First implementation of info center --- synology_api/DSM/ControlPanel/InfoCenter.py | 578 ++++++++++++++++++++ 1 file changed, 578 insertions(+) diff --git a/synology_api/DSM/ControlPanel/InfoCenter.py b/synology_api/DSM/ControlPanel/InfoCenter.py index 593b26b6..38fc2cf8 100644 --- a/synology_api/DSM/ControlPanel/InfoCenter.py +++ b/synology_api/DSM/ControlPanel/InfoCenter.py @@ -1,4 +1,582 @@ from synology_api import base_api class InfoCenter(base_api.BaseApi): + """ + Info center class for interacting with Synology DSM Info center settings. + + Supported methods: + - Getters: + + - Setters: + + """ + + def get_system_info(self) -> dict: + """Get system information. + + Returns + ------- + dict + Return system information including CPU, memory, and disk usage. + + Example return + ---------- + ```json + { + "data": { + "cpu_clock_speed": 2600, + "cpu_cores": "2", + "cpu_family": "Ryzen", + "cpu_series": "R1600", + "cpu_vendor": "AMD", + "enabled_ntp": true, + "external_pci_slot_info": [ + { + "Occupied": "no", + "Recognized": "no", + "cardName": "-", + "slot": "1" + } + ], + "firmware_date": "2025/01/20", + "firmware_ver": "DSM 7.2.2-72806 Update 3", + "model": "DS723+", + "ntp_server": "time.google.com", + "ram_size": 2048, + "sata_dev": [], + "serial": "YOUR-SERIAL-NUMBER", + "support_esata": "yes", + "sys_temp": 47, + "sys_tempwarn": false, + "systempwarn": false, + "temperature_warning": false, + "time": "2025-07-06 00:23:44", + "time_zone": "Amsterdam", + "time_zone_desc": "(GMT+01:00) Amsterdam, Berlin, Rome, Stockholm, Vienna", + "up_time": "49:46:21", + "usb_dev": [] + }, + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.System' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'info' + } + return self.request_data(api_name, api_path, req_param) + + def get_network_info(self) -> dict: + """Get network information. + + Returns + ------- + dict + Return network information including interfaces, IP addresses, and DNS settings. + + Example return + ---------- + ```json + { + "data": { + "dns": "YOUR-DNS", + "enabled_domain": false, + "enabled_samba": true, + "gateway": "YOUR-GATEWAY", + "hostname": "YOUR-HOSTNAME", + "nif": [ + { + "addr": "YOUR-IP-ADDRESS", + "duplex": true, + "id": "ovs_eth0", + "ipv6": [ + { + "addr": "YOUR-IPv6-ADDRESS", + "prefix_len": 64, + "scope": "global" + }, + { + "addr": "YOUR-IPv6-ADDRESS", + "prefix_len": 64, + "scope": "link" + } + ], + "mac": "YOUR-MAC-ADDRESS", + "mask": "255.255.255.0", + "mtu": 1500, + "speed": 1000, + "status": "connected", + "type": "ovseth", + "use_dhcp": true + }, + { + "addr": "YOUR-SECOND-IP-ADDRESS", + "duplex": true, + "id": "ovs_eth1", + "mac": "YOUR-SECOND-MAC-ADDRESS", + "mask": "255.255.0.0", + "mtu": 1500, + "speed": -1, + "status": "disconnected", + "type": "ovseth", + "use_dhcp": true + } + ], + "wins": "", + "workgroup": "WORKGROUP" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.System' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'info', + 'type': 'network' + } + return self.request_data(api_name, api_path, req_param) + + def get_storage_info(self) -> dict: + """Get storage information. + + Returns + ------- + dict + Return storage information including volumes, disks, and RAID status. + + Example return + ---------- + ```json + { + "data": { + "hdd_info": [ + { + "action": { + "alert": false, + "notification": false, + "selectable": true, + "show_lifetime_chart": true + }, + "action_status": { + "action_name": "idle", + "action_progress": "" + }, + "action_status_category": "processing", + "action_status_key": "idle", + "adv_progress": "", + "adv_status": "not_support", + "allocation_role": "reuse_1", + "below_remain_life_mail_notify_thr": false, + "below_remain_life_show_thr": false, + "below_remain_life_thr": false, + "compatibility": "support", + "container": { + "order": 0, + "str": "DS723+", + "supportPwrBtnDisable": false, + "type": "internal" + }, + "container_id": 0, + "device": "/dev/sata1", + "disable_secera": false, + "diskType": "SATA", + "disk_code": "", + "disk_location": "Main", + "drive_status_category": "health", + "drive_status_key": "normal", + "erase_time": 450, + "firm": "SC60", + "firmware_status": "-", + "has_system": true, + "hide_info": [], + "i18nNamingInfo": "[\"dsm:volume:volume_disk\",\" \",\"1\"]", + "id": "sata1", + "ihm_testing": false, + "is4Kn": false, + "isSsd": false, + "isSynoDrive": false, + "isSynoPartition": true, + "is_bundle_ssd": false, + "is_erasing": false, + "longName": "Drive 1", + "m2_pool_support": false, + "model": "ST4000VN006-3CW104", + "name": "Drive 1", + "num_id": 1, + "order": 1, + "overview_status": "normal", + "pciSlot": -1, + "perf_testing": false, + "portType": "normal", + "remain_life": { + "trustable": true, + "value": -1 + }, + "remain_life_danger": false, + "remote_info": { + "compatibility": "disabled", + "unc": 0 + }, + "sb_days_left": 0, + "sb_days_left_below_show_thres": false, + "sb_days_left_critical": false, + "sb_days_left_warning": false, + "serial": "YOUR-FIRST-SERIAL-NUMBER", + "size_total": "4000787030016", + "slot_id": 1, + "smart_progress": "", + "smart_status": "normal", + "smart_test_limit": 0, + "smart_test_support": true, + "smart_testing": false, + "ssd_unhealth_reason": "none", + "status": "normal", + "summary_status_category": "health", + "summary_status_key": "normal", + "temp": 35, + "testing_progress": "", + "testing_type": "idle", + "tray_status": "join", + "ui_serial": "YOUR-FIRST-SERIAL-NUMBER", + "unc": 0, + "used_by": "reuse_1", + "vendor": "Seagate", + "wcache_force_off": false, + "wcache_force_on": false, + "wdda_support": false + }, + { + "action": { + "alert": false, + "notification": false, + "selectable": true, + "show_lifetime_chart": true + }, + "action_status": { + "action_name": "idle", + "action_progress": "" + }, + "action_status_category": "processing", + "action_status_key": "idle", + "adv_progress": "", + "adv_status": "not_support", + "allocation_role": "reuse_1", + "below_remain_life_mail_notify_thr": false, + "below_remain_life_show_thr": false, + "below_remain_life_thr": false, + "compatibility": "support", + "container": { + "order": 0, + "str": "DS723+", + "supportPwrBtnDisable": false, + "type": "internal" + }, + "container_id": 0, + "device": "/dev/sata2", + "disable_secera": false, + "diskType": "SATA", + "disk_code": "", + "disk_location": "Main", + "drive_status_category": "health", + "drive_status_key": "normal", + "erase_time": 462, + "firm": "SC60", + "firmware_status": "-", + "has_system": true, + "hide_info": [], + "i18nNamingInfo": "[\"dsm:volume:volume_disk\",\" \",\"2\"]", + "id": "sata2", + "ihm_testing": false, + "is4Kn": false, + "isSsd": false, + "isSynoDrive": false, + "isSynoPartition": true, + "is_bundle_ssd": false, + "is_erasing": false, + "longName": "Drive 2", + "m2_pool_support": false, + "model": "ST4000VN006-3CW104", + "name": "Drive 2", + "num_id": 2, + "order": 2, + "overview_status": "normal", + "pciSlot": -1, + "perf_testing": false, + "portType": "normal", + "remain_life": { + "trustable": true, + "value": -1 + }, + "remain_life_danger": false, + "remote_info": { + "compatibility": "disabled", + "unc": 0 + }, + "sb_days_left": 0, + "sb_days_left_below_show_thres": false, + "sb_days_left_critical": false, + "sb_days_left_warning": false, + "serial": "YOUR-SECOND-SERIAL-NUMBER", + "size_total": "4000787030016", + "slot_id": 2, + "smart_progress": "", + "smart_status": "normal", + "smart_test_limit": 0, + "smart_test_support": true, + "smart_testing": false, + "ssd_unhealth_reason": "none", + "status": "normal", + "summary_status_category": "health", + "summary_status_key": "normal", + "temp": 37, + "testing_progress": "", + "testing_type": "idle", + "tray_status": "join", + "ui_serial": "YOUR-SECOND-SERIAL-NUMBER", + "unc": 0, + "used_by": "reuse_1", + "vendor": "Seagate", + "wcache_force_off": false, + "wcache_force_on": false, + "wdda_support": false + } + ], + "vol_info": [ + { + "desc": "", + "inode_free": "0", + "inode_total": "0", + "is_encrypted": false, + "name": "volume_1", + "status": "normal", + "total_size": "206158430208", + "used_size": "16905019392", + "vol_desc": "Apps", + "volume": "volume_1" + }, + { + "desc": "", + "inode_free": "0", + "inode_total": "0", + "is_encrypted": false, + "name": "volume_2", + "status": "normal", + "total_size": "3623234412544", + "used_size": "1154716925952", + "vol_desc": "Stockage", + "volume": "volume_2" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Storage' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'info', + 'type': 'storage_v2' + } + return self.request_data(api_name, api_path, req_param) + + def get_services_status(self) -> dict: + """Get services status. + + Returns + ------- + dict + Return the status of various services running on the Synology DSM. + + Example return + ---------- + ```json + { + "data": { + "service": [ + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "helptoc:winmacnfs_mac", + "enable_status": "disabled", + "service_id": "atalk" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "network:bonjourPrinter_subject", + "enable_status": "enabled", + "service_id": "bonjour" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "helptoc:ntp_service", + "enable_status": "enabled", + "service_id": "chronyd" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "service:cups_printer_daemon", + "enable_status": "static", + "service_id": "cupsd" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "tree:leaf_ftp", + "enable_status": "disabled", + "service_id": "ftp-pure" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "tree:leaf_ftpes", + "enable_status": "disabled", + "service_id": "ftp-ssl" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "remote_key:kmip_tab_title", + "enable_status": "disabled", + "service_id": "kmip-server" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "nfs:nfs_title", + "enable_status": "disabled", + "service_id": "nfs-server" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "tree:leaf_iscsi", + "enable_status": "static", + "service_id": "pkg-iscsi" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "helptoc:winmacnfs_win", + "enable_status": "enabled", + "service_id": "pkg-synosamba-smbd" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "service:wstransfer_title", + "enable_status": "enabled", + "service_id": "pkg-synosamba-wstransfer-genconf" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "service:service_rsync", + "enable_status": "enabled", + "service_id": "rsyncd" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "tree:leaf_sftp", + "enable_status": "disabled", + "service_id": "sftp" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "SNMP", + "enable_status": "static", + "service_id": "snmpd" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "firewall:firewall_service_opt_ssh", + "enable_status": "enabled", + "service_id": "ssh-shell" + }, + { + "additional": { + "active_status": "active" + }, + "display_name_section_key": "about:dsm", + "enable_status": "static", + "service_id": "synoscgi" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "firewall:firewall_service_opt_telnet", + "enable_status": "disabled", + "service_id": "telnetd" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "ftp:tftp_title", + "enable_status": "disabled", + "service_id": "tftp" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "helptoc:power_ups", + "enable_status": "disabled", + "service_id": "ups-net" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "helptoc:power_ups", + "enable_status": "static", + "service_id": "ups-usb" + } + ] + }, + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.Service' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get', + 'additional': ['active_status'] + } + return self.request_data(api_name, api_path, req_param) + + pass \ No newline at end of file From c49b3aa5e163ac32b02ee3a43dcf1b235295919e Mon Sep 17 00:00:00 2001 From: Lubos Zima Date: Thu, 3 Jul 2025 21:37:17 +0700 Subject: [PATCH 012/126] fix: synology_api/base_api.py update docstrings to comply with Numpydoc standards --- synology_api/base_api.py | 115 +++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 35 deletions(-) diff --git a/synology_api/base_api.py b/synology_api/base_api.py index c1702e64..909456d5 100644 --- a/synology_api/base_api.py +++ b/synology_api/base_api.py @@ -1,42 +1,46 @@ +""" +Base API module for Synology DSM. + +Provides a base class for all API implementations, handling authentication, +session management, and connection setup to a Synology NAS device. +""" from typing import Optional, Any from . import auth as syn class BaseApi(object): - """Base class to be used for all API implementations. - - Takes auth and connection information to create a session to the NAS. - - The session is created on instanciation. - - Parameters - ---------- - ip_address : str - The IP/DNS address of the NAS. - - port : str - The port of the NAS. Defaults to `5000`. - - username : str - The username to use for authentication. - - password : str - The password to use for authentication. - - secure : bool - Whether to use HTTPS or not. Defaults to `False`. - - cert_verify : bool - Whether to verify the SSL certificate or not. Defaults to `False`. - - dsm_version : int - The DSM version. Defaults to `7`. - - debug : bool - Whether to print debug messages or not. Defaults to `True`. - - otp_code : str - The OTP code to use for authentication. Defaults to `None` + """ + Base class to be used for all API implementations. + + Takes auth and connection information to create a session to the NAS. + The session is created on instanciation. + + Parameters + ---------- + ip_address : str + The IP/DNS address of the NAS. + port : str + The port of the NAS. Defaults to `5000`. + username : str + The username to use for authentication. + password : str + The password to use for authentication. + secure : bool, optional + Whether to use HTTPS or not. Defaults to `False`. + cert_verify : bool, optional + Whether to verify the SSL certificate or not. Defaults to `False`. + dsm_version : int, optional + The DSM version. Defaults to `7`. + debug : bool, optional + Whether to print debug messages or not. Defaults to `True`. + otp_code : str, optional + The OTP code to use for authentication. Defaults to `None`. + device_id : str, optional + Device ID for device binding. Defaults to `None`. + device_name : str, optional + Device name for device binding. Defaults to `None`. + application : str, optional + The application context for API list retrieval. Defaults to `'Core'`. """ # Class-level attribute to store the shared session @@ -56,7 +60,41 @@ def __init__(self, device_name: Optional[str] = None, application: str = 'Core', ) -> None: + """ + Initialize the BaseApi object and create or reuse a session. + Parameters + ---------- + ip_address : str + The IP/DNS address of the NAS. + port : str + The port of the NAS. + username : str + The username to use for authentication. + password : str + The password to use for authentication. + secure : bool, optional + Whether to use HTTPS or not. Defaults to `False`. + cert_verify : bool, optional + Whether to verify the SSL certificate or not. Defaults to `False`. + dsm_version : int, optional + The DSM version. Defaults to `7`. + debug : bool, optional + Whether to print debug messages or not. Defaults to `True`. + otp_code : str, optional + The OTP code to use for authentication. Defaults to `None`. + device_id : str, optional + Device ID for device binding. Defaults to `None`. + device_name : str, optional + Device name for device binding. Defaults to `None`. + application : str, optional + The application context for API list retrieval. Defaults to `'Core'`. + + Returns + ------- + None + Just actions, no return values. + """ self.application = application # Reuse shared session if it exists, otherwise create a new one @@ -87,7 +125,14 @@ def __init__(self, self.base_url: str = self.session.base_url def logout(self) -> None: - """Close current session.""" + """ + Close current session. + + Returns + ------- + None + Action, no return values. + """ api_name = 'hotfix' # fix for docs_parser.py issue if self.session: self.session.logout() From 34f41c9862c40f7505510dd3147a0024461c75c0 Mon Sep 17 00:00:00 2001 From: luboszima Date: Tue, 8 Jul 2025 21:23:05 +0700 Subject: [PATCH 013/126] fix: synology_api/cloud_sync.py update docstrings to comply with Numpydoc standards --- synology_api/cloud_sync.py | 209 +++++++++++++++++++++---------------- 1 file changed, 120 insertions(+), 89 deletions(-) diff --git a/synology_api/cloud_sync.py b/synology_api/cloud_sync.py index bb95f033..4ce5aff0 100644 --- a/synology_api/cloud_sync.py +++ b/synology_api/cloud_sync.py @@ -1,3 +1,9 @@ +""" +CloudSync API module. + +This module provides the CloudSync class, which implements methods to interact with Synology's Cloud Sync API. +It allows retrieving and setting package settings, managing cloud connections and tasks, and handling synchronization processes. +""" from __future__ import annotations from typing import Any from . import base_api @@ -6,7 +12,8 @@ class CloudSync(base_api.BaseApi): - """Cloud Sync API implementation. + """ + Cloud Sync API implementation. This API provides the functionality to get information related to the package settings and current connections and tasks. It also provides functionalities to set most of the settings for tasks and package configuration, as well as manage the current syncing processes. @@ -45,11 +52,11 @@ class CloudSync(base_api.BaseApi): - Delete task - Validate task settings - Create S3 task - """ def get_pkg_config(self) -> dict[str, object]: - """Retrieve package settings. + """ + Retrieve package settings. Returns ------- @@ -103,7 +110,8 @@ def get_pkg_config(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_connections(self, group_by: str = 'group_by_user') -> dict[str, object]: - """Retrieve a list of current cloud connections. + """ + Retrieve a list of current cloud connections. Parameters ---------- @@ -175,7 +183,8 @@ def get_connections(self, group_by: str = 'group_by_user') -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_connection_settings(self, conn_id: int) -> dict[str, object]: - """Retrieve settings for a specific connection. + """ + Retrieve settings for a specific connection. Parameters ---------- @@ -219,7 +228,8 @@ def get_connection_settings(self, conn_id: int) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_connection_information(self, conn_id: int) -> dict[str, object]: - """Retrieve cloud information for a specific connection. + """ + Retrieve cloud information for a specific connection. Parameters ---------- @@ -267,7 +277,8 @@ def get_connection_information(self, conn_id: int) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_connection_auth(self, conn_id: int) -> dict[str, object]: - """Retrieve authentication information for a specific connection. + """ + Retrieve authentication information for a specific connection. Parameters ---------- @@ -344,7 +355,8 @@ def get_connection_logs( offset: int = 0, limit: int = 200 ) -> dict[str, object]: - """Retrieve logs for a specific connection. + """ + Retrieve logs for a specific connection. Parameters ---------- @@ -445,7 +457,8 @@ def get_connection_logs( return self.request_data(api_name, api_path, req_param) def get_tasks(self, conn_id: int) -> dict[str, object]: - """Retrieve a list of tasks related to a specific connection. + """ + Retrieve a list of tasks related to a specific connection. Parameters ---------- @@ -495,7 +508,8 @@ def get_tasks(self, conn_id: int) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_task_filters(self, sess_id: int) -> dict[str, object]: - """Retrieve filter information for a specific task. + """ + Retrieve filter information for a specific task. Parameters ---------- @@ -553,7 +567,8 @@ def get_task_cloud_folders( remote_folder_id: str, path: str = '/' ) -> dict[str, object]: - """Retrieve a list of children directories in the cloud for a specific task. + """ + Retrieve a list of children directories in the cloud for a specific task. Parameters ---------- @@ -622,7 +637,8 @@ def get_task_cloud_folders( return self.request_data(api_name, api_path, req_param) def get_recently_modified(self) -> dict[str, object]: - """Retrieve the 5 latest modified files and the currently syncing items. + """ + Retrieve the 5 latest modified files and the currently syncing items. Returns ------- @@ -722,7 +738,8 @@ def set_pkg_config( workers: int = 3, admin_mode: bool = True ) -> dict[str, object]: - """Set package configuration settings. + """ + Set package configuration settings. Parameters ---------- @@ -768,7 +785,8 @@ def set_pkg_config( return self.request_data(api_name, api_path, req_param) def set_relink_behavior(self, delete_from_cloud: bool) -> dict[str, object]: - """Set the relinking behavior for personal user accounts. + """ + Set the relinking behavior for personal user accounts. Warning: Miss-configuration of this action may lead to data loss. @@ -814,7 +832,8 @@ def set_connection_settings( isSSE: bool = False, part_size: int = 128 ) -> dict[str, object]: - """Set settings for a specific cloud connection. + """ + Set settings for a specific cloud connection. Parameters ---------- @@ -880,7 +899,8 @@ def set_connection_schedule( enable: bool, schedule_info: list[str] = [] ) -> dict[str, object]: - """Set the schedule for a specific connection. + """ + Set the schedule for a specific connection. Parameters ---------- @@ -910,7 +930,7 @@ def set_connection_schedule( '111111111111111111111111', # saturday - hours from 0 to 23 ] set_connection_schedule(conn_id=3, enable=True, schedule_info=days) - ``` + ```. Returns ------- @@ -951,7 +971,8 @@ def set_task_settings( no_delete_on_cloud: bool = True, convert_gd: bool = False ) -> dict[str, object]: - """Set the task settings for a specific session. + """ + Set the task settings for a specific session. Parameters ---------- @@ -1011,7 +1032,8 @@ def set_task_filters( filtered_extensions: list[str] = [], max_upload_size: int = 0 ) -> dict[str, object]: - """Set task filters for selective synchronization in a specific session. + """ + Set task filters for selective synchronization in a specific session. Parameters ---------- @@ -1061,7 +1083,8 @@ def set_task_filters( return self.request_data(api_name, api_path, req_param) def connection_pause(self, conn_id: int = -1) -> dict[str, object]: - """Pause one or all connections. + """ + Pause one or all connections. Parameters ---------- @@ -1095,7 +1118,8 @@ def connection_pause(self, conn_id: int = -1) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def connection_resume(self, conn_id: int = -1) -> dict[str, object]: - """Resume one or all connections. + """ + Resume one or all connections. Parameters ---------- @@ -1129,7 +1153,8 @@ def connection_resume(self, conn_id: int = -1) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def connection_remove(self, conn_id: int) -> dict[str, object]: - """Remove a specific connection and all associated tasks. + """ + Remove a specific connection and all associated tasks. The data will remain in both the local and remote directories. @@ -1167,7 +1192,8 @@ def task_remove( conn_id: int, sess_id: int ) -> dict[str, object]: - """Remove a specific task. + """ + Remove a specific task. The data will remain in both the local and remote directories. @@ -1215,7 +1241,8 @@ def __generate_sync_task_s3_params( filter_names: list[str] = [], server_folder_id: str = '', ) -> dict[str, Any]: - """Generate parameters for creating a sync task with S3. + """ + Generate parameters for creating a sync task with S3. Parameters ---------- @@ -1243,6 +1270,9 @@ def __generate_sync_task_s3_params( filter_names : list[str], optional List of file names to filter. Defaults to `[]`. + server_folder_id : str, optional + The unique identifier of the remote (cloud) folder to be synchronized. Defaults ``. + Returns ------- dict[str, Any] @@ -1294,7 +1324,7 @@ def __generate_sync_task_s3_params( # Merge authentication details with request parameters return merge_dicts(auth['data'], create_session_request_params) - def test_task_setting( + def create_sync_task_s3( self, conn_id: int, local_path: str, @@ -1304,8 +1334,9 @@ def test_task_setting( file_filter: list[str] = [], filter_max_upload_size: int = 0, filter_names: list[str] = [], - ) -> tuple[bool, dict[str, object] | str]: - """Test the task settings make sure they are valid. + ) -> tuple[bool, Any]: + """ + Add a new synchronization task. Parameters ---------- @@ -1335,11 +1366,17 @@ def test_task_setting( Returns ------- - tuple[bool, dict[str, object] | str] - A tuple containing a boolean indicating success, and a dictionary or string with the result. + tuple[bool, Any] + A tuple containing the result of the task creation. """ - # Generate sync task parameters - creation_params = self.generate_sync_task_s3_params( + + # Validate is connection is Amazon S3 + conn_info = self.get_connection_information(conn_id) + if conn_info['data']['type'] != 'az': + return (False, 'Connection is not Amazon S3') + + # Merge authentication details with request parameters + creation_params = self.__generate_sync_task_s3_params( conn_id, local_path, cloud_path, @@ -1349,41 +1386,53 @@ def test_task_setting( filter_max_upload_size, filter_names ) - # Prepare API request data api_name = 'SYNO.CloudSync' info = self.gen_list[api_name] - request_params = { + # Run test task setting + test_result = self.test_task_setting( + conn_id, + local_path, + cloud_path, + sync_direction, + storage_class, + file_filter, + filter_max_upload_size, + filter_names + ) + if not test_result[0]: + return (False, test_result[1]) + + create_session_request = { 'api': api_name, - 'method': 'test_task_setting', + 'method': 'create_session', 'version': info['minVersion'], - 'conn_info': creation_params + 'conn_info': creation_params, } + list_session_request = { + 'api': api_name, + 'method': 'list_sess', + 'version': info['minVersion'], + 'connection_id': conn_id + } + # Compound data + compound_data = [create_session_request, list_session_request] + # Send request and return response + return (True, self.batch_request(compound_data, method='post')) - # Send request and get result - compound_data = [request_params] - result = self.batch_request(compound_data, method='post') - - # Check if the request was successful - if result is not None and result['data']['has_fail'] == False: - # print('Task setting is valid') - return (True, result['data']) - else: - # print('Task setting is invalid') - return (False, 'Invalid task setting') - - def create_sync_task_s3( + def test_task_setting( self, conn_id: int, local_path: str, cloud_path: str, sync_direction='BIDIRECTION', storage_class='STANDARD', - filter_max_upload_size: int = 0, file_filter: list[str] = [], + filter_max_upload_size: int = 0, filter_names: list[str] = [], - ) -> tuple[bool, Any]: - """Add a new synchronization task. + ) -> tuple[bool, dict[str, object] | str]: + """ + Test the task settings make sure they are valid. Parameters ---------- @@ -1411,20 +1460,13 @@ def create_sync_task_s3( filter_names : list[str], optional List of file names to filter. Defaults to `[]`. - Returns ------- - tuple[bool, Any] - A tuple containing the result of the task creation. + tuple[bool, dict[str, object] | str] + A tuple containing a boolean indicating success, and a dictionary or string with the result. """ - - # Validate is connection is Amazon S3 - conn_info = self.get_connection_information(conn_id) - if conn_info['data']['type'] != 'az': - return (False, 'Connection is not Amazon S3') - - # Merge authentication details with request parameters - creation_params = self.__generate_sync_task_s3_params( + # Generate sync task parameters + creation_params = self.generate_sync_task_s3_params( conn_id, local_path, cloud_path, @@ -1434,36 +1476,25 @@ def create_sync_task_s3( filter_max_upload_size, filter_names ) + # Prepare API request data api_name = 'SYNO.CloudSync' info = self.gen_list[api_name] - # Run test task setting - test_result = self.test_task_setting( - conn_id, - local_path, - cloud_path, - sync_direction, - storage_class, - file_filter, - filter_max_upload_size, - filter_names - ) - if not test_result[0]: - return (False, test_result[1]) - - create_session_request = { - 'api': api_name, - 'method': 'create_session', - 'version': info['minVersion'], - 'conn_info': creation_params, - } - list_session_request = { + request_params = { 'api': api_name, - 'method': 'list_sess', + 'method': 'test_task_setting', 'version': info['minVersion'], - 'connection_id': conn_id + 'conn_info': creation_params } - # Compound data - compound_data = [create_session_request, list_session_request] - # Send request and return response - return (True, self.batch_request(compound_data, method='post')) + + # Send request and get result + compound_data = [request_params] + result = self.batch_request(compound_data, method='post') + + # Check if the request was successful + if result is not None and result['data']['has_fail'] == False: + # print('Task setting is valid') + return (True, result['data']) + else: + # print('Task setting is invalid') + return (False, 'Invalid task setting') From 340192ccf6d9dfa99d531a3822b894734707636f Mon Sep 17 00:00:00 2001 From: Renato <33936751+N4S4@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:19:36 +0200 Subject: [PATCH 014/126] Update filestation.py get_file_list fail additional file attribute fix #257 --- synology_api/filestation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index 16e03d8f..6c36dfd3 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -122,8 +122,8 @@ def get_file_list(self, if additional is None: additional = ['real_path', 'size', 'owner', 'time'] - if type(additional) is list: - additional = ','.join(additional) + #if type(additional) is list: + # additional = ','.join(additional) req_param['additional'] = additional From f2a22d99b9e9dae82981803f80f6c40b34393a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 20:22:34 +0700 Subject: [PATCH 015/126] fix: synology_api/core_active_backup.py update docstrings to comply with Numpydoc standards --- synology_api/core_active_backup.py | 114 +++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 31 deletions(-) diff --git a/synology_api/core_active_backup.py b/synology_api/core_active_backup.py index fe730dc5..a826735a 100644 --- a/synology_api/core_active_backup.py +++ b/synology_api/core_active_backup.py @@ -1,3 +1,4 @@ +"""Active Backup for Business API Implementation.""" from __future__ import annotations from . import base_api @@ -6,7 +7,8 @@ class ActiveBackupBusiness(base_api.BaseApi): - """Active Backup for Business API Implementation. + """ + Active Backup for Business API Implementation. This class provides methods to interact with the Active Backup for Business package. @@ -46,7 +48,31 @@ def __create_filter( action_type: str = "" ): """ - Create a filter dictionary based on the provided parameters. + Create a filter dictionary for API requests based on provided parameters. + + Parameters + ---------- + log_level : str, optional + Log level to filter by. Possible values: 'error', 'warning', 'information'. Defaults to "" (all). + keyword : str, optional + Keyword to filter logs or tasks. Defaults to "" (no keyword). + from_date : int, optional + Start of the time window (epoch seconds). Defaults to 0 (no lower bound). + to_date : int, optional + End of the time window (epoch seconds). Defaults to 0 (no upper bound). + task_status : str, optional + Task status to filter by. Defaults to "" (all statuses). + result_status : str, optional + Result status to filter by. Possible values: 'success', 'partial_success', 'fail', 'cancel', 'no_backup'. Defaults to "" (all). + backup_type : str, optional + Backup type to filter by. Possible values: 'vm', 'pc', 'physical_server', 'file_server', 'nas'. Defaults to "" (all). + action_type : str, optional + Action type to filter by. Possible values: 'backup', 'dedup_data', 'restore', 'migrate', 'delete_target', 'delete_version', 'delete_host', 'relink', 'create_task'. Defaults to "" (all). + + Returns + ------- + dict + Dictionary containing filter parameters for API requests. """ log_level_map = { 'error': 0, @@ -104,7 +130,8 @@ def __create_filter( return filter def get_settings(self) -> dict[str, object]: - """Get the package settings including certificate information. + """ + Get the package settings including certificate information. Returns ------- @@ -198,7 +225,8 @@ def get_settings(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def set_concurrent_devices(self, value: int) -> dict[str, object]: - """Set the maximum number of concurrent devices that can be backed up at the same time. + """ + Set the maximum number of concurrent devices that can be backed up at the same time. Note: You can run multiple concurrent backup devices, but only up to the maximum limit you set—provided that your NAS's RAM usage does not exceed its limit. @@ -239,7 +267,8 @@ def set_concurrent_devices(self, value: int) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def set_retention_policy_exec_time(self, hour: int, minute: int) -> dict[str, object]: - """Set the time of day when the retention policy will be executed. + """ + Set the time of day when the retention policy will be executed. Parameters ---------- @@ -247,7 +276,7 @@ def set_retention_policy_exec_time(self, hour: int, minute: int) -> dict[str, ob Hour in 24-hour format (0 - 23) when the retention policy will be executed. minute : int - Minute (0 - 59) when the retention policy will be executed + Minute (0 - 59) when the retention policy will be executed. Returns ------- @@ -283,7 +312,8 @@ def set_traffic_throttle( traffic_control: dict[str, object] = {"enable": False, "bandwidth": 0}, ip_range: list[str] = ["", ""] ) -> dict[str, object]: - """Set the global bandwidth control and IP range bandwidth control. + """ + Set the global bandwidth control and IP range bandwidth control. Note: Applies only to PC, Physical Server and NAS devices. @@ -308,7 +338,7 @@ def set_traffic_throttle( Example: ```python ["192.168.0.1", "192.168.0.10"] - ``` + ```. Returns ------- @@ -329,6 +359,21 @@ def set_traffic_throttle( settings = [] def item(key: str, value: str) -> dict[str, str]: + """ + Create a dictionary representing a setting item. + + Parameters + ---------- + key : str + The name of the setting. + value : str + The value of the setting. + + Returns + ------- + dict[str, str] + Dictionary with 'name' and 'value' keys. + """ return {'name': key, 'value': value} if traffic_control['enable'] and traffic_control['bandwidth'] > -1: @@ -357,7 +402,8 @@ def item(key: str, value: str) -> dict[str, str]: return self.request_data(api_name, api_path, req_param) def set_use_pkg_cert(self, use_package_cert: bool) -> dict[str, object]: - """Set whether to use the self signed certificate provided by the package. + """ + Set whether to use the self signed certificate provided by the package. Parameters ---------- @@ -391,7 +437,8 @@ def set_use_pkg_cert(self, use_package_cert: bool) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def list_vm_hypervisor(self) -> dict[str, object]: - """Get a list of all configured hypervisors present in ABB. + """ + Get a list of all configured hypervisors present in ABB. Returns ------- @@ -416,7 +463,8 @@ def list_device_transfer_size( time_start: int = int(time.time() - 86400), time_end: int = int(time.time()) ) -> dict[str, object]: - """Get a list of all devices and their respective transfer size for the given time frame. + """ + Get a list of all devices and their respective transfer size for the given time frame. Parameters ---------- @@ -558,12 +606,13 @@ def list_tasks( to_date: int = 0, include_versions: bool = False, ) -> dict[str, object]: - """Get information of one or all tasks. + """ + Get information of one or all tasks. Parameters ---------- task_id : int, optional - Get information of specific task. Defaults to `-1` (all tasks) + Get information of specific task. Defaults to `-1` (all tasks). backup_type : str, optional Return only tasks matching the device type provided. Defaults to `""` (all device types). @@ -575,7 +624,6 @@ def list_tasks( - `"file_server"` - `"nas"` - Note that values are different when returned by the API. Return values mappings: @@ -823,14 +871,15 @@ def list_logs( offset: int = 0, limit: int = 200, ) -> dict[str, object]: - """Get logs from the package, tasks and devices. From `[Activities -> Log]` screen in ABB. + """ + Get logs from the package, tasks and devices. From `[Activities -> Log]` screen in ABB. For specific task logs `[Task List -> Details -> Log]`, specify `task_id` parameter. Parameters ---------- task_id : int, optional - Get logs of specific task. Defaults to `-1` (all logs - package/tasks/devices) + Get logs of specific task. Defaults to `-1` (all logs - package/tasks/devices). log_level : str, optional Type of logs to return. Defaults to `""` (all types). @@ -840,7 +889,6 @@ def list_logs( - `"warning"` - `"information"` - Note that values are different when returned by the API. Return values mappings: @@ -933,12 +981,13 @@ def task_history( offset: int = 0, limit: int = 200 ) -> dict[str, object]: - """Return the history of task execution. + """ + Return the history of task execution. Parameters ---------- task_id : int, optional - Get logs of specific task. Defaults to `-1` (all tasks) + Get logs of specific task. Defaults to `-1` (all tasks). status : str, optional Return only tasks matching the status provided. Defaults to `""` (all status). @@ -949,7 +998,6 @@ def task_history( - `"fail"` - `"cancel"` - Note that values are different when returned by the API. Return values mappings: @@ -958,6 +1006,9 @@ def task_history( - `4` -> `fail` - `5` -> `cancel` + keyword : str, optional + Keyword used to filter the results. Defaults to `""`. + backup_type : str, optional Return only tasks matching the device type provided. Defaults to `""` (all device types). @@ -968,7 +1019,6 @@ def task_history( - `"file_server"` - `"nas"` - Note that values are different when returned by the API. Return values mappings: @@ -992,7 +1042,6 @@ def task_history( - `"relink"` - `"create_task"` - Note that values are different when returned by the API. Return values mappings: @@ -1006,9 +1055,6 @@ def task_history( - `2097152` -> `relink` - `268435456` -> `create_task` - keyword : str, optional - Keyword used to filter the results. Defaults to `""`. - from_date : int, optional Date from which the results will start. Format must be epoch date in seconds. Defaults to `0` (no time limit). @@ -1093,7 +1139,8 @@ def result_details( order_by: str = "log_level", direction: str = "ASC" ) -> dict[str, object]: - """Get details of a task result log. `result_id` can be retrieved from `list_logs()` function. + """ + Get details of a task result log. `result_id` can be retrieved from `list_logs()` function. Parameters ---------- @@ -1179,7 +1226,8 @@ def result_details( return self.request_data(api_name, api_path, req_param) def list_storage(self) -> dict[str, object]: - """Get a list of all storage devices present in ABB. + """ + Get a list of all storage devices present in ABB. Returns ------- @@ -1249,7 +1297,8 @@ def list_storage(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def backup_task_run(self, task_ids: list[int]) -> dict[str, object]: - """Trigger a backup event for the given tasks. + """ + Trigger a backup event for the given tasks. Parameters ---------- @@ -1285,7 +1334,8 @@ def backup_task_run(self, task_ids: list[int]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def backup_task_cancel(self, task_ids: list[int]) -> dict[str, object]: - """Cancel specified ongoing task. + """ + Cancel specified ongoing task. Parameters ---------- @@ -1320,7 +1370,8 @@ def backup_task_cancel(self, task_ids: list[int]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def backup_task_remove(self, task_ids: list[int]) -> dict[str, object]: - """Remove the given tasks from ABB. + """ + Remove the given tasks from ABB. Warning: This will remove the task and all its versions from the NAS. The backed up data will not be preserved after this operation. @@ -1357,7 +1408,8 @@ def backup_task_remove(self, task_ids: list[int]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def backup_task_delete_versions(self, task_id: int, versions_ids: list[int]) -> dict[str, object]: - """Delete the specified versions from a task. + """ + Delete the specified versions from a task. Warning: This will remove the specified versions from the NAS. The corresponding versions data will not be preserved after this operation. From 3439ffdf49879244a14bbcc0ef2fb6ca2de992d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 20:41:53 +0700 Subject: [PATCH 016/126] fix: synology_api/core_backup.py update docstrings to comply with Numpydoc standards --- synology_api/core_backup.py | 344 +++++++++++++++++++++++++++++------- 1 file changed, 280 insertions(+), 64 deletions(-) diff --git a/synology_api/core_backup.py b/synology_api/core_backup.py index 81541804..7295e418 100644 --- a/synology_api/core_backup.py +++ b/synology_api/core_backup.py @@ -1,13 +1,25 @@ +"""Synology Hyper Backup API.""" from __future__ import annotations from . import base_api class Backup(base_api.BaseApi): + """Synology Hyper Backup API.""" def backup_repository_get(self, task_id: str) -> dict[str, object] | str: - ''' - Get repository information for given task. - ''' + """ + Get repository information for a given task. + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + Repository information. + """ api_name = 'SYNO.Backup.Repository' info = self.gen_list[api_name] api_path = info['path'] @@ -17,9 +29,14 @@ def backup_repository_get(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_repository_list(self) -> dict[str, object] | str: - ''' + """ Get a list of all present repositories in Hyper Backup. - ''' + + Returns + ------- + dict[str, object] or str + List of repositories. + """ api_name = 'SYNO.Backup.Repository' info = self.gen_list[api_name] api_path = info['path'] @@ -28,9 +45,14 @@ def backup_repository_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_list(self) -> dict[str, object] | str: - ''' + """ Get current restoring information and a list of present tasks in Hyper Backup. - ''' + + Returns + ------- + dict[str, object] or str + List of tasks and restoring information. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -39,9 +61,19 @@ def backup_task_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_status(self, task_id: str) -> dict[str, object] | str: - ''' - Get status and state of task. - ''' + """ + Get status and state of a task. + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + Status and state information. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -51,9 +83,19 @@ def backup_task_status(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_get(self, task_id: str) -> dict[str, object] | str: - ''' + """ Get detailed task information. - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + Task information. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -63,9 +105,19 @@ def backup_task_get(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_result(self, task_id: str) -> dict[str, object] | str: - ''' + """ Get last result summary information of a task. - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + Last result summary. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -76,10 +128,21 @@ def backup_task_result(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_run(self, task_id: str) -> dict[str, object] | str: - ''' + """ Run backup task for corresponding task_id. + If the task is not in backupable state, the API will return an error, usually 44xx. - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -91,10 +154,21 @@ def backup_task_run(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_cancel(self, task_id: str) -> dict[str, object] | str: - ''' + """ Cancel currently running backup task. + If the task is not running, the API will return an error, usually 44xx. - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -107,10 +181,21 @@ def backup_task_cancel(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_suspend(self, task_id: str) -> dict[str, object] | str: - ''' + """ Suspend currently running backup task. + If the task is not running or not yet suspendable, the API will return an error, usually 44xx. - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -123,10 +208,21 @@ def backup_task_suspend(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_discard(self, task_id: str) -> dict[str, object] | str: - ''' + """ Discard currently suspended backup task. + If the task is not suspended, the request will not fail, and will fail to discard the task, leaving the task state as "Failed". - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -138,10 +234,21 @@ def backup_task_discard(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_resume(self, task_id: str) -> dict[str, object] | str: - ''' - Discard currently suspended backup task. + """ + Resume currently suspended backup task. + If the task is not suspended, the request will not fail, and will fail to resume the task, leaving the task state as "Failed". - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -153,12 +260,23 @@ def backup_task_resume(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def backup_task_remove(self, task_id_list: str) -> dict[str, object] | str: - ''' + """ Remove one or more backup tasks. + Data in destination will not be removed. It is still possible to relink the task using the original .hbk file. The API requires an array of tasks to remove, it should be passed as a string with the following format: - `task_id_list = '[29]'` || `task_id_list = '[29,15]'` - ''' + `task_id_list = '[29]'` or `task_id_list = '[29,15]'` + + Parameters + ---------- + task_id_list : str + List of task IDs as a string. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Task' info = self.gen_list[api_name] api_path = info['path'] @@ -171,10 +289,21 @@ def backup_task_remove(self, task_id_list: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def integrity_check_run(self, task_id: str) -> dict[str, object] | str: - ''' + """ Run integrity check for backup task. - If the task is running, the request will not fail, and will fail to perform the integrity check due to target is busy. - ''' + + If the task is running, the request will not fail, and will fail to perform the integrity check due to target being busy. + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Target' info = self.gen_list[api_name] api_path = info['path'] @@ -189,10 +318,21 @@ def integrity_check_run(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def integrity_check_cancel(self, task_id: str) -> dict[str, object] | str: - ''' + """ Cancel currently running integrity check for backup task. + If integrity check is not running, the API will return an error, usually 44xx. - ''' + + Parameters + ---------- + task_id : str + Task ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Backup.Target' info = self.gen_list[api_name] api_path = info['path'] @@ -203,18 +343,38 @@ def integrity_check_cancel(self, task_id: str) -> dict[str, object] | str: } return self.request_data(api_name, api_path, req_param) - def hb_logs_get(self, - limit: int = 1000, - offset: int = 0, - filter_keyword: str = '', - # filter_level: str = '', For some reason when passing filter_level, the API returns error 120. - filter_date_from: int = 0, - filter_date_to: int = 0) -> dict[str, object] | str: - ''' + def hb_logs_get( + self, + limit: int = 1000, + offset: int = 0, + filter_keyword: str = '', + # filter_level: str = '', For some reason when passing filter_level, the API returns error 120. + filter_date_from: int = 0, + filter_date_to: int = 0 + ) -> dict[str, object] | str: + """ Get Hyper Backup UI logs. `filter_date_from` and `filter_date_to` need to be passed in epoch format. - ''' + + Parameters + ---------- + limit : int, optional + Maximum number of logs to return (default is 1000). + offset : int, optional + Offset for pagination (default is 0). + filter_keyword : str, optional + Keyword to filter logs (default is ''). + filter_date_from : int, optional + Start date in epoch format (default is 0). + filter_date_to : int, optional + End date in epoch format (default is 0). + + Returns + ------- + dict[str, object] or str + Logs information. + """ api_name = 'SYNO.SDS.Backup.Client.Common.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -230,10 +390,15 @@ def hb_logs_get(self, } return self.request_data(api_name, api_path, req_param) - def vault_target_list(self) -> dict[str, object]: # Should be working now - ''' + def vault_target_list(self) -> dict[str, object]: + """ List all available targets in Vault. - ''' + + Returns + ------- + dict[str, object] + List of available targets. + """ api_name = 'SYNO.Backup.Service.VersionBackup.Target' info = self.gen_list[api_name] api_path = info['path'] @@ -242,9 +407,14 @@ def vault_target_list(self) -> dict[str, object]: # Should be working now return self.request_data(api_name, api_path, req_param) def vault_concurrency_get(self) -> dict[str, object]: - ''' - Get number of concurrent tasks allowed to run in HB Vault. Default value is 2. - ''' + """ + Get number of concurrent tasks allowed to run in HB Vault. + + Returns + ------- + dict[str, object] + Number of concurrent tasks (default is 2). + """ api_name = 'SYNO.Backup.Service.VersionBackup.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -255,9 +425,19 @@ def vault_concurrency_get(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def vault_concurrency_set(self, parallel_backup_limit: int = 2) -> dict[str, object]: - ''' - Set number of concurrent tasks allowed to run in HB Vault. Default value is 2. - ''' + """ + Set number of concurrent tasks allowed to run in HB Vault. + + Parameters + ---------- + parallel_backup_limit : int, optional + Number of concurrent tasks (default is 2). + + Returns + ------- + dict[str, object] + API response. + """ api_name = 'SYNO.Backup.Service.VersionBackup.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -269,9 +449,19 @@ def vault_concurrency_set(self, parallel_backup_limit: int = 2) -> dict[str, obj return self.request_data(api_name, api_path, req_param) def vault_target_settings_get(self, target_id: int) -> dict[str, object]: - ''' - Get settings of target. - ''' + """ + Get settings of a target. + + Parameters + ---------- + target_id : int + Target ID. + + Returns + ------- + dict[str, object] + Target settings. + """ api_name = 'SYNO.Backup.Service.VersionBackup.Target' info = self.gen_list[api_name] api_path = info['path'] @@ -283,9 +473,19 @@ def vault_target_settings_get(self, target_id: int) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def vault_task_statistics_get(self, task_id: int) -> dict[str, object]: - ''' - Get statistics for given task. - ''' + """ + Get statistics for a given task. + + Parameters + ---------- + task_id : int + Task ID. + + Returns + ------- + dict[str, object] + Task statistics. + """ api_name = 'SYNO.SDS.Backup.Server.Common.Statistic' info = self.gen_list[api_name] api_path = info['path'] @@ -297,13 +497,29 @@ def vault_task_statistics_get(self, task_id: int) -> dict[str, object]: } return self.request_data(api_name, api_path, req_param) - def vault_target_logs_get(self, - target_id: int, - limit: int = 1000, - offset: int = 0) -> dict[str, object]: - ''' - Get logs for given task. - ''' + def vault_target_logs_get( + self, + target_id: int, + limit: int = 1000, + offset: int = 0 + ) -> dict[str, object]: + """ + Get logs for a given target. + + Parameters + ---------- + target_id : int + Target ID. + limit : int, optional + Maximum number of logs to return (default is 1000). + offset : int, optional + Offset for pagination (default is 0). + + Returns + ------- + dict[str, object] + Logs information. + """ api_name = 'SYNO.SDS.Backup.Server.Common.Log' info = self.gen_list[api_name] api_path = info['path'] From 2fa9ffb5710e858c6452b8fc94b0a4201900fcec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 20:45:29 +0700 Subject: [PATCH 017/126] fix: synology_api/core_certificate.py update docstrings to comply with Numpydoc standards --- synology_api/core_certificate.py | 161 +++++++++++++++++++++++++++++-- 1 file changed, 152 insertions(+), 9 deletions(-) diff --git a/synology_api/core_certificate.py b/synology_api/core_certificate.py index b648dc18..7f52dce4 100644 --- a/synology_api/core_certificate.py +++ b/synology_api/core_certificate.py @@ -1,3 +1,4 @@ +"""Synology DSM Core Certificate API Wrapper.""" from __future__ import annotations from io import BytesIO from typing import Optional @@ -10,6 +11,34 @@ class Certificate(base_api.BaseApi): + """ + Synology DSM Core Certificate API Wrapper. + + This class provides methods to interact with the Synology DSM Core Certificate API, + allowing management of SSL certificates on a Synology NAS. + + Parameters + ---------- + ip_address : str + IP address or hostname of the Synology NAS. + port : str + Port number to connect to. + username : str + Username for authentication. + password : str + Password for authentication. + secure : bool, optional + Use HTTPS if True, HTTP if False (default is False). + cert_verify : bool, optional + Verify SSL certificates (default is False). + dsm_version : int, optional + DSM version (default is 7). + debug : bool, optional + Enable debug output (default is True). + otp_code : Optional[str], optional + One-time password for 2FA (default is None). + """ + def __init__(self, ip_address: str, port: str, @@ -21,6 +50,30 @@ def __init__(self, debug: bool = True, otp_code: Optional[str] = None ) -> None: + """ + Initialize the Certificate API wrapper. + + Parameters + ---------- + ip_address : str + IP address or hostname of the Synology NAS. + port : str + Port number to connect to. + username : str + Username for authentication. + password : str + Password for authentication. + secure : bool, optional + Use HTTPS if True, HTTP if False (default is False). + cert_verify : bool, optional + Verify SSL certificates (default is False). + dsm_version : int, optional + DSM version (default is 7). + debug : bool, optional + Enable debug output (default is True). + otp_code : Optional[str], optional + One-time password for 2FA (default is None). + """ super(Certificate, self).__init__(ip_address, port, username, password, secure, cert_verify, dsm_version, debug, otp_code) self._debug: bool = debug @@ -30,6 +83,23 @@ def _base_certificate_methods(self, cert_id: Optional[str] = None, ids: Optional[str | list[str]] = None ) -> str | dict[str, object]: + """ + Internal method to perform basic certificate operations. + + Parameters + ---------- + method : str + The method to perform ('list', 'set', or 'delete'). + cert_id : Optional[str], optional + Certificate ID for 'set' method (default is None). + ids : Optional[str or list[str]], optional + Certificate IDs for 'delete' method (default is None). + + Returns + ------- + str or dict[str, object] + API response or error message. + """ available_method = ['list', 'set', 'delete'] if method not in available_method: # print error here @@ -55,12 +125,46 @@ def _base_certificate_methods(self, return self.request_data(api_name, api_path, req_param) def list_cert(self) -> dict[str, object]: + """ + List all certificates. + + Returns + ------- + dict[str, object] + List of certificates. + """ return self._base_certificate_methods('list') def set_default_cert(self, cert_id: str) -> dict[str, object]: + """ + Set a certificate as the default. + + Parameters + ---------- + cert_id : str + Certificate ID to set as default. + + Returns + ------- + dict[str, object] + API response. + """ return self._base_certificate_methods('set', cert_id) def delete_certificate(self, ids: str | list[str]) -> dict[str, object]: + """ + Delete one or more certificates. + + Parameters + ---------- + ids : str or list[str] + Certificate ID or list of IDs to delete. + + Returns + ------- + dict[str, object] + API response. + """ if isinstance(ids, str): ids = [ids] return self._base_certificate_methods('delete', ids=ids) @@ -73,6 +177,29 @@ def upload_cert(self, cert_id: Optional[str] = None, desc: Optional[str] = None ) -> tuple[int, dict[str, object]]: + """ + Upload a certificate to the Synology NAS. + + Parameters + ---------- + serv_key : str, optional + Path to the server key file (default is "server.key"). + ser_cert : str, optional + Path to the server certificate file (default is "server.crt"). + ca_cert : Optional[str], optional + Path to the CA certificate file (default is None). + set_as_default : bool, optional + Set as default certificate after upload (default is True). + cert_id : Optional[str], optional + Certificate ID to update (default is None). + desc : Optional[str], optional + Description for the certificate (default is None). + + Returns + ------- + tuple[int, dict[str, object]] + HTTP status code and API response. + """ api_name = 'SYNO.Core.Certificate' info = self.session.app_api_list[api_name] api_path = info['path'] @@ -114,6 +241,21 @@ def set_certificate_for_service(self, cert_id: str, service_name: str = "DSM Desktop Service", ) -> tuple[int, dict[str, object]]: + """ + Set a certificate for a specific DSM service. + + Parameters + ---------- + cert_id : str + Certificate ID to assign. + service_name : str, optional + Name of the service (default is "DSM Desktop Service"). + + Returns + ------- + tuple[int, dict[str, object]] + HTTP status code and API response. + """ api_name = 'SYNO.Core.Certificate.Service' info = self.session.app_api_list[api_name] api_path = info['path'] @@ -188,17 +330,18 @@ def set_certificate_for_service(self, return r.status_code, r.json() def export_cert(self, cert_id: str) -> Optional[BytesIO]: - """Export a certificate from the Synology NAS. + """ + Export a certificate from the Synology NAS. - Parameters - ---------- - cert_id : str - The certificate ID to export. This can be found in the list_cert() method. + Parameters + ---------- + cert_id : str + The certificate ID to export. This can be found in the list_cert() method. - Returns - ------- - Optional[BytesIO] - A BytesIO object containing the certificate archive. + Returns + ------- + Optional[BytesIO] + A BytesIO object containing the certificate archive, or None if export fails. """ api_name = "SYNO.Core.Certificate" From d2f890664d98d09fcb53730cbb00a1101a0766b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 20:49:31 +0700 Subject: [PATCH 018/126] fix: synology_api/core_group.py update docstrings to comply with Numpydoc standards --- synology_api/core_group.py | 911 ++++++++++++++++++------------------- 1 file changed, 447 insertions(+), 464 deletions(-) diff --git a/synology_api/core_group.py b/synology_api/core_group.py index 0a0d13b4..952372fb 100644 --- a/synology_api/core_group.py +++ b/synology_api/core_group.py @@ -1,3 +1,11 @@ +""" +Synology Core Group API wrapper. + +This module provides a Python interface for managing groups on Synology NAS devices, +including group creation, deletion, membership management, quota and permission settings, +and bandwidth control. +""" + import json from typing import Any from . import base_api @@ -5,83 +13,97 @@ class Group(base_api.BaseApi): """ - Core Group API implementation. - - Supported methods: - - Getters: - - Get all groups - - Get group members - - Get group shares permissions - - Get group shares quota - - Get group services speed limits - - - Setters: - - Set group name/description - - Set group share permissions - - Set group share quotas - - Set group service speed limit - - - Actions: - - Create new group - - Delete groups - - Add users to a group - - Remove users from a group + Core Group API implementation for Synology NAS. + + This class provides methods to manage groups, including: + - Retrieving group information, members, permissions, quotas, and speed limits. + - Modifying group name, description, share permissions, quotas, and speed limits. + - Creating and deleting groups. + - Adding and removing users from groups. + + Methods + ------- + get_groups(offset=0, limit=-1, name_only=False) + Retrieve groups information. + get_users(group, in_group=True) + Retrieve users who are members or not members of a group. + get_speed_limits(group) + Retrieve bandwidth control settings for a group. + get_quota(group) + Retrieve quota settings for a group. + get_permissions(group) + Retrieve share permissions for a group. + set_group_info(group, new_name="", new_description="") + Change group name and/or description. + set_share_quota(group, share_quotas) + Set group quota for a given share. + set_share_permissions(group, permissions) + Set group permissions for a given share. + set_speed_limit(group, upload_limit, download_limit, protocol) + Set speed limit for a given share. + add_users(group, users) + Add users to a group. + remove_users(group, users) + Remove users from a group. + create(name, description="") + Create a new group. + delete(groups) + Delete specified groups. """ def get_groups( self, offset: int = 0, limit: int = -1, name_only: bool = False ) -> dict[str, object]: - """Retrieve groups information. - - Parameters - ---------- - offset : int, optional - The offset of the groups to retrieve. Defaults to `0`. - - limit : int, optional - The maximum number of groups to retrieve. Defaults to `-1` (all groups). - - name_only : bool, optional - If `True`, returns only group names. If `False`, returns full group information. Defaults to `False`. - - Returns - ------- - dict[str, object] - A dictionary containing the groups information. - - Examples - -------- - ```json - { - "data": { - "groups": [ - { - "description": "System default admin group", - "gid": 101, - "name": "administrators" - }, - { - "description": "System default group for Web services", - "gid": 1023, - "name": "http" - }, - { - "description": "A test group", - "gid": 65536, - "name": "Test" - }, - { - "description": "System default group", - "gid": 100, - "name": "users" - } - ], - "offset": 0, - "total": 4 - }, - "success": true - } - ``` + """ + Retrieve groups information. + + Parameters + ---------- + offset : int, optional + The offset of the groups to retrieve. Defaults to 0. + limit : int, optional + The maximum number of groups to retrieve. Defaults to -1 (all groups). + name_only : bool, optional + If True, returns only group names. If False, returns full group information. Defaults to False. + + Returns + ------- + dict[str, object] + A dictionary containing the groups information. + + Examples + -------- + ```json + { + "data": { + "groups": [ + { + "description": "System default admin group", + "gid": 101, + "name": "administrators" + }, + { + "description": "System default group for Web services", + "gid": 1023, + "name": "http" + }, + { + "description": "A test group", + "gid": 65536, + "name": "Test" + }, + { + "description": "System default group", + "gid": 100, + "name": "users" + } + ], + "offset": 0, + "total": 4 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Group" @@ -106,53 +128,50 @@ def get_groups( return self.request_data(api_name, api_path, req_param) def get_users(self, group: str, in_group: bool = True) -> dict[str, object]: - """Retrieve users members or not of a group. - - Parameters - ---------- - group : str - The group to list users from. - - in_group : bool, optional - Defaults to `True`. - - If `True`, retrieves users who are members of the specified group. - - If `False`, retrieves users who are not members of the group. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": { - "offset": 0, - "total": 3, - "users": [ - { - "description": "System default user", - "name": "admin", - "uid": 1024 - }, - { - "description": "", - "name": "customAdmin", - "uid": 1026 - }, - { - "description": "", - "name": "test", - "uid": 1032 - } - ] - }, - "success": true - } - ``` + """ + Retrieve users who are members or not members of a group. + + Parameters + ---------- + group : str + The group to list users from. + in_group : bool, optional + If True, retrieves users who are members of the specified group. + If False, retrieves users who are not members of the group. Defaults to True. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "offset": 0, + "total": 3, + "users": [ + { + "description": "System default user", + "name": "admin", + "uid": 1024 + }, + { + "description": "", + "name": "customAdmin", + "uid": 1026 + }, + { + "description": "", + "name": "test", + "uid": 1032 + } + ] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Group.Member" info = self.core_list[api_name] @@ -167,40 +186,42 @@ def get_users(self, group: str, in_group: bool = True) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_speed_limits(self, group: str) -> dict[str, object]: - """Retrieve bandwidth control settings for a given group. - - Parameters - ---------- - group : str - The group to retrieve settings for. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": { - "bandwidths": [ - { - "download_limit_1": 0, - "download_limit_2": 0, - "name": "group_name", - "owner_type": "local_group", - "policy": "notexist", - "protocol": "FTP", - "protocol_ui": "FTP", - "schedule_plan": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", - "upload_limit_1": 0, - "upload_limit_2": 0 - }, - ] - }, - "success": true - } + """ + Retrieve bandwidth control settings for a given group. + + Parameters + ---------- + group : str + The group to retrieve settings for. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "bandwidths": [ + { + "download_limit_1": 0, + "download_limit_2": 0, + "name": "group_name", + "owner_type": "local_group", + "policy": "notexist", + "protocol": "FTP", + "protocol_ui": "FTP", + "schedule_plan": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "upload_limit_1": 0, + "upload_limit_2": 0 + }, + ] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.BandwidthControl" info = self.core_list[api_name] @@ -214,42 +235,43 @@ def get_speed_limits(self, group: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_quota(self, group: str) -> dict[str, object]: - """Retrieve quota settings for a given group. - - Parameters - ---------- - group : str - The group to retrieve quota settings for. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": { - "group_quota": [ - { - "deduped": false, - "quota_status": "v1", - "shares": [ - { - "description": "", - "name": "ActiveBackupforBusiness", - "quota": 1024 - } - ], - "support_share_quota": true, - "volume": "/volume3" - } - ] - }, - "success": true - } - ``` + """ + Retrieve quota settings for a given group. + + Parameters + ---------- + group : str + The group to retrieve quota settings for. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "group_quota": [ + { + "deduped": false, + "quota_status": "v1", + "shares": [ + { + "description": "", + "name": "ActiveBackupforBusiness", + "quota": 1024 + } + ], + "support_share_quota": true, + "volume": "/volume3" + } + ] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Quota" info = self.core_list[api_name] @@ -264,42 +286,43 @@ def get_quota(self, group: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_permissions(self, group: str) -> dict[str, object]: - """Retrieve share permissions for a given group. - - Parameters - ---------- - group : str - The group to list permissions for. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": { - "shares": [ - { - "is_aclmode": true, - "is_custom": false, - "is_deny": true, - "is_mask": false, - "is_readonly": false, - "is_sync_share": false, - "is_unite_permission": false, - "is_writable": false, - "name": "ActiveBackupforBusiness", - "share_path": "/volume3/ActiveBackupforBusiness" - } - ], - "total": 1 - }, - "success": true - } - ``` + """ + Retrieve share permissions for a given group. + + Parameters + ---------- + group : str + The group to list permissions for. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "shares": [ + { + "is_aclmode": true, + "is_custom": false, + "is_deny": true, + "is_mask": false, + "is_readonly": false, + "is_sync_share": false, + "is_unite_permission": false, + "is_writable": false, + "name": "ActiveBackupforBusiness", + "share_path": "/volume3/ActiveBackupforBusiness" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -320,35 +343,34 @@ def get_permissions(self, group: str) -> dict[str, object]: def set_group_info( self, group: str, new_name: str = "", new_description: str = "" ) -> dict[str, object]: - """Change group name and/or description. - - Parameters - ---------- - group : str - The group to set information for. - - new_name : str, optional - The new name of the group. Defaults to current value. - - new_description : str, optional - The new description of the group. Defaults to current value. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": { - "gid": 65536, - "name": "Test_mod" - }, - "success": true - } - ``` + """ + Change group name and/or description. + + Parameters + ---------- + group : str + The group to set information for. + new_name : str, optional + The new name of the group. Defaults to current value. + new_description : str, optional + The new description of the group. Defaults to current value. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "gid": 65536, + "name": "Test_mod" + }, + "success": true + } + ``` """ current_groups_info = self.groups_info() current_group = filter( @@ -377,43 +399,29 @@ def set_group_info( def set_share_quota( self, group: str, share_quotas: list[dict[str, Any]] ) -> dict[str, object]: - """Set group quota for a given share. - - Parameters - ---------- - group : str - The group to set the quota for. - - share_quotas (list[dict[str, Any]]): - The quotas to set for the group. - - Example: - ```python - [ - { - "share": "web", - "quota": 1024, # in MB - }, - { - "share": "photo", - "quota": 5120, # in MB - } - ] - ``` - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": {}, - "success": true - } - ``` + """ + Set group quota for a given share. + + Parameters + ---------- + group : str + The group to set the quota for. + share_quotas : list of dict + The quotas to set for the group. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": {}, + "success": true + } + ``` """ api_name = "SYNO.Core.Quota" info = self.core_list[api_name] @@ -430,46 +438,28 @@ def set_share_quota( def set_share_permissions( self, group: str, permissions: list[dict[str, object]] ) -> dict[str, object]: - """Set group permissions for a given share. - - Parameters - ---------- - group : str - The group to set the permissions for. - - permissions : list[dict[str, object]]: - The permissions to set for the group. - - Example: - ```python - [ - { - "name": "web", - "is_readonly": False, - "is_writable": False, - "is_deny": True - }, - { - "name": "ActiveBackupforBusiness", - "is_readonly": False, - "is_writable": True, - "is_deny": False - } - ] - ``` - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "success": true - } - ``` + """ + Set group permissions for a given share. + + Parameters + ---------- + group : str + The group to set the permissions for. + permissions : list of dict + The permissions to set for the group. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -491,48 +481,40 @@ def set_speed_limit( download_limit: int, protocol: str, ) -> dict[str, object]: - """Set speed limit for a given share. - - Info: Doesn't support **scheduled** speed limits, only on/off. - - Parameters - ---------- - group : str - The group to set the speed limit for. - - upload_limit : int - The maximum upload speed in KB/s. - - download_limit : int - The maximum download speed in KB/s. - - protocol : str - The protocol to set the speed limit for. - - Possible values: - - FileStation - - WebDAV - - FTP - - NetworkBackup (Rsync) - - CloudStation (Synology Drive) - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. + """ + Set speed limit for a given share. + + Parameters + ---------- + group : str + The group to set the speed limit for. + upload_limit : int + The maximum upload speed in KB/s. + download_limit : int + The maximum download speed in KB/s. + protocol : str + The protocol to set the speed limit for. Possible values: + FileStation, WebDAV, FTP, NetworkBackup (Rsync), CloudStation (Synology Drive). + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "results": [ + true + ] + }, + "success": true + } + ``` - Examples - -------- - ```json - { - "data": { - "results": [ - true - ] - }, - "success": true - } - ``` + Note: Doesn't support scheduled speed limits, only on/off. """ settings = [ { @@ -557,29 +539,29 @@ def set_speed_limit( return self.request_data(api_name, api_path, req_param) def add_users(self, group: str, users: list[str]) -> dict[str, object]: - """Add users to a group. - - Parameters - ---------- - group : str - The group to add users to. - - users : list[str] - The users to add to the group. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": {}, - "success": true - } - ``` + """ + Add users to a group. + + Parameters + ---------- + group : str + The group to add users to. + users : list of str + The users to add to the group. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": {}, + "success": true + } + ``` """ api_name = "SYNO.Core.Group.Member" info = self.core_list[api_name] @@ -595,29 +577,29 @@ def add_users(self, group: str, users: list[str]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def remove_users(self, group: str, users: list[str]) -> dict[str, object]: - """Remove users from a group. - - Parameters - ---------- - group : str - The group to remove users from. - - users : list[str] - The users to remove from the group. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": {}, - "success": true - } - ``` + """ + Remove users from a group. + + Parameters + ---------- + group : str + The group to remove users from. + users : list of str + The users to remove from the group. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": {}, + "success": true + } + ``` """ api_name = "SYNO.Core.Group.Member" info = self.core_list[api_name] @@ -633,32 +615,32 @@ def remove_users(self, group: str, users: list[str]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def create(self, name: str, description: str = "") -> dict[str, object]: - """Create group. - - Parameters - ---------- - name : str - Name to assign to the group. - - description : str, optional - Description to assign to the group. Defaults to empty string. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": { - "gid": 65541, - "name": "new_group" - }, - "success": true - } - ``` + """ + Create a new group. + + Parameters + ---------- + name : str + Name to assign to the group. + description : str, optional + Description to assign to the group. Defaults to empty string. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": { + "gid": 65541, + "name": "new_group" + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Group" @@ -674,26 +656,27 @@ def create(self, name: str, description: str = "") -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def delete(self, groups: list[str]) -> dict[str, object]: - """Delete specified groups. - - Parameters - ---------- - groups : list[str] - The groups to delete. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the request. - - Examples - -------- - ```json - { - "data": {}, - "success": true - } - ``` + """ + Delete specified groups. + + Parameters + ---------- + groups : list of str + The groups to delete. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the request. + + Examples + -------- + ```json + { + "data": {}, + "success": true + } + ``` """ api_name = "SYNO.Core.Group" info = self.core_list[api_name] From ac26c551186abb557548ae28ae246a9d482c0eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:02:15 +0700 Subject: [PATCH 019/126] fix: synology_api/core_package.py update docstrings to comply with Numpydoc standards --- synology_api/core_package.py | 1416 ++++++++++++++++++---------------- 1 file changed, 736 insertions(+), 680 deletions(-) diff --git a/synology_api/core_package.py b/synology_api/core_package.py index 2582d7e1..acc2a47f 100644 --- a/synology_api/core_package.py +++ b/synology_api/core_package.py @@ -1,3 +1,10 @@ +""" +Synology Core Package API wrapper. + +This module provides a Python interface for managing packages on Synology NAS devices, +including listing, installing, upgrading, uninstalling, and configuring packages. +""" + import json from typing import List from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor @@ -10,46 +17,90 @@ class Package(base_api.BaseApi): """ - Core Package API implementation. + Core Package API implementation for Synology NAS. + + This class provides methods to manage packages, including: + - Listing installed and installable packages. + - Installing, upgrading, and uninstalling packages. + - Uploading package files. + - Configuring package center settings. + + Methods + ------- + get_package(package_id, additional) + Get information about a package. + list_installed(additional, ignore_hidden) + List installed packages. + list_installable() + List installable packages. + get_package_center_settings() + Get package center settings. + set_package_center_settings(...) + Set package center settings. + get_package_center_infos() + Get package center information. + feasibility_check_install(packages) + Check if installation is possible. + download_package(url, package_id, checksum, filesize) + Start download of a package. + get_dowload_package_status(task_id) + Get current download status of a package. + check_installation_from_download(task_id) + Get info about downloaded package file. + upload_package_file(file_path, verify, progress_bar, additional) + Upload a file for installing a package. + get_default_install_volume() + Get default install volume for packages. + check_installation(...) + Check installation of a package. + upgrade_package(...) + Upgrade an existing package. + install_package(...) + Install a package that is already downloaded. + uninstall_package(package_id) + Uninstall a package. + easy_install(package_id, volume_path, install_dependencies) + Execute an easy installation process of a package. """ def get_package(self, package_id: str, additional: List[str] = []) -> dict: - """Get infos of a package - - Parameters - ---------- - package_id : str - Package ID - additional : List[str], optional - Additional field to retrieves. Defaults to `[]` - All filed known are: - `["status","dsm_apps"]` - - Returns - ------- - dict - Informations about the package - - Examples - -------- - ```json - { - "data": { - "additional": { - "dsm_apps": " com.plexapp.plexmediaserver", - "status": "running", - "status_code": 0, - "status_description": "retrieve from status script", - "status_origin": "running" - }, - "id": "PlexMediaServer", - "name": "Plex Media Server", - "timestamp": 1739228562839, - "version": "1.41.3.9314-72009314" + """ + Get infos of a package. + + Parameters + ---------- + package_id : str + Package ID. + additional : List[str], optional + Additional field to retrieves. Defaults to `[]`. + All filed known are: + `["status","dsm_apps"]`. + + Returns + ------- + dict + Informations about the package. + + Examples + -------- + ```json + { + "data": { + "additional": { + "dsm_apps": " com.plexapp.plexmediaserver", + "status": "running", + "status_code": 0, + "status_description": "retrieve from status script", + "status_origin": "running" }, - "success": true - } - ``` + "id": "PlexMediaServer", + "name": "Plex Media Server", + "timestamp": 1739228562839, + "version": "1.41.3.9314-72009314" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package' info = self.core_list[api_name] @@ -63,45 +114,47 @@ def get_package(self, package_id: str, additional: List[str] = []) -> dict: return self.request_data(api_name, api_path, req_param) def list_installed(self, additional: list = [], ignore_hidden: bool = False) -> dict: - """List installed packages - Parameters - ---------- - additional : list[str], optional - Additional fields to retrieve. Defaults to `[]`. - All fields known are: - `["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url", - "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", - "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages","install_type", - "autoupdate", "silent_upgrade", "installing_progress", "ctl_uninstall", "updated_at", "status", - "url","available_operation"]`. - ignore_hidden : bool - TODO: Write description - - Returns - ------- - dict - List of packages installed on the NAS - - Examples - -------- - ```json - { - "data": { - "packages": [ - { - "additional": { - "install_type": "" - }, - "id": "ActiveBackup-Office365", - "name": "Active Backup for Microsoft 365", - "timestamp": 1738880043640, - "version": "2.5.5-14034" - } - ] - }, - "success": true + """ + List installed packages. + + Parameters + ---------- + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: + `["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url", + "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", + "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages","install_type", + "autoupdate", "silent_upgrade", "installing_progress", "ctl_uninstall", "updated_at", "status", + "url","available_operation"]`. + ignore_hidden : bool + Whether to ignore hidden packages. + + Returns + ------- + dict + List of packages installed on the NAS. + + Examples + -------- + ```json + { + "data": { + "packages": [ + { + "additional": { + "install_type": "" + }, + "id": "ActiveBackup-Office365", + "name": "Active Backup for Microsoft 365", + "timestamp": 1738880043640, + "version": "2.5.5-14034" + } } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package' info = self.core_list[api_name] @@ -116,25 +169,27 @@ def list_installed(self, additional: list = [], ignore_hidden: bool = False) -> return self.request_data(api_name, api_path, req_param) def list_installable(self) -> dict: - """List installable packages - Returns - ------- - dict - List of beta_package, categories and packages available - - Examples - -------- - ```json - { - "data": { - "banners": [], - "beta_packages": [...], - "categories": [...], - "packages": [...] - }, - "success": true - } - ``` + """ + List installable packages. + + Returns + ------- + dict + List of beta_package, categories and packages available. + + Examples + -------- + ```json + { + "data": { + "banners": [], + "beta_packages": [...], + "categories": [...], + "packages": [...] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Server' info = self.core_list[api_name] @@ -149,51 +204,53 @@ def list_installable(self) -> dict: return self.request_data(api_name, api_path, req_param) def get_package_center_settings(self) -> dict: - """Get package center settings - Returns - ------- - dict - List settings of the Package center - - Examples - -------- - ```json - { - "data": { - "autoupdateall": false, - "autoupdateimportant": true, - "default_vol": "/volume1", - "enable_autoupdate": true, - "enable_dsm": true, - "enable_email": false, - "mailset": true, - "trust_level": 0, - "update_channel": true, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 184.72 GB )", - "mount_point": "/volume1", - "size_free": "198336327680", - "size_total": "206158430208", - "vol_desc": "Apps", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.14 GB )", - "mount_point": "/volume2", - "size_free": "2567467421696", - "size_total": "3623234412544", - "vol_desc": "Stockage", - "volume_features": [] - } - ] - }, - "success": true - } - ``` + """ + Get package center settings. + + Returns + ------- + dict + List settings of the Package center. + + Examples + -------- + ```json + { + "data": { + "autoupdateall": false, + "autoupdateimportant": true, + "default_vol": "/volume1", + "enable_autoupdate": true, + "enable_dsm": true, + "enable_email": false, + "mailset": true, + "trust_level": 0, + "update_channel": true, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 184.72 GB )", + "mount_point": "/volume1", + "size_free": "198336327680", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.14 GB )", + "mount_point": "/volume2", + "size_free": "2567467421696", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting' info = self.core_list[api_name] @@ -210,48 +267,44 @@ def set_package_center_settings(self, autoupdateall: bool, autoupdateimportant: bool, default_vol: str, update_channel: str ) -> dict: - """Set settings of the package center - Parameters - ---------- - enable_email : bool - Enable email notification - - enable_dsm : bool - Enable desktop notification - - enable_autoupdate: bool - Update packages automatically - - autoupdateall : bool - Auto update all packages - - autoupdateimportant : bool - Auto update "important" packages - - default_vol : str - Default volume for installation, all your volumes or `"no_default_vol" = Always ask me` - - udpate_channel : str - "stable" => Disable beta packages - "beta" => Enable beta packages - - Returns - ------- - dict - Return some settings - - Examples - -------- - ```json - { - "data": { - "enable_dsm": true, - "enable_email": false, - "update_channel": "stable" - }, - "success": true - } - ``` + """ + Set settings of the package center. + + Parameters + ---------- + enable_email : bool + Enable email notification. + enable_dsm : bool + Enable desktop notification. + enable_autoupdate : bool + Update packages automatically. + autoupdateall : bool + Auto update all packages. + autoupdateimportant : bool + Auto update "important" packages. + default_vol : str + Default volume for installation, all your volumes or `"no_default_vol" = Always ask me`. + update_channel : str + "stable" => Disable beta packages. + "beta" => Enable beta packages. + + Returns + ------- + dict + Return some settings. + + Examples + -------- + ```json + { + "data": { + "enable_dsm": true, + "enable_email": false, + "update_channel": "stable" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting' @@ -272,45 +325,47 @@ def set_package_center_settings(self, return self.request_data(api_name, api_path, req_param) def get_package_center_infos(self) -> dict: - """Get package center informations - Returns - ------- - dict - List of configs - - Examples - -------- - ```json - { - "data": { - "config": { - "auth_key": "------------------------------", - "blBetaChannel": false, - "blOtherServer": false, - "def_void": "", - "ds_build": "72806", - "ds_major": "7", - "ds_minor": "2", - "ds_timezone": "Amsterdam", - "ds_unique": "synology_r1000_723+", - "myPayBaseURL": "https://payment.synology.com", - "myds_id": "7886858", - "serial": "2260TPR7X30E6", - "success": true - }, - "prerelease": { - "agreed": true, - "success": true - }, - "term": { - "agreed_term_version": "0003", - "curr_term_version": "0003", - "success": true - } + """ + Get package center informations. + + Returns + ------- + dict + List of configs. + + Examples + -------- + ```json + { + "data": { + "config": { + "auth_key": "------------------------------", + "blBetaChannel": false, + "blOtherServer": false, + "def_void": "", + "ds_build": "72806", + "ds_major": "7", + "ds_minor": "2", + "ds_timezone": "Amsterdam", + "ds_unique": "synology_r1000_723+", + "myPayBaseURL": "https://payment.synology.com", + "myds_id": "7886858", + "serial": "2260TPR7X30E6", + "success": true }, - "success": true - } - ``` + "prerelease": { + "agreed": true, + "success": true + }, + "term": { + "agreed_term_version": "0003", + "curr_term_version": "0003", + "success": true + } + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Info' info = self.core_list[api_name] @@ -322,28 +377,29 @@ def get_package_center_infos(self) -> dict: return self.request_data(api_name, api_path, req_param) def feasibility_check_install(self, packages: List[str]) -> dict: - """Check if installation is possible - - Parameters - ---------- - packages : List[str] - List of package IDs to check for feasibility - - Returns - ------- - dict - _description_ - - Examples - -------- - ```json - { - "data": { - "template": "data" - }, - "success": true - } - ``` + """ + Check if installation is possible. + + Parameters + ---------- + packages : List[str] + List of package IDs to check for feasibility. + + Returns + ------- + dict + Feasibility check result. + + Examples + -------- + ```json + { + "data": { + "template": "data" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting' info = self.core_list[api_name] @@ -358,35 +414,36 @@ def feasibility_check_install(self, packages: List[str]) -> dict: return self.request_data(api_name, api_path, req_param) def download_package(self, url: str, package_id: str, checksum: str, filesize: str) -> dict: - """Start download of the package, return a taskId for check status - - Parameters - ---------- - url : str - Url that can be retrieve from package info using `get_installable` function, in the `link` field - package_id : str - Package ID that can be retrieve from package info using `get_installable` function, in the `id` field - checksum : str - Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field - filesize : str - Filesize that can be retrieve from package info using `get_installable` function, in the `size` field - - Returns - ------- - dict - Retreive first progress of the download and the taskid used to check download status with `get_dowload_package_status` function - - Examples - -------- - ```json - { - "data": { - "progress": 1.0000000000000001e-05, - "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer" - }, - "success": true - } - ``` + """ + Start download of the package, return a taskId for check status. + + Parameters + ---------- + url : str + Url that can be retrieve from package info using `get_installable` function, in the `link` field. + package_id : str + Package ID that can be retrieve from package info using `get_installable` function, in the `id` field. + checksum : str + Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field. + filesize : str + Filesize that can be retrieve from package info using `get_installable` function, in the `size` field. + + Returns + ------- + dict + Retrieve first progress of the download and the taskid used to check download status with `get_dowload_package_status` function. + + Examples + -------- + ```json + { + "data": { + "progress": 1.0000000000000001e-05, + "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] @@ -405,40 +462,41 @@ def download_package(self, url: str, package_id: str, checksum: str, filesize: s return self.request_data(api_name, api_path, req_param) def get_dowload_package_status(self, task_id: str) -> dict: - """Get current download status of the package - - Parameters - ---------- - task_id : str - task ID retrieve from response of `download_package` function - - Returns - ------- - dict - Retrieve informations about the download, important info is the `progress` field - - Examples - -------- - ```json - { - "data": { - "beta": false, - "blqinst": false, - "finished": false, - "id": "DhcpServer", - "installing": false, - "name": "DhcpServer", - "pid": 27844, - "progress": 1.0000000000000001e-05, - "remote_link": "https://global.synologydownload.com/download/Package/spk/DhcpServer/1.0.2-0046/DhcpServer-x86_64-1.0.2-0046.spk", - "size": "1378697", - "success": true, - "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer", - "tmp_folder": "/volume1/@tmp/synopkg/download.esnnkb" - }, - "success": true - } - ``` + """ + Get current download status of the package. + + Parameters + ---------- + task_id : str + Task ID retrieved from response of `download_package` function. + + Returns + ------- + dict + Retrieve informations about the download, important info is the `progress` field. + + Examples + -------- + ```json + { + "data": { + "beta": false, + "blqinst": false, + "finished": false, + "id": "DhcpServer", + "installing": false, + "name": "DhcpServer", + "pid": 27844, + "progress": 1.0000000000000001e-05, + "remote_link": "https://global.synologydownload.com/download/Package/spk/DhcpServer/1.0.2-0046/DhcpServer-x86_64-1.0.2-0046.spk", + "size": "1378697", + "success": true, + "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer", + "tmp_folder": "/volume1/@tmp/synopkg/download.esnnkb" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] @@ -451,43 +509,44 @@ def get_dowload_package_status(self, task_id: str) -> dict: return self.request_data(api_name, api_path, req_param) def check_installation_from_download(self, task_id: str) -> dict: - """Get info about downloaded package file, response field is used for `check_installation` and `install_package` function - - Parameters - ---------- - task_id : str - task ID retrieve from response of `download_package` function - - Returns - ------- - dict - Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function - - Examples - -------- - ```json - { - "data": { - "description": "DHCP Server turns your DiskStation into a DHCP server within LAN to assign dynamic IP addresses and manage DHCP clients.", - "distributor": "", - "dsm_apps": "SYNO.SDS.DHCP.Instance", - "filename": "/volume1/@tmp/synopkg/download.esnnkb/@SYNOPKG_DOWNLOAD_DhcpServer", - "id": "DhcpServer", - "install_on_cold_storage": false, - "install_reboot": false, - "install_type": "system", - "maintainer": "Synology Inc.", - "name": "DHCP Server", - "startable": true, - "status": "non_installed", - "status_code": 255, - "status_description": "failed to locate given package", - "status_origin": "non_installed", - "version": "1.0.2-0046" - }, - "success": true - } - ``` + """ + Get info about downloaded package file, response field is used for `check_installation` and `install_package` function. + + Parameters + ---------- + task_id : str + Task ID retrieved from response of `download_package` function. + + Returns + ------- + dict + Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function. + + Examples + -------- + ```json + { + "data": { + "description": "DHCP Server turns your DiskStation into a DHCP server within LAN to assign dynamic IP addresses and manage DHCP clients.", + "distributor": "", + "dsm_apps": "SYNO.SDS.DHCP.Instance", + "filename": "/volume1/@tmp/synopkg/download.esnnkb/@SYNOPKG_DOWNLOAD_DhcpServer", + "id": "DhcpServer", + "install_on_cold_storage": false, + "install_reboot": false, + "install_type": "system", + "maintainer": "Synology Inc.", + "name": "DHCP Server", + "startable": true, + "status": "non_installed", + "status_code": 255, + "status_description": "failed to locate given package", + "status_origin": "non_installed", + "version": "1.0.2-0046" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation.Download' info = self.core_list[api_name] @@ -500,57 +559,58 @@ def check_installation_from_download(self, task_id: str) -> dict: return self.request_data(api_name, api_path, req_param) def upload_package_file(self, file_path: str, verify: bool = False, progress_bar: bool = True, additional: list = []) -> dict: - """Upload a file for install a package - - Parameters - ---------- - file_path : str - File path - verify : bool, optional - Use https. Defaults to `False` - progress_bar : bool, optional - Enable progress bar in the terminal. Defaults to `True` - additional : list, optional - Additional field to retrieves. Defaults to `[]` - All fields know are: - `["description","maintainer","distributor","startable","dsm_apps","status","install_reboot", - "install_type","install_on_cold_storage","break_pkgs","replace_pkgs"]`. - - Returns - ------- - dict - Informations about the uploaded file for installation - - Examples - -------- - ```json - { - "data": { - "additional": { - "break_pkgs": null, - "description": "Plex organizes all of your personal media so you can easily access and enjoy it.", - "distributor": "", - "dsm_apps": " com.plexapp.plexmediaserver", - "install_on_cold_storage": false, - "install_reboot": false, - "install_type": "", - "maintainer": "Plex Inc", - "replace_pkgs": { "Plex Media Server": "" }, - "startable": true, - "status": "running", - "status_code": 0, - "status_description": "retrieve from status script", - "status_origin": "running" - }, - "codesign_error": 4532, - "id": "PlexMediaServer", - "name": "Plex Media Server", - "task_id": "@SYNOPKG_UPLOAD_17392283048566DD3", - "version": "1.41.3.9314-72009314" + """ + Upload a file for install a package. + + Parameters + ---------- + file_path : str + File path. + verify : bool, optional + Use https. Defaults to `False`. + progress_bar : bool, optional + Enable progress bar in the terminal. Defaults to `True`. + additional : list, optional + Additional field to retrieves. Defaults to `[]`. + All fields know are: + `["description","maintainer","distributor","startable","dsm_apps","status","install_reboot", + "install_type","install_on_cold_storage","break_pkgs","replace_pkgs"]`. + + Returns + ------- + dict + Informations about the uploaded file for installation. + + Examples + -------- + ```json + { + "data": { + "additional": { + "break_pkgs": null, + "description": "Plex organizes all of your personal media so you can easily access and enjoy it.", + "distributor": "", + "dsm_apps": " com.plexapp.plexmediaserver", + "install_on_cold_storage": false, + "install_reboot": false, + "install_type": "", + "maintainer": "Plex Inc", + "replace_pkgs": { "Plex Media Server": "" }, + "startable": true, + "status": "running", + "status_code": 0, + "status_description": "retrieve from status script", + "status_origin": "running" }, - "success": true - } - ``` + "codesign_error": 4532, + "id": "PlexMediaServer", + "name": "Plex Media Server", + "task_id": "@SYNOPKG_UPLOAD_17392283048566DD3", + "version": "1.41.3.9314-72009314" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] @@ -604,23 +664,24 @@ def upload_package_file(self, file_path: str, verify: bool = False, progress_bar return r.json() def get_default_install_volume(self) -> dict: - """Get default install volume for package - - Returns - ------- - dict - Return default volume, if default volume is set to `Always ask me` it return error 4501 - - Examples - -------- - ```json - { - "data": { - "default_vol": "/volume1" - }, - "success": true - } - ``` + """ + Get default install volume for package. + + Returns + ------- + dict + Return default volume, if default volume is set to `Always ask me` it return error 4501. + + Examples + -------- + ```json + { + "data": { + "default_vol": "/volume1" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting.Volume' info = self.core_list[api_name] @@ -636,58 +697,59 @@ def check_installation(self, package_id: str, install_type: str = "", install_on_cold_storage: bool = False, blCheckDep: bool = False, replacepkgs: dict = {} ) -> dict: - """Check installation of the package on the default volume - - Parameters - ---------- - package_id : str - Id of the package to install - install_type : str, optionnal - Installation type, Defaults to `""`. TODO: Add description and possible types - install_on_cold_storage : bool, optional - Defaults to `False`. TODO: Add description - blCheckDep : bool, optional - Defaults to `False`. TODO: Add description - replacepkgs : dict, optional - Defaults to `{}`. TODO: Add description - - Returns - ------- - dict - List of usefull informations about volumes - - Examples - -------- - ```json - { - "data": { - "is_occupied": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 184.52 GB )", - "mount_point": "/volume1", - "size_free": "198126022656", - "size_total": "206158430208", - "vol_desc": "vol1", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.16 GB )", - "mount_point": "/volume2", - "size_free": "2567484923904", - "size_total": "3623234412544", - "vol_desc": "vol2", - "volume_features": [] - } - ], - "volume_path": "/volume1" - }, - "success": true, - } - ``` + """ + Check installation of the package on the default volume. + + Parameters + ---------- + package_id : str + Id of the package to install. + install_type : str, optionnal + Installation type, Defaults to `""`. TODO: Add description and possible types. + install_on_cold_storage : bool, optional + Defaults to `False`. TODO: Add description. + blCheckDep : bool, optional + Defaults to `False`. TODO: Add description. + replacepkgs : dict, optional + Defaults to `{}`. TODO: Add description. + + Returns + ------- + dict + List of usefull informations about volumes. + + Examples + -------- + ```json + { + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 184.52 GB )", + "mount_point": "/volume1", + "size_free": "198126022656", + "size_total": "206158430208", + "vol_desc": "vol1", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.16 GB )", + "mount_point": "/volume2", + "size_free": "2567484923904", + "size_total": "3623234412544", + "vol_desc": "vol2", + "volume_features": [] + } + ], + "volume_path": "/volume1" + }, + "success": true, + } + ``` """ api_name = 'SYNO.Core.Package.Installation' @@ -707,50 +769,39 @@ def check_installation(self, return self.request_data(api_name, api_path, req_param) def upgrade_package(self, task_id: str, check_codesign: bool = False, force: bool = False, installrunpackage: bool = True, extra_values: dict = {}) -> dict: - """Upgrade an existing package - - Parameters - ---------- - task_id : str - Task id of the download or the upload file - check_codesign : bool, optional - Check signature of the source code of the package (is it a Synology one). Defaults to `False` - force : bool, optional - Force installation. Defaults to `False` - installrunpackage : bool, optional - Run package after installation. Defaults to `True` - extra_values : dict, optional - Extra values due to some package installation. Defaults to `{}` - All known extra values are: - - Surveillance station - ```json - { - "chkSVS_Alias": true, - "strSVS_Alias": "cam", - "chkSVS_HTTP": true, - "strSVS_HTTP": "9900", - "chkSVS_HTTPS": true, - "strSVS_HTTPS": "9901" - } - ``` - - Returns - ------- - dict - Message and some info about installation - - Examples - -------- - ```json - { - "data": { - "message": "message", - "packageName": "Plex Media Server", - "worker_message": [] - }, - "success": true, - } - ``` + """ + Upgrade an existing package. + + Parameters + ---------- + task_id : str + Task id of the download or the upload file. + check_codesign : bool, optional + Check signature of the source code of the package (is it a Synology one). Defaults to `False`. + force : bool, optional + Force installation. Defaults to `False`. + installrunpackage : bool, optional + Run package after installation. Defaults to `True`. + extra_values : dict, optional + Extra values due to some package installation. Defaults to `{}`. + + Returns + ------- + dict + Message and some info about installation. + + Examples + -------- + ```json + { + "data": { + "message": "message", + "packageName": "Plex Media Server", + "worker_message": [] + }, + "success": true, + } + ``` """ api_name = 'SYNO.Core.Package.Installation' @@ -769,94 +820,84 @@ def upgrade_package(self, task_id: str, check_codesign: bool = False, force: boo return self.request_data(api_name, api_path, req_param) def install_package(self, package_id: str, volume_path: str, file_path: str, check_codesign: bool = True, force: bool = True, installrunpackage: bool = True, extra_values: dict = {}) -> dict: - """Install a package that is already downloaded - - Parameters - ---------- - package_id : str - Id of the package to install - volume_path : str - Volume path of the installation, can get from `check_installation` function - file_path : str - File path of the installation, can get from `check_installation_from_download` function - check_codesign : bool, optional - Check signature of the source code of the package (is it a Synology one). Defaults to `False` - force : bool, optional - Force installation. Defaults to `False` - installrunpackage : bool, optional - Run package after installation. Defaults to `True` - extra_values : dict, optional - Extra values due to some package installation. Defaults to `{}` - All known extra values are: - - Surveillance station - ```json + """ + Install a package that is already downloaded. + + Parameters + ---------- + package_id : str + Id of the package to install. + volume_path : str + Volume path of the installation, can get from `check_installation` function. + file_path : str + File path of the installation, can get from `check_installation_from_download` function. + check_codesign : bool, optional + Check signature of the source code of the package (is it a Synology one). Defaults to `False`. + force : bool, optional + Force installation. Defaults to `False`. + installrunpackage : bool, optional + Run package after installation. Defaults to `True`. + extra_values : dict, optional + Extra values due to some package installation. Defaults to `{}`. + + Returns + ------- + dict + Message and some info about installation. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ { - "chkSVS_Alias": true, - "strSVS_Alias": "cam", - "chkSVS_HTTP": true, - "strSVS_HTTP": "9900", - "chkSVS_HTTPS": true, - "strSVS_HTTPS": "9901" - } - ``` - Returns - ------- - dict - Message and some info about installation - - Examples - -------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.Core.Package.Installation", - "data": { - "is_occupied": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 185.09 GB )", - "mount_point": "/volume1", - "size_free": "198739943424", - "size_total": "206158430208", - "vol_desc": "Apps", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.17 GB )", - "mount_point": "/volume2", - "size_free": "2567495630848", - "size_total": "3623234412544", - "vol_desc": "Stockage", - "volume_features": [] - } - ], - "volume_path": "/volume1" - }, - "method": "check", - "success": true, - "version": 1 + "api": "SYNO.Core.Package.Installation", + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 185.09 GB )", + "mount_point": "/volume1", + "size_free": "198739943424", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.17 GB )", + "mount_point": "/volume2", + "size_free": "2567495630848", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ], + "volume_path": "/volume1" }, - { - "api": "SYNO.Core.Package.Installation", - "data": { - "packageName": "Text Editor", - "worker_message": [] - }, - "method": "install", - "success": true, - "version": 1 - } - ] - }, - "success": true - } - ``` + "method": "check", + "success": true, + "version": 1 + }, + { + "api": "SYNO.Core.Package.Installation", + "data": { + "packageName": "Text Editor", + "worker_message": [] + }, + "method": "install", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` """ compound = [ { @@ -886,29 +927,30 @@ def install_package(self, package_id: str, volume_path: str, file_path: str, che return self.batch_request(compound=compound) def uninstall_package(self, package_id: str) -> dict: - """Uninstall a package - - Parameters - ---------- - package_id : str - Id of the package to uninstall - - Returns - ------- - dict - Possible message to the user - - Examples - -------- - ```json - { - "data": { - "message": "", - "worker_message": [] - }, - "success": true - } - ``` + """ + Uninstall a package. + + Parameters + ---------- + package_id : str + Id of the package to uninstall. + + Returns + ------- + dict + Possible message to the user. + + Examples + -------- + ```json + { + "data": { + "message": "", + "worker_message": [] + }, + "success": true + } + ``` """ if not self._is_package_already_installed(package_id=package_id): @@ -928,6 +970,19 @@ def uninstall_package(self, package_id: str) -> dict: return self.request_data(api_name, api_path, req_param) def _is_package_already_installed(self, package_id: str) -> bool: + """ + Check if a package is already installed. + + Parameters + ---------- + package_id : str + The ID of the package to check. + + Returns + ------- + bool + True if the package is installed, False otherwise. + """ response: dict = self.list_installed() data: dict = response.get("data") installed_packages = data.get("packages") @@ -936,75 +991,76 @@ def _is_package_already_installed(self, package_id: str) -> bool: return package_infos != None def easy_install(self, package_id: str, volume_path: str, install_dependencies: bool = True) -> dict: - """Execute an easy installation process of the package - - Parameters - ---------- - package_id : str - Package ID to install - volume_path : str - Volume path where you want to install the package - install_dependencies : bool, optional - If you want to install dependencies. Defaults to True - - Returns - ------- - dict[str, object] - Information about installation, same as install_package function - - Examples - -------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.Core.Package.Installation", - "data": { - "is_occupied": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 185.11 GB )", - "mount_point": "/volume1", - "size_free": "198759485440", - "size_total": "206158430208", - "vol_desc": "Apps", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.17 GB )", - "mount_point": "/volume2", - "size_free": "2567495565312", - "size_total": "3623234412544", - "vol_desc": "Stockage", - "volume_features": [] - } - ], - "volume_path": "/volume1" - }, - "method": "check", - "success": true, - "version": 1 + """ + Execute an easy installation process of the package. + + Parameters + ---------- + package_id : str + Package ID to install. + volume_path : str + Volume path where you want to install the package. + install_dependencies : bool, optional + If you want to install dependencies. Defaults to True. + + Returns + ------- + dict[str, object] + Information about installation, same as install_package function. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Package.Installation", + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 185.11 GB )", + "mount_point": "/volume1", + "size_free": "198759485440", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.17 GB )", + "mount_point": "/volume2", + "size_free": "2567495565312", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ], + "volume_path": "/volume1" }, - { - "api": "SYNO.Core.Package.Installation", - "data": { - "packageName": "Text Editor", - "worker_message": [] - }, - "method": "install", - "success": true, - "version": 1 - } - ] - }, - "success": true - } - ``` + "method": "check", + "success": true, + "version": 1 + }, + { + "api": "SYNO.Core.Package.Installation", + "data": { + "packageName": "Text Editor", + "worker_message": [] + }, + "method": "install", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` """ api_name = 'hotfix' # fix for docs_parser.py issue From ae4de874469ef0444721cf1ac86e2692fb29a3d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:04:13 +0700 Subject: [PATCH 020/126] fix: synology_api/core_share.py update docstrings to comply with Numpydoc standards --- synology_api/core_share.py | 985 ++++++++++++++++++------------------- 1 file changed, 476 insertions(+), 509 deletions(-) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index 74ca8a16..1be08625 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -1,50 +1,51 @@ +""" +Synology Core Share API wrapper. + +This module provides a Python interface for managing shared folders, permissions, and encryption +on Synology NAS devices. +""" + import json from typing import List, Any from . import base_api class Share(base_api.BaseApi): - """ - Core Share API implementation. - """ + """Core Share API implementation.""" def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_compress: bool = False, enable_share_cow: bool = False, enc_passwd: str = "", encryption: bool = False) -> dict: - """Validate set of parameter for a new / modified shared folder - Parameters - ---------- - name : str - Share name. - - vol_path : str - Volume path. - - desc : str, optional - Share description. Defaults to `""`. - - enable_share_compress : bool, optional - Enable share compress. Defaults to `False`. - - enable_share_cow : bool, optional - Enable share cow. Defaults to `False`. - - enc_passwd : str, optional - Encrypted password. Defaults to `""`. - - encryption : bool, optional - Enable encryption. Defaults to `False`. - - Returns - ------- - dict - Success. - - Examples - -------- - ```json - { - "success": true, - } - ``` + """ + Validate set of parameter for a new / modified shared folder. + + Parameters + ---------- + name : str + Share name. + vol_path : str + Volume path. + desc : str, optional + Share description. Defaults to `""`. + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + enc_passwd : str, optional + Encrypted password. Defaults to `""`. + encryption : bool, optional + Enable encryption. Defaults to `False`. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true, + } + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -77,46 +78,47 @@ def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_co return self.request_data(api_name, api_path, req_param, method="post") def list_folders(self, share_type: str = "all", additional: list = []) -> dict: - """List all folders informations - Parameters - ---------- - share_type : str, optional - Share type. Defaults to `all`. - - additional : list[str], optional - Additional fields to retrieve. Defaults to `[]`. - All fields known are: `[ - "hidden","encryption","is_aclmode","unite_permission","is_support_acl","is_sync_share","is_force_readonly","force_readonly_reason", - "recyclebin","is_share_moving","is_cluster_share","is_exfat_share","is_c2_share","is_cold_storage_share","is_missing_share", - "is_offline_share","support_snapshot","share_quota","enable_share_compress","enable_share_cow","enable_share_tiering", - "load_worm_attr","include_cold_storage_share","is_cold_storage_share","include_missing_share","is_missing_share", - "include_offline_share","is_offline_share","include_worm_share" - ]`. - - Returns - ------- - dict - A dictionary containing the shared folders information. - - Examples - -------- - ```json - { - "data": { - "shares": [ - { - "desc": "", - "is_usb_share": false, - "name": "test_shared_folder", - "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", - "vol_path": "/volume1" - } - ], - "total": 1 - }, - "success": true - } - ``` + """ + List all folders informations. + + Parameters + ---------- + share_type : str, optional + Share type. Defaults to `all`. + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `[ + "hidden","encryption","is_aclmode","unite_permission","is_support_acl","is_sync_share","is_force_readonly","force_readonly_reason", + "recyclebin","is_share_moving","is_cluster_share","is_exfat_share","is_c2_share","is_cold_storage_share","is_missing_share", + "is_offline_share","support_snapshot","share_quota","enable_share_compress","enable_share_cow","enable_share_tiering", + "load_worm_attr","include_cold_storage_share","is_cold_storage_share","include_missing_share","is_missing_share", + "include_offline_share","is_offline_share","include_worm_share" + ]`. + + Returns + ------- + dict + A dictionary containing the shared folders information. + + Examples + -------- + ```json + { + "data": { + "shares": [ + { + "desc": "", + "is_usb_share": false, + "name": "test_shared_folder", + "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", + "vol_path": "/volume1" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -131,39 +133,40 @@ def list_folders(self, share_type: str = "all", additional: list = []) -> dict: return self.request_data(api_name, api_path, req_param) def get_folder(self, name: str, additional: list = []) -> dict: - """Get a folder by name - Parameters - ---------- - name : str - Share name. - - additional : list, optional - Additional fields to retrieve. Defaults to `[]`. - All fields known are: `["disable_list","disable_modify","disable_download","unite_permission","is_aclmode"]`. - - Returns - ------- - dict - A dictionary containing the shared folder information. - - Examples - -------- - ```json - { - "data": { - "desc": "", - "disable_download": false, - "disable_list": false, - "disable_modify": false, - "is_aclmode": true, - "is_usb_share": false, - "name": "test_shared_folder", - "unite_permission": false, - "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", - "vol_path": "/volume1" - }, - "success": true, - ``` + """ + Get a folder by name. + + Parameters + ---------- + name : str + Share name. + additional : list, optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `["disable_list","disable_modify","disable_download","unite_permission","is_aclmode"]`. + + Returns + ------- + dict + A dictionary containing the shared folder information. + + Examples + -------- + ```json + { + "data": { + "desc": "", + "disable_download": false, + "disable_list": false, + "disable_modify": false, + "is_aclmode": true, + "is_usb_share": false, + "name": "test_shared_folder", + "unite_permission": false, + "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", + "vol_path": "/volume1" + }, + "success": true, + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -183,56 +186,48 @@ def create_folder(self, hide_unreadable: bool = False, enable_share_cow: bool = False, enable_share_compress: bool = False, share_quota: int = 0, name_org: str = "", ) -> dict: - """Create a new shared folder - Parameters - ---------- - name : str - Share name. - - vol_path : str - Volume path. - - desc : str, optional - Share description. Defaults to `""`. - - hidden : bool, optional - Hide share. Defaults to `False`. - - enable_recycle_bin : bool, optional - Enable recycle bin. Defaults to `True`. - - recycle_bin_admin_only : bool, optional - Recycle bin admin only. Defaults to `True`. - - hide_unreadable : bool, optional - Hide unreadable. Defaults to `False`. - - enable_share_cow : bool, optional - Enable share cow. Defaults to `False`. - - enable_share_compress : bool, optional - Enable share compress. Defaults to `False`. - - share_quota : int, optional - Share quota. Defaults to `0`. - - name_org : str, optional - Defaults to `""`. - - Returns - ------- - dict - Name of the created shared folder - - Examples - -------- - ```json - { - "data": { - "name": "test_shared_folder" - }, - "success": true, - ``` + """ + Create a new shared folder. + + Parameters + ---------- + name : str + Share name. + vol_path : str + Volume path. + desc : str, optional + Share description. Defaults to `""`. + hidden : bool, optional + Hide share. Defaults to `False`. + enable_recycle_bin : bool, optional + Enable recycle bin. Defaults to `True`. + recycle_bin_admin_only : bool, optional + Recycle bin admin only. Defaults to `True`. + hide_unreadable : bool, optional + Hide unreadable. Defaults to `False`. + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + share_quota : int, optional + Share quota. Defaults to `0`. + name_org : str, optional + Defaults to `""`. + + Returns + ------- + dict + Name of the created shared folder. + + Examples + -------- + ```json + { + "data": { + "name": "test_shared_folder" + }, + "success": true, + ``` """ api_name = "SYNO.Core.Share" @@ -268,25 +263,26 @@ def create_folder(self, return self.request_data(api_name, api_path, req_param, method="post") def delete_folders(self, name: List[str]) -> dict: - """Delete folder(s) by name(s) - - Parameters - ---------- - name : List[str] - Share names. - - Returns - ------- - dict - Success. - - Examples - -------- - ```json - { - "success": true - } - ``` + """ + Delete folder(s) by name(s). + + Parameters + ---------- + name : List[str] + Share names. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -305,56 +301,48 @@ def clone(self, hide_unreadable: bool = False, enable_share_cow: bool = False, enable_share_compress: bool = False, share_quota: int = 0 ) -> dict: - """Clone existing shared folder. - Parameters - ---------- - name : str - New shared folder name. - - name_org : str - Original shared folder name. - - vol_path : str - Volume path. - - desc : str, optional - Shared folder description. Defaults to `""`. - - hidden : bool, optional - Hide shared folder. Defaults to `False`. - - enable_recycle_bin : bool, optional - Enable recycle bin. Defaults to `True`. - - recycle_bin_admin_only : bool, optional - Recycle bin admin only. Defaults to `True`. - - hide_unreadable : bool, optional - Hide unreadable. Defaults to `False`. - - enable_share_cow : bool, optional - Enable share cow. Defaults to `False`. - - enable_share_compress : bool, optional - Enable share compress. Defaults to `False`. - - share_quota : int, optional - Share quota. Defaults to `0`. - - Returns - ------- - dict - Name of the created shared folder - - Examples - -------- - ```json - { - "data": { - "name": "test_shared_folder" - }, - "success": true, - ``` + """ + Clone existing shared folder. + + Parameters + ---------- + name : str + New shared folder name. + name_org : str + Original shared folder name. + vol_path : str + Volume path. + desc : str, optional + Shared folder description. Defaults to `""`. + hidden : bool, optional + Hide shared folder. Defaults to `False`. + enable_recycle_bin : bool, optional + Enable recycle bin. Defaults to `True`. + recycle_bin_admin_only : bool, optional + Recycle bin admin only. Defaults to `True`. + hide_unreadable : bool, optional + Hide unreadable. Defaults to `False`. + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + share_quota : int, optional + Share quota. Defaults to `0`. + + Returns + ------- + dict + Name of the created shared folder. + + Examples + -------- + ```json + { + "data": { + "name": "test_shared_folder" + }, + "success": true, + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -392,65 +380,59 @@ def clone(self, class SharePermission(base_api.BaseApi): - """ - Core Share Permission API implementation. - """ + """Core Share Permission API implementation.""" def get_folder_permission_by_name(self, name: str, permission_substr: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, user_group_type: str = "local_user" ) -> dict: - """Retrieve share permissions for a given folder filtered by permission name (sub string) - Parameters - ---------- - name : str - The folder name to list permissions for. - - permission_substr : str - The substring to search for in the permissions. - - offset : int, optional - The offset to start at. Defaults to `0`. - - limit : int, optional - The maximum number of results to return. Defaults to `50`. - - is_unite_permission : bool, optional - Whether to return unified permissions. Defaults to `False`. - - with_inherit : bool, optional - Whether to include inherited permissions. Defaults to `False`. - - user_group_type : str, optional - The type of user group to list permissions for. Defaults to `"local_user"`. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - Returns - ------- - dict - List of permission(s) on the folder - - Examples - -------- - ```json - { - "data": { - "items": [ - { - "inherit": "-", - "is_admin": false, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "guest" - } - ], - "total": 1 - }, - "success": true - } - ``` + """ + Retrieve share permissions for a given folder filtered by permission name (sub string). + + Parameters + ---------- + name : str + The folder name to list permissions for. + permission_substr : str + The substring to search for in the permissions. + offset : int, optional + The offset to start at. Defaults to `0`. + limit : int, optional + The maximum number of results to return. Defaults to `50`. + is_unite_permission : bool, optional + Whether to return unified permissions. Defaults to `False`. + with_inherit : bool, optional + Whether to include inherited permissions. Defaults to `False`. + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + List of permission(s) on the folder. + + Examples + -------- + ```json + { + "data": { + "items": [ + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" @@ -474,81 +456,78 @@ def get_folder_permissions(self, name: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, user_group_type: str = "local_user" ) -> dict: - """Retrieve share permissions for a given folder. - Parameters - ---------- - name : str - The folder name to list permissions for. - - offset : int, optional - The offset to start at. Defaults to `0`. - - limit : int, optional - The maximum number of results to return. Defaults to `50`. - - is_unite_permission : bool, optional - Whether to return unified permissions. Defaults to `False`. - - with_inherit : bool, optional - Whether to include inherited permissions. Defaults to `False`. - - user_group_type : str, optional - The type of user group to list permissions for. Defaults to `"local_user"`. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - Returns - ------- - dict - All permissions on the folder - - Examples - -------- - ```json - { - "data": { - "items": [ - { - "inherit": "rw", - "is_admin": true, - "is_custom": false, - "is_deny": true, - "is_readonly": false, - "is_writable": false, - "name": "admin" - }, - { - "inherit": "-", - "is_admin": false, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "guest" - }, - { - "inherit": "rw", - "is_admin": true, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": true, - "name": "test_api" - }, - { - "inherit": "-", - "is_admin": false, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "test_test" - } - ], - "total": 5 - }, - "success": true - } - ``` + """ + Retrieve share permissions for a given folder. + + Parameters + ---------- + name : str + The folder name to list permissions for. + offset : int, optional + The offset to start at. Defaults to `0`. + limit : int, optional + The maximum number of results to return. Defaults to `50`. + is_unite_permission : bool, optional + Whether to return unified permissions. Defaults to `False`. + with_inherit : bool, optional + Whether to include inherited permissions. Defaults to `False`. + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + All permissions on the folder. + + Examples + -------- + ```json + { + "data": { + "items": [ + { + "inherit": "rw", + "is_admin": true, + "is_custom": false, + "is_deny": true, + "is_readonly": false, + "is_writable": false, + "name": "admin" + }, + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + }, + { + "inherit": "rw", + "is_admin": true, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": true, + "name": "test_api" + }, + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "test_test" + } + ], + "total": 5 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -567,43 +546,31 @@ def get_folder_permissions(self, return self.request_data(api_name, api_path, req_param, method="get") def set_folder_permissions(self, name: str, user_group_type: str, permissions: List[dict[str, object]]) -> dict: - """Set folder permissions for a given folder. - Parameters - ---------- - name : str - The folder name to set permissions for. - - user_group_type : str - The type of user group to set permissions for. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - permissions : dict - The permissions to set for the folder. - Example: - ```json - [ - { - "name":"guest", - "is_readonly":false, - "is_writable":true, - "is_deny":false, - "is_custom":false - } - ] - ``` - - Returns - ------- - dict - Success - - Examples - -------- - ```json - { - "success": true - } - ``` + """ + Set folder permissions for a given folder. + + Parameters + ---------- + name : str + The folder name to set permissions for. + user_group_type : str + The type of user group to set permissions for. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + permissions : dict + The permissions to set for the folder. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -618,41 +585,43 @@ def set_folder_permissions(self, name: str, user_group_type: str, permissions: L return self.request_data(api_name, api_path, req_param, method="get") def get_local_group_permissions(self, group: str) -> dict: - """Retrieve share permissions for a given group. - Parameters - ---------- - group : str - The group to list permissions for. - - Returns - ------- - dict - Permissions of a group on Shared folders - - Examples - -------- - ```json - { - "data": { - "shares": [ - { - "is_aclmode": true, - "is_custom": false, - "is_deny": true, - "is_mask": false, - "is_readonly": false, - "is_sync_share": false, - "is_unite_permission": false, - "is_writable": false, - "name": "ActiveBackupforBusiness", - "share_path": "/volume3/ActiveBackupforBusiness" - } - ], - "total": 1 - }, - "success": true - } - ``` + """ + Retrieve share permissions for a given group. + + Parameters + ---------- + group : str + The group to list permissions for. + + Returns + ------- + dict + Permissions of a group on Shared folders. + + Examples + -------- + ```json + { + "data": { + "shares": [ + { + "is_aclmode": true, + "is_custom": false, + "is_deny": true, + "is_mask": false, + "is_readonly": false, + "is_sync_share": false, + "is_unite_permission": false, + "is_writable": false, + "name": "ActiveBackupforBusiness", + "share_path": "/volume3/ActiveBackupforBusiness" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -673,44 +642,28 @@ def get_local_group_permissions(self, group: str) -> dict: def set_local_group_permissions( self, group: str, permissions: list[dict[str, Any]] ) -> dict: - """Set group permissions for a given share. - Parameters - ---------- - group : str - The group to set the permissions for. - - permissions : list[dict[str, Any]] - The permissions to set for the group. - Example: - ``` - [ - { - "name": "web", - "is_readonly": False, - "is_writable": False, - "is_deny": True - }, - { - "name": "ActiveBackupforBusiness", - "is_readonly": False, - "is_writable": True, - "is_deny": False - } - ] - ``` - - Returns - ------- - dict - Success - - Examples - -------- - ```json - { - "success": true - } - ``` + """ + Set group permissions for a given share. + + Parameters + ---------- + group : str + The group to set the permissions for. + permissions : list[dict[str, Any]] + The permissions to set for the group. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -727,12 +680,16 @@ def set_local_group_permissions( class KeyManagerStore(base_api.BaseApi): - """ - Core Share KeyManager Store API implementation. - """ + """Core Share KeyManager Store API implementation.""" def init(self) -> dict: - """Initialize KeyManagerStore API. + """ + Initialize KeyManagerStore API. + + Returns + ------- + dict + Not implemented yet. """ raise NotImplementedError( @@ -761,6 +718,14 @@ def init(self) -> dict: return self.request_data(api_name, api_path, req_param, method="post") def verify(self) -> dict: + """ + Not implemented yet. + + Returns + ------- + dict + Not implemented yet. + """ raise NotImplementedError("This method is not implemented yet.") @@ -786,22 +751,24 @@ def verify(self) -> dict: return self.request_data(api_name, api_path, req_param, method="post") def explore(self) -> dict: - """Explore KeyManagerStore API. Get list of existing stores - Returns - ------- - dict - List of stores existing on the NAS - - Examples - -------- - ```json - { - "data": { - "stores": [] - }, - "success": true - } - ``` + """ + Explore KeyManagerStore API. Get list of existing stores. + + Returns + ------- + dict + List of stores existing on the NAS. + + Examples + -------- + ```json + { + "data": { + "stores": [] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.KeyManager.Store" version = self.core_list[api_name]["minVersion"] @@ -815,27 +782,27 @@ def explore(self) -> dict: class KeyManagerAutoKey(base_api.BaseApi): - """ - Core Share KeyManager AutoKey API implementation. - """ + """Core Share KeyManager AutoKey API implementation.""" def list(self) -> dict: - """List KeyManagerStore API. - Returns - ------- - dict - List of keys in the manager - - Examples - -------- - ```json - { - "data": { - "keys": [] - }, - "success": true - } - ``` + """ + List KeyManagerStore API. + + Returns + ------- + dict + List of keys in the manager. + + Examples + -------- + ```json + { + "data": { + "keys": [] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.KeyManager.AutoKey" version = self.core_list[api_name]["minVersion"] From c00af0a4f818c4d727136fe6e9591252a8ee53a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:11:32 +0700 Subject: [PATCH 021/126] feat: update setup.cfg to include RT04 in numpydoc validation checks Some words start with lower character like eSATA --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 2070cac7..efa19967 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [tool:numpydoc_validation] ; to ignore some check add them after for example: checks = all,GL02, GL08 -checks = all,SA01,ES01,EX01 +checks = all,SA01,ES01,EX01,RT04 exclude = \.undocumented_method$,\.__repr__$ From 2f2000d08b82a0d5c651c149734a50bafdf5da54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:11:37 +0700 Subject: [PATCH 022/126] fix: synology_api/core_sys_info.py update docstrings to comply with Numpydoc standards --- synology_api/core_sys_info.py | 1065 ++++++++++++++++++++++++++++++++- 1 file changed, 1037 insertions(+), 28 deletions(-) diff --git a/synology_api/core_sys_info.py b/synology_api/core_sys_info.py index 61029a55..c5b4954e 100644 --- a/synology_api/core_sys_info.py +++ b/synology_api/core_sys_info.py @@ -1,3 +1,10 @@ +""" +Synology Core System Information API wrapper. + +This module provides a Python interface for retrieving and managing system information +on Synology NAS devices, including network, hardware, service, and package status. +""" + from __future__ import annotations from typing import Optional, List from . import base_api @@ -5,8 +12,22 @@ class SysInfo(base_api.BaseApi): + """ + Core System Information API implementation for Synology NAS. + + This class provides methods to retrieve and manage system, network, hardware, + service, and package information from a Synology NAS. + """ def fileserv_smb(self) -> dict[str, object] | str: + """ + Get SMB file service status. + + Returns + ------- + dict[str, object] or str + SMB file service status. + """ api_name = 'SYNO.Core.FileServ.SMB' info = self.core_list[api_name] api_path = info['path'] @@ -15,6 +36,14 @@ def fileserv_smb(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def fileserv_afp(self) -> dict[str, object] | str: + """ + Get AFP file service status. + + Returns + ------- + dict[str, object] or str + AFP file service status. + """ api_name = 'SYNO.Core.FileServ.AFP' info = self.core_list[api_name] api_path = info['path'] @@ -23,6 +52,14 @@ def fileserv_afp(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def fileserv_nfs(self) -> dict[str, object] | str: + """ + Get NFS file service status. + + Returns + ------- + dict[str, object] or str + NFS file service status. + """ api_name = 'SYNO.Core.FileServ.NFS' info = self.core_list[api_name] api_path = info['path'] @@ -31,6 +68,14 @@ def fileserv_nfs(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def fileserv_ftp(self) -> dict[str, object] | str: + """ + Get FTP file service status. + + Returns + ------- + dict[str, object] or str + FTP file service status. + """ api_name = 'SYNO.Core.FileServ.FTP' info = self.core_list[api_name] api_path = info['path'] @@ -39,6 +84,14 @@ def fileserv_ftp(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def fileserv_sftp(self) -> dict[str, object] | str: + """ + Get SFTP file service status. + + Returns + ------- + dict[str, object] or str + SFTP file service status. + """ api_name = 'SYNO.Core.FileServ.FTP.SFTP' info = self.core_list[api_name] api_path = info['path'] @@ -47,6 +100,14 @@ def fileserv_sftp(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_backup_info(self) -> dict[str, object] | str: + """ + Get network backup service information. + + Returns + ------- + dict[str, object] or str + Network backup service information. + """ api_name = 'SYNO.Backup.Service.NetworkBackup' info = self.gen_list[api_name] api_path = info['path'] @@ -55,6 +116,14 @@ def network_backup_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def bandwidth_control_protocol(self) -> dict[str, object] | str: + """ + Get bandwidth control protocol information. + + Returns + ------- + dict[str, object] or str + Bandwidth control protocol information. + """ api_name = 'SYNO.Core.BandwidthControl.Protocol' info = self.core_list[api_name] api_path = info['path'] @@ -64,6 +133,14 @@ def bandwidth_control_protocol(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def shared_folders_info(self) -> dict[str, object] | str: + """ + Get shared folders information. + + Returns + ------- + dict[str, object] or str + Shared folders information. + """ api_name = 'SYNO.Core.Share' info = self.core_list[api_name] api_path = info['path'] @@ -72,6 +149,14 @@ def shared_folders_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def services_status(self) -> dict[str, object] | str: + """ + Get status of core services. + + Returns + ------- + dict[str, object] or str + Status of core services. + """ api_name = 'SYNO.Core.Service' info = self.core_list[api_name] api_path = info['path'] @@ -80,6 +165,14 @@ def services_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def services_discovery(self) -> dict[str, object] | str: + """ + Get service discovery information. + + Returns + ------- + dict[str, object] or str + Service discovery information. + """ api_name = 'SYNO.Core.FileServ.ServiceDiscovery' info = self.core_list[api_name] api_path = info['path'] @@ -88,6 +181,14 @@ def services_discovery(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def file_transfer_status(self) -> dict[str, object] | str: + """ + Get file transfer status. + + Returns + ------- + dict[str, object] or str + File transfer status. + """ api_name = 'SYNO.Core.SyslogClient.FileTransfer' info = self.core_list[api_name] api_path = info['path'] @@ -96,6 +197,14 @@ def file_transfer_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_status(self) -> dict[str, object] | str: + """ + Get network status. + + Returns + ------- + dict[str, object] or str + Network status. + """ api_name = 'SYNO.Core.Network' info = self.core_list[api_name] api_path = info['path'] @@ -104,6 +213,14 @@ def network_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def web_status(self) -> dict[str, object] | str: + """ + Get DSM web status. + + Returns + ------- + dict[str, object] or str + DSM web status. + """ api_name = 'SYNO.Core.Web.DSM' info = self.core_list[api_name] api_path = info['path'] @@ -112,6 +229,14 @@ def web_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def current_connection(self) -> dict[str, object] | str: + """ + Get current connection information. + + Returns + ------- + dict[str, object] or str + Current connection information. + """ api_name = 'SYNO.Core.CurrentConnection' info = self.core_list[api_name] api_path = info['path'] @@ -120,6 +245,14 @@ def current_connection(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def bandwidth_control_status(self) -> dict[str, object] | str: + """ + Get bandwidth control status. + + Returns + ------- + dict[str, object] or str + Bandwidth control status. + """ api_name = 'SYNO.Core.BandwidthControl.Status' info = self.core_list[api_name] api_path = info['path'] @@ -128,6 +261,14 @@ def bandwidth_control_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def sys_status(self) -> dict[str, object] | str: + """ + Get system status. + + Returns + ------- + dict[str, object] or str + System status. + """ api_name = 'SYNO.Core.System.Status' info = self.core_list[api_name] api_path = info['path'] @@ -136,6 +277,14 @@ def sys_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def latest_logs(self) -> dict[str, object] | str: + """ + Get latest system logs. + + Returns + ------- + dict[str, object] or str + Latest system logs. + """ api_name = 'SYNO.Core.SyslogClient.Status' info = self.core_list[api_name] api_path = info['path'] @@ -144,6 +293,14 @@ def latest_logs(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def client_notify_settings_status(self) -> dict[str, object] | str: + """ + Get client notification settings status. + + Returns + ------- + dict[str, object] or str + Client notification settings status. + """ api_name = 'SYNO.Core.SyslogClient.Setting.Notify' info = self.core_list[api_name] api_path = info['path'] @@ -152,6 +309,14 @@ def client_notify_settings_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_security_scan_info(self) -> dict[str, object] | str: + """ + Get security scan configuration. + + Returns + ------- + dict[str, object] or str + Security scan configuration. + """ api_name = 'SYNO.Core.SecurityScan.Conf' info = self.core_list[api_name] api_path = info['path'] @@ -160,6 +325,14 @@ def get_security_scan_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_security_scan_rules(self) -> dict[str, object] | str: + """ + Get security scan rules. + + Returns + ------- + dict[str, object] or str + Security scan rules. + """ api_name = 'SYNO.Core.SecurityScan.Status' info = self.core_list[api_name] api_path = info['path'] @@ -169,6 +342,14 @@ def get_security_scan_rules(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_security_scan_status(self) -> dict[str, object] | str: + """ + Get security scan status. + + Returns + ------- + dict[str, object] or str + Security scan status. + """ api_name = 'SYNO.Core.SecurityScan.Status' info = self.core_list[api_name] api_path = info['path'] @@ -177,6 +358,14 @@ def get_security_scan_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_user_list(self) -> dict[str, object] | str: + """ + Get user list. + + Returns + ------- + dict[str, object] or str + User list. + """ api_name = 'SYNO.Core.User' info = self.core_list[api_name] api_path = info['path'] @@ -187,6 +376,14 @@ def get_user_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def quickconnect_info(self) -> dict[str, object] | str: + """ + Get QuickConnect configuration. + + Returns + ------- + dict[str, object] or str + QuickConnect configuration. + """ api_name = 'SYNO.Core.QuickConnect' info = self.core_list[api_name] api_path = info['path'] @@ -196,6 +393,14 @@ def quickconnect_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def quickconnect_permissions(self) -> dict[str, object] | str: + """ + Get QuickConnect permissions. + + Returns + ------- + dict[str, object] or str + QuickConnect permissions. + """ api_name = 'SYNO.Core.QuickConnect.Permission' info = self.core_list[api_name] api_path = info['path'] @@ -204,6 +409,14 @@ def quickconnect_permissions(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_topology(self) -> dict[str, object] | str: + """ + Get network topology. + + Returns + ------- + dict[str, object] or str + Network topology. + """ api_name = 'SYNO.Core.Network.Router.Topology' info = self.core_list[api_name] api_path = info['path'] @@ -212,6 +425,14 @@ def network_topology(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_wifi_client(self) -> dict[str, object] | str: + """ + Get WiFi client information. + + Returns + ------- + dict[str, object] or str + WiFi client information. + """ api_name = 'SYNO.Core.Network.Wifi.Client' info = self.core_list[api_name] api_path = info['path'] @@ -220,6 +441,14 @@ def network_wifi_client(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_bond(self) -> dict[str, object] | str: + """ + Get network bond information. + + Returns + ------- + dict[str, object] or str + Network bond information. + """ api_name = 'SYNO.Core.Network.Bond' info = self.core_list[api_name] api_path = info['path'] @@ -228,6 +457,14 @@ def network_bond(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_bridge(self) -> dict[str, object] | str: + """ + Get network bridge information. + + Returns + ------- + dict[str, object] or str + Network bridge information. + """ api_name = 'SYNO.Core.Network.Bridge' info = self.core_list[api_name] api_path = info['path'] @@ -236,6 +473,14 @@ def network_bridge(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_ethernet(self) -> dict[str, object] | str: + """ + Get network ethernet information. + + Returns + ------- + dict[str, object] or str + Network ethernet information. + """ api_name = 'SYNO.Core.Network.Ethernet' info = self.core_list[api_name] api_path = info['path'] @@ -244,6 +489,14 @@ def network_ethernet(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_local_bridge(self) -> dict[str, object] | str: + """ + Get local network bridge information. + + Returns + ------- + dict[str, object] or str + Local network bridge information. + """ api_name = 'SYNO.Core.Network.LocalBridge' info = self.core_list[api_name] api_path = info['path'] @@ -252,6 +505,14 @@ def network_local_bridge(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_usb_modem(self) -> dict[str, object] | str: + """ + Get USB modem information. + + Returns + ------- + dict[str, object] or str + USB modem information. + """ api_name = 'SYNO.Core.Network.USBModem' info = self.core_list[api_name] api_path = info['path'] @@ -260,6 +521,14 @@ def network_usb_modem(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_pppoe(self) -> dict[str, object] | str: + """ + Get PPPoE information. + + Returns + ------- + dict[str, object] or str + PPPoE information. + """ api_name = 'SYNO.Core.Network.PPPoE' info = self.core_list[api_name] api_path = info['path'] @@ -268,6 +537,14 @@ def network_pppoe(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_ipv6tunnel(self) -> dict[str, object] | str: + """ + Get IPv6 tunnel information. + + Returns + ------- + dict[str, object] or str + IPv6 tunnel information. + """ api_name = 'SYNO.Core.Network.IPv6Tunnel' info = self.core_list[api_name] api_path = info['path'] @@ -276,6 +553,14 @@ def network_ipv6tunnel(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_vpn_pptp(self) -> dict[str, object] | str: + """ + Get VPN PPTP information. + + Returns + ------- + dict[str, object] or str + VPN PPTP information. + """ api_name = 'SYNO.Core.Network.VPN.PPTP' info = self.core_list[api_name] api_path = info['path'] @@ -284,6 +569,14 @@ def network_vpn_pptp(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_openvpn(self) -> dict[str, object] | str: + """ + Get OpenVPN information. + + Returns + ------- + dict[str, object] or str + OpenVPN information. + """ api_name = 'SYNO.Core.Network.VPN.OpenVPN' info = self.core_list[api_name] api_path = info['path'] @@ -293,6 +586,14 @@ def network_openvpn(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_vpn_l2tp(self) -> dict[str, object] | str: + """ + Get VPN L2TP information. + + Returns + ------- + dict[str, object] or str + VPN L2TP information. + """ api_name = 'SYNO.Core.Network.VPN.L2TP' info = self.core_list[api_name] api_path = info['path'] @@ -301,6 +602,14 @@ def network_vpn_l2tp(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def domain_schedule(self) -> dict[str, object] | str: + """ + Get domain schedule. + + Returns + ------- + dict[str, object] or str + Domain schedule. + """ api_name = 'SYNO.Core.Directory.Domain.Schedule' info = self.core_list[api_name] api_path = info['path'] @@ -309,6 +618,14 @@ def domain_schedule(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def client_ldap(self) -> dict[str, object] | str: + """ + Get LDAP client information. + + Returns + ------- + dict[str, object] or str + LDAP client information. + """ api_name = 'SYNO.Core.Directory.LDAP' info = self.core_list[api_name] api_path = info['path'] @@ -317,6 +634,14 @@ def client_ldap(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def client_sso(self) -> dict[str, object] | str: + """ + Get SSO client information. + + Returns + ------- + dict[str, object] or str + SSO client information. + """ api_name = 'SYNO.Core.Directory.SSO' info = self.core_list[api_name] api_path = info['path'] @@ -325,6 +650,14 @@ def client_sso(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def sys_upgrade_check(self) -> dict[str, object] | str: + """ + Check for system upgrades. + + Returns + ------- + dict[str, object] or str + System upgrade check result. + """ api_name = 'SYNO.Core.Upgrade.Server' info = self.core_list[api_name] api_path = info['path'] @@ -333,6 +666,14 @@ def sys_upgrade_check(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def sys_upgrade_download(self) -> dict[str, object] | str: + """ + Get system upgrade download progress. + + Returns + ------- + dict[str, object] or str + System upgrade download progress. + """ api_name = 'SYNO.Core.Upgrade.Server.Download' info = self.core_list[api_name] api_path = info['path'] @@ -341,6 +682,14 @@ def sys_upgrade_download(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def sys_upgrade_setting(self) -> dict[str, object] | str: + """ + Get system upgrade settings. + + Returns + ------- + dict[str, object] or str + System upgrade settings. + """ api_name = 'SYNO.Core.Upgrade.Setting' info = self.core_list[api_name] api_path = info['path'] @@ -349,6 +698,14 @@ def sys_upgrade_setting(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def notification_sms_conf(self) -> dict[str, object] | str: + """ + Get SMS notification configuration. + + Returns + ------- + dict[str, object] or str + SMS notification configuration. + """ api_name = 'SYNO.Core.Notification.SMS.Conf' info = self.core_list[api_name] api_path = info['path'] @@ -357,6 +714,14 @@ def notification_sms_conf(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def notification_mail_conf(self) -> dict[str, object] | str: + """ + Get mail notification configuration. + + Returns + ------- + dict[str, object] or str + Mail notification configuration. + """ api_name = 'SYNO.Core.Notification.Mail.Conf' info = self.core_list[api_name] api_path = info['path'] @@ -365,6 +730,14 @@ def notification_mail_conf(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def notification_push_mail(self) -> dict[str, object] | str: + """ + Get push mail notification configuration. + + Returns + ------- + dict[str, object] or str + Push mail notification configuration. + """ api_name = 'SYNO.Core.Notification.Push.Mail' info = self.core_list[api_name] api_path = info['path'] @@ -373,6 +746,14 @@ def notification_push_mail(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def notification_push_conf(self) -> dict[str, object] | str: + """ + Get push notification configuration. + + Returns + ------- + dict[str, object] or str + Push notification configuration. + """ api_name = 'SYNO.Core.Notification.Push.Conf' info = self.core_list[api_name] api_path = info['path'] @@ -381,6 +762,14 @@ def notification_push_conf(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def hardware_beep_control(self) -> dict[str, object] | str: + """ + Get hardware beep control status. + + Returns + ------- + dict[str, object] or str + Hardware beep control status. + """ api_name = 'SYNO.Core.Hardware.BeepControl' info = self.core_list[api_name] api_path = info['path'] @@ -389,6 +778,14 @@ def hardware_beep_control(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def hardware_fan_speed(self) -> dict[str, object] | str: + """ + Get hardware fan speed. + + Returns + ------- + dict[str, object] or str + Hardware fan speed. + """ api_name = 'SYNO.Core.Hardware.FanSpeed' info = self.core_list[api_name] api_path = info['path'] @@ -398,6 +795,19 @@ def hardware_fan_speed(self) -> dict[str, object] | str: # coolfan , fullfan def set_fan_speed(self, fan_speed: str = 'quietfan') -> dict[str, object] | str: + """ + Set hardware fan speed. + + Parameters + ---------- + fan_speed : str, optional + Fan speed mode (e.g., 'quietfan', 'coolfan', 'fullfan'). Defaults to 'quietfan'. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.Hardware.FanSpeed' info = self.core_list[api_name] api_path = info['path'] @@ -407,6 +817,19 @@ def set_fan_speed(self, fan_speed: str = 'quietfan') -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def enable_zram(self, enable_zram: bool = True) -> dict[str, object] | str: + """ + Enable or disable ZRAM. + + Parameters + ---------- + enable_zram : bool, optional + Enable ZRAM if True, disable if False. Defaults to True. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.Hardware.ZRAM' info = self.core_list[api_name] api_path = info['path'] @@ -415,10 +838,26 @@ def enable_zram(self, enable_zram: bool = True) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) - def enable_power_recovery(self, - restart_auto_after_issue: bool = True, - wake_on_lan: bool = False - ) -> dict[str, object] | str: + def enable_power_recovery( + self, + restart_auto_after_issue: bool = True, + wake_on_lan: bool = False + ) -> dict[str, object] | str: + """ + Enable power recovery options. + + Parameters + ---------- + restart_auto_after_issue : bool, optional + Restart automatically after issue. Defaults to True. + wake_on_lan : bool, optional + Enable Wake-on-LAN. Defaults to False. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.Hardware.PowerRecovery' info = self.core_list[api_name] api_path = info['path'] @@ -427,12 +866,32 @@ def enable_power_recovery(self, return self.request_data(api_name, api_path, req_param) - def enable_beep_control(self, - fan_fail: Optional[bool] = None, - volume_crash: Optional[bool] = None, - poweron_beep: Optional[bool] = None, - poweroff_beep: Optional[bool] = None - ) -> dict[str, object] | str: + def enable_beep_control( + self, + fan_fail: Optional[bool] = None, + volume_crash: Optional[bool] = None, + poweron_beep: Optional[bool] = None, + poweroff_beep: Optional[bool] = None + ) -> dict[str, object] | str: + """ + Enable or disable beep control options. + + Parameters + ---------- + fan_fail : bool, optional + Enable beep on fan failure. + volume_crash : bool, optional + Enable beep on volume crash. + poweron_beep : bool, optional + Enable beep on power on. + poweroff_beep : bool, optional + Enable beep on power off. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.Hardware.BeepControl' info = self.core_list[api_name] api_path = info['path'] @@ -443,6 +902,19 @@ def enable_beep_control(self, return self.request_data(api_name, api_path, req_param) def set_led_control(self, led_brightness: int = 2) -> dict[str, object] | str: + """ + Set LED brightness. + + Parameters + ---------- + led_brightness : int, optional + LED brightness level. Defaults to 2. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.Led.Brightness' info = self.core_list[api_name] api_path = info['path'] @@ -452,6 +924,21 @@ def set_led_control(self, led_brightness: int = 2) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def set_hibernation(self, internal_hd_idletime: int = 0, usb_idletime: int = 0) -> dict[str, object] | str: + """ + Set hibernation times. + + Parameters + ---------- + internal_hd_idletime : int, optional + Idle time for internal hard drives. Defaults to 0. + usb_idletime : int, optional + Idle time for USB devices. Defaults to 0. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.Hardware.Hibernation' info = self.core_list[api_name] api_path = info['path'] @@ -460,13 +947,35 @@ def set_hibernation(self, internal_hd_idletime: int = 0, usb_idletime: int = 0) return self.request_data(api_name, api_path, req_param) - def enable_external_ups(self, - enable: bool = False, - mode: str = 'SLAVE', - delay_time: int = 1, - snmp_auth_key_dirty: bool = False, - snmp_privacy_key_dirty: bool = False - ) -> dict[str, object] | str: + def enable_external_ups( + self, + enable: bool = False, + mode: str = 'SLAVE', + delay_time: int = 1, + snmp_auth_key_dirty: bool = False, + snmp_privacy_key_dirty: bool = False + ) -> dict[str, object] | str: + """ + Enable or configure external UPS. + + Parameters + ---------- + enable : bool, optional + Enable external UPS. Defaults to False. + mode : str, optional + UPS mode. Defaults to 'SLAVE'. + delay_time : int, optional + Delay time. Defaults to 1. + snmp_auth_key_dirty : bool, optional + SNMP auth key dirty flag. Defaults to False. + snmp_privacy_key_dirty : bool, optional + SNMP privacy key dirty flag. Defaults to False. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.ExternalDevice.UPS' info = self.core_list[api_name] api_path = info['path'] @@ -477,6 +986,14 @@ def enable_external_ups(self, return self.request_data(api_name, api_path, req_param) def get_system_info(self) -> dict[str, object] | str: + """ + Get system information. + + Returns + ------- + dict[str, object] or str + System information. + """ api_name = 'SYNO.Core.System' info = self.core_list[api_name] api_path = info['path'] @@ -485,6 +1002,14 @@ def get_system_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_cpu_temp(self) -> str: + """ + Get CPU temperature. + + Returns + ------- + str + CPU temperature. + """ api_name = 'SYNO.Core.System' info = self.core_list[api_name] api_path = info['path'] @@ -493,6 +1018,14 @@ def get_cpu_temp(self) -> str: return self.request_data(api_name, api_path, req_param)['data']['sys_temp'] def get_all_system_utilization(self) -> str: + """ + Get all system utilization statistics. + + Returns + ------- + str + System utilization statistics. + """ api_name = 'SYNO.Core.System.Utilization' info = self.core_list[api_name] api_path = info['path'] @@ -501,6 +1034,14 @@ def get_all_system_utilization(self) -> str: return self.request_data(api_name, api_path, req_param)['data'] def get_cpu_utilization(self) -> str: + """ + Get CPU utilization statistics. + + Returns + ------- + str + CPU utilization statistics. + """ api_name = 'SYNO.Core.System.Utilization' info = self.core_list[api_name] api_path = info['path'] @@ -509,6 +1050,14 @@ def get_cpu_utilization(self) -> str: return self.request_data(api_name, api_path, req_param)['data']['cpu'] def get_disk_utilization(self) -> str: + """ + Get disk utilization statistics. + + Returns + ------- + str + Disk utilization statistics. + """ api_name = 'SYNO.Core.System.Utilization' info = self.core_list[api_name] api_path = info['path'] @@ -517,6 +1066,14 @@ def get_disk_utilization(self) -> str: return self.request_data(api_name, api_path, req_param)['data']['disk'] def get_memory_utilization(self) -> str: + """ + Get memory utilization statistics. + + Returns + ------- + str + Memory utilization statistics. + """ api_name = 'SYNO.Core.System.Utilization' info = self.core_list[api_name] api_path = info['path'] @@ -525,6 +1082,19 @@ def get_memory_utilization(self) -> str: return self.request_data(api_name, api_path, req_param)['data']['memory'] def shutdown(self, version: str = None) -> dict[str, object] | str: + """ + Shutdown the system. + + Parameters + ---------- + version : str, optional + API version to use. Defaults to None. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.System' info = self.core_list[api_name] api_path = info['path'] @@ -534,6 +1104,14 @@ def shutdown(self, version: str = None) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def reboot(self) -> dict[str, object] | str: + """ + Reboot the system. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.Core.System' info = self.core_list[api_name] api_path = info['path'] @@ -542,6 +1120,14 @@ def reboot(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def dsm_info(self) -> dict[str, object] | str: + """ + Get DSM information. + + Returns + ------- + dict[str, object] or str + DSM information. + """ api_name = 'SYNO.DSM.Info' info = self.gen_list[api_name] api_path = info['path'] @@ -550,6 +1136,14 @@ def dsm_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_network_info(self) -> dict[str, object] | str: + """ + Get network information. + + Returns + ------- + dict[str, object] or str + Network information. + """ api_name = 'SYNO.Core.System' info = self.core_list[api_name] api_path = info['path'] @@ -559,6 +1153,14 @@ def get_network_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_volume_info(self) -> dict[str, object] | str: + """ + Get volume information. + + Returns + ------- + dict[str, object] or str + Volume information. + """ api_name = 'SYNO.Core.System' info = self.core_list[api_name] api_path = info['path'] @@ -568,6 +1170,14 @@ def get_volume_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def hardware_hibernation(self) -> dict[str, object] | str: + """ + Get hardware hibernation status. + + Returns + ------- + dict[str, object] or str + Hardware hibernation status. + """ api_name = 'SYNO.Core.Hardware.Hibernation' info = self.core_list[api_name] api_path = info['path'] @@ -576,6 +1186,14 @@ def hardware_hibernation(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def hardware_ups(self) -> dict[str, object] | str: + """ + Get hardware UPS status. + + Returns + ------- + dict[str, object] or str + Hardware UPS status. + """ api_name = 'SYNO.Core.ExternalDevice.UPS' info = self.core_list[api_name] api_path = info['path'] @@ -584,6 +1202,14 @@ def hardware_ups(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def terminal_info(self) -> dict[str, object] | str: + """ + Get terminal information. + + Returns + ------- + dict[str, object] or str + Terminal information. + """ api_name = 'SYNO.Core.Terminal' info = self.core_list[api_name] api_path = info['path'] @@ -592,6 +1218,14 @@ def terminal_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def snmp_info(self) -> dict[str, object] | str: + """ + Get SNMP information. + + Returns + ------- + dict[str, object] or str + SNMP information. + """ api_name = 'SYNO.Core.SNMP' info = self.core_list[api_name] api_path = info['path'] @@ -600,6 +1234,14 @@ def snmp_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def process(self) -> dict[str, object] | str: + """ + Get system process information. + + Returns + ------- + dict[str, object] or str + System process information. + """ api_name = 'SYNO.Core.System.Process' info = self.core_list[api_name] api_path = info['path'] @@ -608,6 +1250,14 @@ def process(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def storage(self) -> dict[str, object] | str: + """ + Get storage information. + + Returns + ------- + dict[str, object] or str + Storage information. + """ api_name = 'SYNO.Storage.CGI.Storage' info = self.gen_list[api_name] api_path = info['path'] @@ -616,6 +1266,14 @@ def storage(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def external_device_storage_usb(self) -> dict[str, object] | str: + """ + Get USB storage device information. + + Returns + ------- + dict[str, object] or str + USB storage device information. + """ api_name = 'SYNO.Core.ExternalDevice.Storage.USB' info = self.gen_list[api_name] api_path = info['path'] @@ -625,6 +1283,14 @@ def external_device_storage_usb(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def external_device_storage_esata(self) -> dict[str, object] | str: + """ + Get eSATA storage device information. + + Returns + ------- + dict[str, object] or str + eSATA storage device information. + """ api_name = 'SYNO.Core.ExternalDevice.Storage.eSATA' info = self.gen_list[api_name] api_path = info['path'] @@ -634,6 +1300,14 @@ def external_device_storage_esata(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def file_index_resource(self) -> dict[str, object] | str: + """ + Get file indexing status. + + Returns + ------- + dict[str, object] or str + File indexing status. + """ api_name = 'SYNO.Finder.FileIndexing.Status' info = self.gen_list[api_name] api_path = info['path'] @@ -642,6 +1316,14 @@ def file_index_resource(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def cms_info(self) -> dict[str, object] | str: + """ + Get CMS information. + + Returns + ------- + dict[str, object] or str + CMS information. + """ api_name = 'SYNO.Core.CMS.Info' info = self.gen_list[api_name] api_path = info['path'] @@ -649,16 +1331,15 @@ def cms_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) - # TODO {'error': {'code': 2502}, 'success': False} - '''def service_port_info(self) -> dict[str, object] | str: - api_name = 'SYNO.Core.Service.PortInfo' - info = self.gen_list[api_name] - api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'load', 'target': ['port_forward']} - - return self.request_data(api_name, api_path, req_param)''' - def port_forwarding_rules(self) -> dict[str, object] | str: + """ + Get port forwarding rules. + + Returns + ------- + dict[str, object] or str + Port forwarding rules. + """ api_name = 'SYNO.Core.PortForwarding.Rules' info = self.gen_list[api_name] api_path = info['path'] @@ -667,6 +1348,14 @@ def port_forwarding_rules(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def port_forwarding_router_conf(self) -> dict[str, object] | str: + """ + Get port forwarding router configuration. + + Returns + ------- + dict[str, object] or str + Port forwarding router configuration. + """ api_name = 'SYNO.Core.PortForwarding.RouterConf' info = self.gen_list[api_name] api_path = info['path'] @@ -675,6 +1364,14 @@ def port_forwarding_router_conf(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def disk_list(self) -> dict[str, object] | str: + """ + Get disk list. + + Returns + ------- + dict[str, object] or str + Disk list. + """ api_name = 'SYNO.Core.Polling.Data' info = self.gen_list[api_name] api_path = info['path'] @@ -683,6 +1380,14 @@ def disk_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def ddns_provider_info(self) -> dict[str, object] | str: + """ + Get DDNS provider information. + + Returns + ------- + dict[str, object] or str + DDNS provider information. + """ api_name = 'SYNO.Core.DDNS.Provider' info = self.gen_list[api_name] api_path = info['path'] @@ -691,6 +1396,14 @@ def ddns_provider_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def ddns_record_info(self) -> dict[str, object] | str: + """ + Get DDNS record information. + + Returns + ------- + dict[str, object] or str + DDNS record information. + """ api_name = 'SYNO.Core.DDNS.Record' info = self.gen_list[api_name] api_path = info['path'] @@ -699,6 +1412,14 @@ def ddns_record_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def ddns_external_ip(self) -> dict[str, object] | str: + """ + Get DDNS external IP. + + Returns + ------- + dict[str, object] or str + DDNS external IP. + """ api_name = 'SYNO.Core.DDNS.ExtIP' info = self.gen_list[api_name] api_path = info['path'] @@ -708,6 +1429,14 @@ def ddns_external_ip(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def ddns_synology(self) -> dict[str, object] | str: + """ + Get Synology DDNS information. + + Returns + ------- + dict[str, object] or str + Synology DDNS information. + """ api_name = 'SYNO.Core.DDNS.Synology' info = self.gen_list[api_name] api_path = info['path'] @@ -717,6 +1446,14 @@ def ddns_synology(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def iscsi_lun_info(self) -> dict[str, object] | str: + """ + Get iSCSI LUN information. + + Returns + ------- + dict[str, object] or str + iSCSI LUN information. + """ api_name = 'SYNO.Core.ISCSI.LUN' info = self.gen_list[api_name] api_path = info['path'] @@ -725,6 +1462,14 @@ def iscsi_lun_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def hddman(self) -> dict[str, object] | str: + """ + Get HDD manager information. + + Returns + ------- + dict[str, object] or str + HDD manager information. + """ api_name = 'SYNO.Storage.CGI.HddMan' info = self.gen_list[api_name] api_path = info['path'] @@ -733,6 +1478,14 @@ def hddman(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def ftp_security_info(self) -> dict[str, object] | str: + """ + Get FTP security information. + + Returns + ------- + dict[str, object] or str + FTP security information. + """ api_name = 'SYNO.Core.FileServ.FTP.Security' info = self.core_list[api_name] api_path = info['path'] @@ -741,6 +1494,14 @@ def ftp_security_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def bandwidth_control_info(self) -> dict[str, object] | str: + """ + Get bandwidth control information. + + Returns + ------- + dict[str, object] or str + Bandwidth control information. + """ api_name = 'SYNO.Core.BandwidthControl.Protocol' info = self.core_list[api_name] api_path = info['path'] @@ -749,7 +1510,15 @@ def bandwidth_control_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) - def directory_domain_info(self) -> dict[str, object] | str: # TODO to test + def directory_domain_info(self) -> dict[str, object] | str: + """ + Get directory domain information. + + Returns + ------- + dict[str, object] or str + Directory domain information. + """ api_name = 'SYNO.Core.Directory.Domain' info = self.core_list[api_name] api_path = info['path'] @@ -757,7 +1526,15 @@ def directory_domain_info(self) -> dict[str, object] | str: # TODO to test return self.request_data(api_name, api_path, req_param) - def ws_transfer_info(self) -> dict[str, object] | str: # TODO to test + def ws_transfer_info(self) -> dict[str, object] | str: + """ + Get WS transfer information. + + Returns + ------- + dict[str, object] or str + WS transfer information. + """ api_name = 'SYNO.Core.FileServ.ServiceDiscovery.WSTransfer' info = self.core_list[api_name] api_path = info['path'] @@ -766,6 +1543,14 @@ def ws_transfer_info(self) -> dict[str, object] | str: # TODO to test return self.request_data(api_name, api_path, req_param) def ref_link_copy_info(self) -> dict[str, object] | str: + """ + Get reflink copy information. + + Returns + ------- + dict[str, object] or str + Reflink copy information. + """ api_name = 'SYNO.Core.FileServ.ReflinkCopy' info = self.core_list[api_name] api_path = info['path'] @@ -774,6 +1559,14 @@ def ref_link_copy_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def bonjour_service_info(self) -> dict[str, object] | str: + """ + Get Bonjour service information. + + Returns + ------- + dict[str, object] or str + Bonjour service information. + """ api_name = 'SYNO.Core.ExternalDevice.Printer.BonjourSharing' info = self.core_list[api_name] api_path = info['path'] @@ -782,6 +1575,14 @@ def bonjour_service_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def personal_photo_enable(self) -> dict[str, object] | str: + """ + Get personal photo enable status. + + Returns + ------- + dict[str, object] or str + Personal photo enable status. + """ api_name = 'SYNO.Core.User.Home' info = self.core_list[api_name] api_path = info['path'] @@ -790,6 +1591,14 @@ def personal_photo_enable(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def ftp_chroot_user(self) -> dict[str, object] | str: + """ + Get FTP chroot user information. + + Returns + ------- + dict[str, object] or str + FTP chroot user information. + """ api_name = 'SYNO.Core.FileServ.FTP.ChrootUser' info = self.core_list[api_name] api_path = info['path'] @@ -798,6 +1607,14 @@ def ftp_chroot_user(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def server_pair(self) -> dict[str, object] | str: + """ + Get server pair information. + + Returns + ------- + dict[str, object] or str + Server pair information. + """ api_name = 'SYNO.S2S.Server.Pair' info = self.gen_list[api_name] api_path = info['path'] @@ -807,6 +1624,23 @@ def server_pair(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def groups_info(self, offset: int = 0, limit: int = -1, name_only: bool = False) -> dict[str, object] | str: + """ + Get groups information. + + Parameters + ---------- + offset : int, optional + Offset for pagination. Defaults to 0. + limit : int, optional + Maximum number of groups to retrieve. Defaults to -1. + name_only : bool, optional + If True, returns only group names. Defaults to False. + + Returns + ------- + dict[str, object] or str + Groups information. + """ api_name = 'SYNO.Core.Group' info = self.core_list[api_name] api_path = info['path'] @@ -823,6 +1657,14 @@ def groups_info(self, offset: int = 0, limit: int = -1, name_only: bool = False) return self.request_data(api_name, api_path, req_param) def ldap_info(self) -> dict[str, object] | str: + """ + Get LDAP information. + + Returns + ------- + dict[str, object] or str + LDAP information. + """ api_name = 'SYNO.Core.Directory.LDAP' info = self.core_list[api_name] api_path = info['path'] @@ -840,6 +1682,14 @@ def ldap_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param)''' def sso_iwa_info(self) -> dict[str, object] | str: + """ + Get SSO IWA information. + + Returns + ------- + dict[str, object] or str + SSO IWA information. + """ api_name = 'SYNO.Core.Directory.SSO.IWA' info = self.core_list[api_name] api_path = info['path'] @@ -848,6 +1698,14 @@ def sso_iwa_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def sso_info(self) -> dict[str, object] | str: + """ + Get SSO information. + + Returns + ------- + dict[str, object] or str + SSO information. + """ api_name = 'SYNO.Core.Directory.SSO' info = self.core_list[api_name] api_path = info['path'] @@ -856,6 +1714,14 @@ def sso_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_interface_info(self) -> dict[str, object] | str: + """ + Get network interface information. + + Returns + ------- + dict[str, object] or str + Network interface information. + """ api_name = 'SYNO.Core.Network.Interface' info = self.core_list[api_name] api_path = info['path'] @@ -864,6 +1730,14 @@ def network_interface_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def proxy_info(self) -> dict[str, object] | str: + """ + Get proxy information. + + Returns + ------- + dict[str, object] or str + Proxy information. + """ api_name = 'SYNO.Core.Network.Proxy' info = self.core_list[api_name] api_path = info['path'] @@ -872,6 +1746,21 @@ def proxy_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def gateway_list(self, ip_type: str = 'ipv4', type: str = 'wan') -> dict[str, object] | str: + """ + Get gateway list. + + Parameters + ---------- + ip_type : str, optional + IP type (e.g., 'ipv4', 'ipv6'). Defaults to 'ipv4'. + type : str, optional + Gateway type (e.g., 'wan'). Defaults to 'wan'. + + Returns + ------- + dict[str, object] or str + Gateway list. + """ api_name = 'SYNO.Core.Network.Router.Gateway.List' info = self.core_list[api_name] api_path = info['path'] @@ -881,6 +1770,14 @@ def gateway_list(self, ip_type: str = 'ipv4', type: str = 'wan') -> dict[str, ob return self.request_data(api_name, api_path, req_param) def firewall_info(self) -> dict[str, object] | str: + """ + Get firewall information. + + Returns + ------- + dict[str, object] or str + Firewall information. + """ api_name = 'SYNO.Core.Security.Firewall.Profile' info = self.core_list[api_name] api_path = info['path'] @@ -901,6 +1798,14 @@ def firewall_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param)''' def auto_upgrade_status(self) -> dict[str, object] | str: + """ + Get auto upgrade status. + + Returns + ------- + dict[str, object] or str + Auto upgrade status. + """ api_name = 'SYNO.Core.Upgrade.AutoUpgrade' info = self.core_list[api_name] api_path = info['path'] @@ -909,6 +1814,14 @@ def auto_upgrade_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def upgrade_server_check(self) -> dict[str, object] | str: + """ + Check upgrade server. + + Returns + ------- + dict[str, object] or str + Upgrade server check result. + """ api_name = 'SYNO.Core.Upgrade.Server' info = self.core_list[api_name] api_path = info['path'] @@ -918,6 +1831,14 @@ def upgrade_server_check(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def alarm_rules_logs(self) -> dict[str, object] | str: + """ + Get alarm rules logs. + + Returns + ------- + dict[str, object] or str + Alarm rules logs. + """ api_name = 'SYNO.ResourceMonitor.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -927,6 +1848,14 @@ def alarm_rules_logs(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def alarm_rules_list(self) -> dict[str, object] | str: + """ + Get alarm rules list. + + Returns + ------- + dict[str, object] or str + Alarm rules list. + """ api_name = 'SYNO.ResourceMonitor.EventRule' info = self.gen_list[api_name] api_path = info['path'] @@ -935,6 +1864,14 @@ def alarm_rules_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def resource_monitor_settings_list(self) -> dict[str, object] | str: + """ + Get resource monitor settings. + + Returns + ------- + dict[str, object] or str + Resource monitor settings. + """ api_name = 'SYNO.ResourceMonitor.Setting' info = self.gen_list[api_name] api_path = info['path'] @@ -944,6 +1881,25 @@ def resource_monitor_settings_list(self) -> dict[str, object] | str: def file_handling_access(self, sort_direction: str = 'ASC', sort_by: str = 'service', limit: int = 50, offset: int = 0) -> dict[str, object] | str: + """ + Get file handling access information. + + Parameters + ---------- + sort_direction : str, optional + Sort direction ('ASC' or 'DESC'). Defaults to 'ASC'. + sort_by : str, optional + Field to sort by. Defaults to 'service'. + limit : int, optional + Maximum number of results. Defaults to 50. + offset : int, optional + Offset for pagination. Defaults to 0. + + Returns + ------- + dict[str, object] or str + File handling access information. + """ api_name = 'SYNO.Core.FileHandle' info = self.core_list[api_name] api_path = info['path'] @@ -953,6 +1909,19 @@ def file_handling_access(self, sort_direction: str = 'ASC', sort_by: str = 'serv return self.request_data(api_name, api_path, req_param) def list_service_group(self, interval=0) -> dict[str, object] | str: + """ + Get service group list. + + Parameters + ---------- + interval : int, optional + Interval for statistics. Defaults to 0. + + Returns + ------- + dict[str, object] or str + Service group list. + """ api_name = 'SYNO.Core.System.ProcessGroup' info = self.core_list[api_name] api_path = info['path'] @@ -962,6 +1931,14 @@ def list_service_group(self, interval=0) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def list_process_group(self) -> dict[str, object] | str: + """ + Get process group list. + + Returns + ------- + dict[str, object] or str + Process group list. + """ api_name = 'SYNO.Core.System.Process' info = self.core_list[api_name] api_path = info['path'] @@ -970,6 +1947,14 @@ def list_process_group(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def installed_package_list(self) -> dict[str, object] | str: + """ + Get installed package list. + + Returns + ------- + dict[str, object] or str + Installed package list. + """ api_name = 'SYNO.Core.Package' info = self.core_list[api_name] api_path = info['path'] @@ -988,6 +1973,14 @@ def installed_package_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def active_notifications(self) -> dict[str, object] | str: + """ + Get active notifications. + + Returns + ------- + dict[str, object] or str + Active notifications. + """ api_name = 'SYNO.Core.DSMNotify' info = self.core_list[api_name] api_path = info['path'] @@ -997,6 +1990,14 @@ def active_notifications(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_system_health(self) -> dict[str, object] | str: + """ + Get system health information. + + Returns + ------- + dict[str, object] or str + System health information. + """ api_name = 'SYNO.Core.System.SystemHealth' info = self.core_list[api_name] api_path = info['path'] @@ -1004,6 +2005,14 @@ def get_system_health(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def upgrade_status(self) -> dict[str, object] | str: + """ + Get upgrade status. + + Returns + ------- + dict[str, object] or str + Upgrade status. + """ api_name = 'SYNO.Core.Upgrade' info = self.core_list[api_name] api_path = info['path'] From 0c368875a92916160f6a9554bf0218e40555ae12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:20:26 +0700 Subject: [PATCH 023/126] fix: synology_api/core_user.py update docstrings to comply with Numpydoc standards --- synology_api/core_user.py | 1011 ++++++++++++++++++------------------- 1 file changed, 503 insertions(+), 508 deletions(-) diff --git a/synology_api/core_user.py b/synology_api/core_user.py index 536fb66a..3dd86e21 100644 --- a/synology_api/core_user.py +++ b/synology_api/core_user.py @@ -1,98 +1,120 @@ +""" +Synology Core User API wrapper. + +This module provides a Python interface for managing users on Synology NAS devices, +including user creation, modification, deletion, group membership, password policies, +and password expiry. +""" + import json from typing import Any from . import base_api class User(base_api.BaseApi): - """Core User API implementation. - - Supported actions: - - Getters: - - Get all users - - Password policies - - Password expiry - - - Setters: - - Set user password policy - - - Actions: - - Create new user - - Modify user - - Delete user - - User join/leave group + """ + Core User API implementation. + + Methods + ------- + get_users(offset=0, limit=-1, sort_by="name", sort_direction="ASC", additional=[]) + Retrieve groups information. + get_user(name, additional=[]) + Retrieve user information. + create_user(...) + Create a new user. + modify_user(...) + Modify a user. + delete_user(name) + Delete a user. + affect_groups(name, join_groups=[], leave_groups=[]) + Affect or disaffect groups to a user. + affect_groups_status(task_id) + Get the status of a join task. + get_password_policy() + Get the password policy. + set_password_policy(...) + Set the password policy. + get_password_expiry() + Get the password expiry. + set_password_expiry(...) + Set the password expiry. + password_confirm(password) + Confirm password/session. + get_username_policy() + Get the username policy. + + Examples + -------- + See individual method docstrings for usage examples. """ def get_users( self, offset: int = 0, limit: int = -1, sort_by: str = "name", sort_direction: str = "ASC", additional: list[str] = [] ) -> dict[str, object]: - """Retrieve groups information. - - Parameters - ---------- - offset : int, optional - The offset of the groups to retrieve. Defaults to `0`. - - limit : int, optional - The maximum number of groups to retrieve. Defaults to `-1` . - - sort_by : str, optional - Sort by a specific field. Defaults to `"name"`. - - sort_direction : str, optional - The sort direction. Defaults to `"ASC"` else `"DESC"`. - - additional : list[str], optional - Additional fields to retrieve. Defaults to `[]`. - - All fields known are: `["description","email","expired","cannot_chg_passwd","passwd_never_expire","password_last_change", "groups", "2fa_status"]`. - - - Returns - ------- - dict[str, object] - A dictionary containing the groups information. - - Examples - -------- - ```json - { - "data": { - "offset": 0, - "total": 5, - "users": [ - { - "description": "System default user", - "email": "", - "expired": "now", - "name": "admin", - "passwd_never_expire": true - }, - { - "description": "Guest", - "email": "", - "expired": "now", - "name": "guest", - "passwd_never_expire": true - }, - { - "description": "", - "email": "", - "expired": "normal", - "name": "test_api", - "passwd_never_expire": true - }, - { - "description": "test description", - "email": "testemail@test.com", - "expired": "normal", - "name": "test_user", - "passwd_never_expire": true - } - ] + """ + Retrieve groups information. + + Parameters + ---------- + offset : int, optional + The offset of the groups to retrieve. Defaults to `0`. + limit : int, optional + The maximum number of groups to retrieve. Defaults to `-1`. + sort_by : str, optional + Sort by a specific field. Defaults to `"name"`. + sort_direction : str, optional + The sort direction. Defaults to `"ASC"` else `"DESC"`. + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `["description","email","expired","cannot_chg_passwd","passwd_never_expire","password_last_change", "groups", "2fa_status"]`. + + Returns + ------- + dict[str, object] + A dictionary containing the groups information. + + Examples + -------- + ```json + { + "data": { + "offset": 0, + "total": 5, + "users": [ + { + "description": "System default user", + "email": "", + "expired": "now", + "name": "admin", + "passwd_never_expire": true }, - "success": true - } - ``` + { + "description": "Guest", + "email": "", + "expired": "now", + "name": "guest", + "passwd_never_expire": true + }, + { + "description": "", + "email": "", + "expired": "normal", + "name": "test_api", + "passwd_never_expire": true + }, + { + "description": "test description", + "email": "testemail@test.com", + "expired": "normal", + "name": "test_user", + "passwd_never_expire": true + } + ] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.User" info = self.core_list[api_name] @@ -111,48 +133,47 @@ def get_users( return self.request_data(api_name, api_path, req_param) def get_user(self, name: str, additional: list[str] = []) -> dict[str, object]: - """Retrieve a user information. - - Parameters - ---------- - name : str - The name of the user. - - additional : list[str], optional - Additional fields to retrieve. Defaults to `[]`. - - All fields known are: `["description","email","expired","cannot_chg_passwd","passwd_never_expire","password_last_change","is_password_pending"]`. - - Returns - ------- - dict[str, object] - A dictionary containing the user information. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User", - "data": { - "users": [ - { - "cannot_chg_passwd": false, - "description": "", - "email": "", - "expired": "normal", - "is_password_pending": false, - "name": "test_api", - "passwd_never_expire": true, - "password_last_change": 19789, - "uid": 1027 - } - ] - }, - "method": "get", - "success": true, - "version": 1 - } - ``` + """ + Retrieve user information. + + Parameters + ---------- + name : str + The name of the user. + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `["description","email","expired","cannot_chg_passwd","passwd_never_expire","password_last_change","is_password_pending"]`. + + Returns + ------- + dict[str, object] + A dictionary containing the user information. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User", + "data": { + "users": [ + { + "cannot_chg_passwd": false, + "description": "", + "email": "", + "expired": "normal", + "is_password_pending": false, + "name": "test_api", + "passwd_never_expire": true, + "password_last_change": 19789, + "uid": 1027 + } + ] + }, + "method": "get", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User" info = self.core_list[api_name] @@ -171,54 +192,47 @@ def create_user( self, name: str, password: str, description: str = "", email: str = "", expire: str = "never", cannot_chg_passwd: bool = False, passwd_never_expire: bool = True, notify_by_email: bool = False, send_password: bool = False ) -> dict[str, object]: - """Create a new user. - - Parameters - ---------- - name : str - The name of the user. - - password : str - The password of the user. - - description : str, optional - The description of the user. Defaults to `""`. - - email : str, optional - The email of the user. Defaults to `""`. - - expire : str, optional - The expiration date of the user. Defaults to `"never"`. - - cannot_chg_passwd : bool, optional - Whether the password can be changed. Defaults to `False`. - - passwd_never_expire : bool, optional - Whether the password should never expire. Defaults to `True`. - - notify_by_email : bool, optional - Whether to notify by email. Defaults to `False`. - - send_password : bool, optional - Whether to send the password. Defaults to `False`. - - Returns - ------- - dict[str, object] - A dictionary containing the user information. - - Examples - -------- - ```json + """ + Create a new user. + + Parameters + ---------- + name : str + The name of the user. + password : str + The password of the user. + description : str, optional + The description of the user. Defaults to `""`. + email : str, optional + The email of the user. Defaults to `""`. + expire : str, optional + The expiration date of the user. Defaults to `"never"`. + cannot_chg_passwd : bool, optional + Whether the password can be changed. Defaults to `False`. + passwd_never_expire : bool, optional + Whether the password should never expire. Defaults to `True`. + notify_by_email : bool, optional + Whether to notify by email. Defaults to `False`. + send_password : bool, optional + Whether to send the password. Defaults to `False`. + + Returns + ------- + dict[str, object] + A dictionary containing the user information. + + Examples + -------- + ```json + { + "data": { - "data": - { - "name":"toto", - "uid": 1030 - }, - "success": true - } - ``` + "name":"toto", + "uid": 1030 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.User" @@ -254,57 +268,49 @@ def modify_user( self, name: str, new_name: str, password: str = "", description: str = "", email: str = "", expire: str = "never", cannot_chg_passwd: bool = False, passwd_never_expire: bool = True, notify_by_email: bool = False, send_password: bool = False ) -> dict[str, object]: - """Modify a user. - - Parameters - ---------- - name : str - The name of the actual user. - - new_name : str - The new name of the user. - - password : str, optional - The password of the user. Defaults to `""`. - - description : str, optional - The description of the user. Defaults to `""`. - - email : str, optional - The email of the user. Defaults to `""`. - - expire : str, optional - The expiration date of the user. Defaults to `"never"`. - - cannot_chg_passwd : bool, optional - Whether the password can be changed. Defaults to `False`. - - passwd_never_expire : bool, optional - Whether the password should never expire. Defaults to `True`. - - notify_by_email : bool, optional - Whether to notify by email. Defaults to `False`. - - send_password : bool, optional - Whether to send the password. Defaults to `False`. - - Returns - ------- - dict[str, object] - A dictionary containing the user information. - - Examples - -------- - ```json - { - "data":{ - "name": "test_user2", - "password_last_change": 20106, - "uid": 1028 - }, - "success": true - } - ``` + """ + Modify a user. + + Parameters + ---------- + name : str + The name of the actual user. + new_name : str + The new name of the user. + password : str, optional + The password of the user. Defaults to `""`. + description : str, optional + The description of the user. Defaults to `""`. + email : str, optional + The email of the user. Defaults to `""`. + expire : str, optional + The expiration date of the user. Defaults to `"never"`. + cannot_chg_passwd : bool, optional + Whether the password can be changed. Defaults to `False`. + passwd_never_expire : bool, optional + Whether the password should never expire. Defaults to `True`. + notify_by_email : bool, optional + Whether to notify by email. Defaults to `False`. + send_password : bool, optional + Whether to send the password. Defaults to `False`. + + Returns + ------- + dict[str, object] + A dictionary containing the user information. + + Examples + -------- + ```json + { + "data":{ + "name": "test_user2", + "password_last_change": 20106, + "uid": 1028 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.User" info = self.core_list[api_name] @@ -333,29 +339,30 @@ def modify_user( return self.request_data(api_name, api_path, req_param, method="post") def delete_user(self, name: str) -> dict[str, object]: - """Delete a user. - - Parameters - ---------- - name : str - The name of the user to delete. - - Returns - ------- - dict[str, object] - A dictionary containing the user information. - - Examples - -------- - ```json - { - "data": { - "name": "toto", - "uid": 1030 - }, - "success": true - } - ``` + """ + Delete a user. + + Parameters + ---------- + name : str + The name of the user to delete. + + Returns + ------- + dict[str, object] + A dictionary containing the user information. + + Examples + -------- + ```json + { + "data": { + "name": "toto", + "uid": 1030 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.User" info = self.core_list[api_name] @@ -369,40 +376,38 @@ def delete_user(self, name: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def affect_groups(self, name: str, join_groups: list[str] = [], leave_groups: list[str] = []) -> dict[str, object]: - """Affect or disaffect groups to a user. - - Tip: This request is asynchronous and will return a task id to check the status of the join task. Use `affect_groups_status` func to check the status of the task. - - Parameters - ---------- - name : str - The name of the user. - - join_groups : list[str] - The names of the groups to join. - - leave_groups : list[str] - The names of the groups to leave. - - - Returns - ------- - dict[str, object] - A dictionary containing the task id to check the status of the join task. Use `affect_groups_status` func to check the status of the task. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User.Group", - "data": { - "task_id": "@administrators/groupbatch1737238746C6723E33" - }, - "method": "join", - "success": true, - "version": 1 - } - ``` + """ + Affect or disaffect groups to a user. + + Tip: This request is asynchronous and will return a task id to check the status of the join task. Use `affect_groups_status` func to check the status of the task. + + Parameters + ---------- + name : str + The name of the user. + join_groups : list[str] + The names of the groups to join. + leave_groups : list[str] + The names of the groups to leave. + + Returns + ------- + dict[str, object] + A dictionary containing the task id to check the status of the join task. Use `affect_groups_status` func to check the status of the task. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User.Group", + "data": { + "task_id": "@administrators/groupbatch1737238746C6723E33" + }, + "method": "join", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User.Group" @@ -418,44 +423,45 @@ def affect_groups(self, name: str, join_groups: list[str] = [], leave_groups: li return self.request_data(api_name, api_path, req_param) def affect_groups_status(self, task_id: str): - """Get the status of a join task. - - Parameters - ---------- - task_id : str - The task id of the join task. - - Returns - ------- - dict[str, object] - A dictionary containing the status of the join task. - - Examples - -------- - ```json - { + """ + Get the status of a join task. + + Parameters + ---------- + task_id : str + The task id of the join task. + + Returns + ------- + dict[str, object] + A dictionary containing the status of the join task. + + Examples + -------- + ```json + { + "data": { + "auto_remove": false, "data": { - "auto_remove": false, - "data": { - "name": "test_user2", - "pid": 18126, - "progress": 1, - "total": 1, - "uid": 1028 - }, - "finish": false, - "info": { - "api": "SYNO.Core.User.Group", - "group": "admin", - "method": "join", - "prefix": "groupbatch", - "version": 1 - }, - "success": true + "name": "test_user2", + "pid": 18126, + "progress": 1, + "total": 1, + "uid": 1028 + }, + "finish": false, + "info": { + "api": "SYNO.Core.User.Group", + "group": "admin", + "method": "join", + "prefix": "groupbatch", + "version": 1 }, "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = "SYNO.Core.User.Group" info = self.core_list[api_name] @@ -468,36 +474,37 @@ def affect_groups_status(self, task_id: str): return self.request_data(api_name, api_path, req_param) def get_password_policy(self) -> dict[str, object]: - """Get the password policy. - - Returns - ------- - dict[str, object] - A dictionary containing the password policy information. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User.PasswordPolicy", - "data": { - "enable_reset_passwd_by_email": false, - "password_must_change": false, - "strong_password": { - "exclude_username": true, - "history_num": 0, - "included_numeric_char": true, - "included_special_char": false, - "min_length": 8, - "min_length_enable": true, - "mixed_case": true - } - }, - "method": "get", - "success": true, - "version": 1 - } - ``` + """ + Get the password policy. + + Returns + ------- + dict[str, object] + A dictionary containing the password policy information. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User.PasswordPolicy", + "data": { + "enable_reset_passwd_by_email": false, + "password_must_change": false, + "strong_password": { + "exclude_username": true, + "history_num": 0, + "included_numeric_char": true, + "included_special_char": false, + "min_length": 8, + "min_length_enable": true, + "mixed_case": true + } + }, + "method": "get", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User.PasswordPolicy" info = self.core_list[api_name] @@ -514,56 +521,48 @@ def set_password_policy( min_length: int = 8, min_length_enable: bool = True, mixed_case: bool = True, exclude_common_password: bool = False, exclude_history: bool = False ) -> dict[str, object]: - """Set the password policy. - - Parameters - ---------- - enable_reset_passwd_by_email : bool, optional - Defaults to `False`. - - password_must_change : bool, optional - Defaults to `False`. - - exclude_username : bool, optional - Defaults to `True`. - - included_numeric_char : bool, optional - Defaults to `True`. - - included_special_char : bool, optional - Defaults to `False`. - - min_length : int, optional - Defaults to `8`. - - min_length_enable : bool, optional - Defaults to `True`. - - mixed_case : bool, optional - Defaults to `True`. - - exclude_common_password : bool, optional - Defaults to `False`. - - exclude_history : bool, optional - Defaults to `False`. - - Returns - ------- - dict[str, object] - A dictionary indicating the success of the operation. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User.PasswordPolicy", - "data": {}, - "method": "set", - "success": true, - "version": 1 - } - ``` + """ + Set the password policy. + + Parameters + ---------- + enable_reset_passwd_by_email : bool, optional + Defaults to `False`. + password_must_change : bool, optional + Defaults to `False`. + exclude_username : bool, optional + Defaults to `True`. + included_numeric_char : bool, optional + Defaults to `True`. + included_special_char : bool, optional + Defaults to `False`. + min_length : int, optional + Defaults to `8`. + min_length_enable : bool, optional + Defaults to `True`. + mixed_case : bool, optional + Defaults to `True`. + exclude_common_password : bool, optional + Defaults to `False`. + exclude_history : bool, optional + Defaults to `False`. + + Returns + ------- + dict[str, object] + A dictionary indicating the success of the operation. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User.PasswordPolicy", + "data": {}, + "method": "set", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User.PasswordPolicy" @@ -588,31 +587,32 @@ def set_password_policy( return self.request_data(api_name, api_path, req_param) def get_password_expiry(self) -> dict[str, object]: - """Get the password expiry. - - Returns - ------- - dict[str, object] - A dictionary containing the password expiry information. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User.PasswordExpiry", - "data": { - "allow_reset_after_expired": true, - "enable_login_prompt": false, - "enable_mail_notification": false, - "mail_notification_days": "", - "min_age_enable": false, - "password_expire_enable": false - }, - "method": "get", - "success": true, - "version": 1 - } - ``` + """ + Get the password expiry. + + Returns + ------- + dict[str, object] + A dictionary containing the password expiry information. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User.PasswordExpiry", + "data": { + "allow_reset_after_expired": true, + "enable_login_prompt": false, + "enable_mail_notification": false, + "mail_notification_days": "", + "min_age_enable": false, + "password_expire_enable": false + }, + "method": "get", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User.PasswordExpiry" info = self.core_list[api_name] @@ -628,52 +628,45 @@ def set_password_expiry( enable_login_prompt: bool = False, login_prompt_days: int = 1, allow_reset_after_expired: bool = True, enable_mail_notification: bool = False, never_expired_list: list[str] = [] ) -> dict[str, object]: - """Set the password expiry. - - Parameters - ---------- - password_expire_enable : bool, optional - Enable password expiry. Defaults to `False`. - - max_age : int, optional - Maximum time before password expiry. Defaults to `30`. - - min_age_enable : bool, optional - Enable minimum time before password expiry. Defaults to `False`. - - min_age : int, optional - Minimum time before password expiry. Defaults to `1`. - - enable_login_prompt : bool, optional - Enable login prompt. Defaults to `False`. - - login_prompt_days : int, optional - Days before login prompt. Defaults to `1`. - - allow_reset_after_expired : bool, optional - Allow reset after password expiry. Defaults to `True`. - - enable_mail_notification : bool, optional - Enable mail notification. Defaults to `False`. - - never_expired_list : list[str], optional - List of users that should never expire. - - Returns - ------- - dict[str, object] - A dictionary indicating the success of the operation. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User.PasswordExpiry", - "method": "set", - "success": true, - "version": 1 - } - ``` + """ + Set the password expiry. + + Parameters + ---------- + password_expire_enable : bool, optional + Enable password expiry. Defaults to `False`. + max_age : int, optional + Maximum time before password expiry. Defaults to `30`. + min_age_enable : bool, optional + Enable minimum time before password expiry. Defaults to `False`. + min_age : int, optional + Minimum time before password expiry. Defaults to `1`. + enable_login_prompt : bool, optional + Enable login prompt. Defaults to `False`. + login_prompt_days : int, optional + Days before login prompt. Defaults to `1`. + allow_reset_after_expired : bool, optional + Allow reset after password expiry. Defaults to `True`. + enable_mail_notification : bool, optional + Enable mail notification. Defaults to `False`. + never_expired_list : list[str], optional + List of users that should never expire. + + Returns + ------- + dict[str, object] + A dictionary indicating the success of the operation. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User.PasswordExpiry", + "method": "set", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User.PasswordExpiry" @@ -695,30 +688,31 @@ def set_password_expiry( return self.request_data(api_name, api_path, req_param) def password_confirm(self, password: str) -> dict[str, object]: - """Issues a passowrd/session comparison to ensure the given password matches the auth of the current session. - - Note: This is needed by some APIs as a confirmation method, for example, when creating/modifying a scheduled task with root permissions, seldom needed by end users. - - Parameters - ---------- - password : str - The password with which the session was initiated. - - Returns - ------- - dict[str, object] - A dictionary containing a `SynoConfirmPWToken`, or an error message. - - Examples - -------- - ```json - { - "data": { - "SynoConfirmPWToken": "xxxxx" - }, - "success": true - } - ``` + """ + Confirm password/session to ensure the given password matches the auth of the current session. + + Note: This is needed by some APIs as a confirmation method, for example, when creating/modifying a scheduled task with root permissions, seldom needed by end users. + + Parameters + ---------- + password : str + The password with which the session was initiated. + + Returns + ------- + dict[str, object] + A dictionary containing a `SynoConfirmPWToken`, or an error message. + + Examples + -------- + ```json + { + "data": { + "SynoConfirmPWToken": "xxxxx" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.User.PasswordConfirm' info = self.core_list[api_name] @@ -735,24 +729,25 @@ def password_confirm(self, password: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param, method="post") def get_username_policy(self) -> dict[str, object]: - """Get the username policy (List of username that are not usable). - - Returns - ------- - dict[str, object] - A dictionary containing the username policy information. - - Examples - -------- - ```json - { - "api": "SYNO.Core.User.UsernamePolicy", - "data": ["root", "rootuser", "rootusr", "admin", "administrator", "adm", "adminuser", "adminusr", "user",…], - "method": "get", - "success": true, - "version": 1 - } - ``` + """ + Get the username policy (list of usernames that are not usable). + + Returns + ------- + dict[str, object] + A dictionary containing the username policy information. + + Examples + -------- + ```json + { + "api": "SYNO.Core.User.UsernamePolicy", + "data": ["root", "rootuser", "rootusr", "admin", "administrator", "adm", "adminuser", "adminusr", "user",…], + "method": "get", + "success": true, + "version": 1 + } + ``` """ api_name = "SYNO.Core.User.UsernamePolicy" info = self.core_list[api_name] From 6e4a0ebd95068d55dd2862a067dbde96e4173cd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:21:41 +0700 Subject: [PATCH 024/126] fix: synology_api/dhcp_server.py update docstrings to comply with Numpydoc standards --- synology_api/dhcp_server.py | 92 +++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/synology_api/dhcp_server.py b/synology_api/dhcp_server.py index 367408e4..fd7bd4eb 100644 --- a/synology_api/dhcp_server.py +++ b/synology_api/dhcp_server.py @@ -1,3 +1,10 @@ +""" +Synology DHCP Server API wrapper. + +This module provides a Python interface for managing DHCP server, PXE, TFTP, and network +interfaces on Synology NAS devices. +""" + from __future__ import annotations from typing import Optional @@ -6,8 +13,27 @@ class DhcpServer(base_api.BaseApi): + """ + Core DHCP Server API implementation for Synology NAS. + + This class provides methods to retrieve and manage DHCP server, PXE, TFTP, and network + interface information. + """ def general_info(self, ifname: str = 'ovs_eth0') -> dict[str, object] | str: + """ + Get general DHCP server information for a given interface. + + Parameters + ---------- + ifname : str, optional + Interface name. Defaults to 'ovs_eth0'. + + Returns + ------- + dict[str, object] or str + General DHCP server information. + """ api_name = 'SYNO.Network.DHCPServer' info = self.gen_list[api_name] api_path = info['path'] @@ -17,6 +43,14 @@ def general_info(self, ifname: str = 'ovs_eth0') -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def vendor(self) -> dict[str, object] | str: + """ + Get DHCP vendor information. + + Returns + ------- + dict[str, object] or str + DHCP vendor information. + """ api_name = 'SYNO.Network.DHCPServer.Vendor' info = self.gen_list[api_name] api_path = info['path'] @@ -25,6 +59,14 @@ def vendor(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def pxe(self) -> dict[str, object] | str: + """ + Get PXE server information. + + Returns + ------- + dict[str, object] or str + PXE server information. + """ api_name = 'SYNO.Network.DHCPServer.PXE' info = self.gen_list[api_name] api_path = info['path'] @@ -33,6 +75,14 @@ def pxe(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def tftp(self) -> dict[str, object] | str: + """ + Get TFTP server information. + + Returns + ------- + dict[str, object] or str + TFTP server information. + """ api_name = 'SYNO.Core.TFTP' info = self.core_list[api_name] api_path = info['path'] @@ -41,6 +91,14 @@ def tftp(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_bond(self) -> dict[str, object] | str: + """ + Get network bond interface information. + + Returns + ------- + dict[str, object] or str + Network bond interface information. + """ api_name = 'SYNO.Core.Network.Bond' info = self.gen_list[api_name] api_path = info['path'] @@ -49,6 +107,14 @@ def network_bond(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def network_ethernet(self) -> dict[str, object] | str: + """ + Get network ethernet interface information. + + Returns + ------- + dict[str, object] or str + Network ethernet interface information. + """ api_name = 'SYNO.Core.Network.Ethernet' info = self.gen_list[api_name] api_path = info['path'] @@ -57,6 +123,19 @@ def network_ethernet(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def dhcp_clientlist(self, ifname: str = 'bond0') -> dict[str, object] | str: + """ + Get DHCP client list for a given interface. + + Parameters + ---------- + ifname : str, optional + Interface name. Defaults to 'bond0'. + + Returns + ------- + dict[str, object] or str + DHCP client list. + """ api_name = 'SYNO.Network.DHCPServer.ClientList' info = self.gen_list[api_name] api_path = info['path'] @@ -66,6 +145,19 @@ def dhcp_clientlist(self, ifname: str = 'bond0') -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def dhcp_reservations(self, ifname: str = 'bond0') -> dict[str, object] | str: + """ + Get DHCP reservations for a given interface. + + Parameters + ---------- + ifname : str, optional + Interface name. Defaults to 'bond0'. + + Returns + ------- + dict[str, object] or str + DHCP reservations. + """ api_name = 'SYNO.Network.DHCPServer.Reservation' info = self.gen_list[api_name] api_path = info['path'] From ec2cc0a6997c89f42f925252b14d1b11b6ce707c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:35:56 +0700 Subject: [PATCH 025/126] fix: synology_api/directory_server.py update docstrings to comply with Numpydoc standards --- synology_api/directory_server.py | 1164 +++++++++++++++--------------- 1 file changed, 564 insertions(+), 600 deletions(-) diff --git a/synology_api/directory_server.py b/synology_api/directory_server.py index f5a783a2..036500f0 100644 --- a/synology_api/directory_server.py +++ b/synology_api/directory_server.py @@ -1,4 +1,5 @@ -"""directory_server.py works with base_api_core to provide AD capabilities.""" +"""Directory_server.py works with base_api_core to provide AD capabilities.""" + from __future__ import annotations import json from typing import Optional, Any @@ -6,16 +7,18 @@ class DirectoryServer(base_api.BaseApi): - """The directory server API. + """ + The directory server API. - Not all items within this class use the Active Directory API. Some use the Synology Entry API which proxies - the request. Some are related to managing users in ways that are useful in the Directory Server context. For + Not all items within this class use the Active Directory API. Some use the Synology Entry API which proxies + the request. Some are related to managing users in ways that are useful in the Directory Server context. For example, sending a user password reset email, or updating the user information. This api works slightly differently than other similar APIs. There are multi-leveled calls where Synology makes requests on behalf of the original request and relays information back. Additionally, the query-string api item is not used often in this class as API is defined within the actual request. The APIs in this class are tested working against the following scenarios: + - Getters: - Get Active Directory information - List objects within a Base DN on the Active Directory Server @@ -36,43 +39,44 @@ class DirectoryServer(base_api.BaseApi): """ def get_directory_info(self) -> dict[str, object]: - """Gets directory info. - - Returns - ------- - dict[str, object] - Information about your domain. - - Examples - -------- - ```json - { + """ + Get directory info. + + Returns + ------- + dict[str, object] + Information about your domain. + + Examples + -------- + ```json + { + "data": { "data": { - "data": { - "domainBasicInfo": { - "realm": "MY.DOMAIN.COM", - "workgroup": "NETBIOSNAME" - }, - "domainControllers": [ - { - "cn": "AD", - "dn": "CN=AD,OU=Domain Controllers,DC=MY,DC=DOMAIN,DC=COM", - "dnshostname": "AD.MY.DOMAIN.COM", - "roles": [ - "pdc", - "rid", - "schema", - "naming", - "infrastructure" - ] - } + "domainBasicInfo": { + "realm": "MY.DOMAIN.COM", + "workgroup": "NETBIOSNAME" + }, + "domainControllers": [ + { + "cn": "AD", + "dn": "CN=AD,OU=Domain Controllers,DC=MY,DC=DOMAIN,DC=COM", + "dnshostname": "AD.MY.DOMAIN.COM", + "roles": [ + "pdc", + "rid", + "schema", + "naming", + "infrastructure" ] - }, - "status": "running" + } + ] }, - "success": true - } - ``` + "status": "running" + }, + "success": true + } + ``` """ api_name = 'SYNO.ActiveDirectory.Info' info = {'maxVersion': 3, 'minVersion': 1, @@ -89,68 +93,61 @@ def list_directory_objects(self, objectCategory: list[str] = [ "person", "group", "organizationalUnit", "computer", "container", "builtinDomain"] ) -> dict[str, object]: - """lists directory objects. - - Parameters - ---------- - basedn : str - The Base DN for the search. eg. `CN=Users,CN=MY,CN=DOMAIN,CN=COM" or CN=MY,CN=DOMAIN,CN=COM` - - offset : int, optional - When searching large data, you may wish to start at a certain number, e.g. for 10 at a time one - would set the limit to 10 and the offset by multiples of 10 for each request. - Defaults to `0` - - limit : int, optional - The numeric the number of maximum objects to return. - Defaults to `40` - - objectCategory : optional, list[str] - The categories of items to search. e.g. `["organizationalUnit","container","builtinDomain"]` for a list of - base server containers, and `["person","group","organizationalUnit","computer"]` for a list of contained objects. - Defaults to `["person","group","organizationalUnit","computer","container","builtinDomain"]` - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "data": [ - { - "accountExpiryTime": 910692730085, - "deletable": true, - "description": "This is a description of a user person", - "disabled": false, - "displayName": "John Doe", - "dn": "CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM", - "locked": false, - "mail": "jdoe@MY.EMAIL.COM", - "movable": true, - "name": "john", - "objectCategory": "person", - "passwordExpired": true, - "physicalDeliveryOfficeName": "official office of officers", - "primaryGroupToken": 0, - "renamable": true, - "sAMAccountName": "jdoe", - "showInAdvancedViewOnly": false, - "telephoneNumber": "123-444-5677" - }, - ], - "total": 99999 + """ + List directory objects. + + Parameters + ---------- + basedn : str + The Base DN for the search. E.g. `CN=Users,CN=MY,CN=DOMAIN,CN=COM` or `CN=MY,CN=DOMAIN,CN=COM`. + offset : int, optional + When searching large data, you may wish to start at a certain number, e.g. for 10 at a time one + would set the limit to 10 and the offset by multiples of 10 for each request. Defaults to `0`. + limit : int, optional + The number of maximum objects to return. Defaults to `40`. + objectCategory : list[str], optional + The categories of items to search. E.g. `["organizationalUnit","container","builtinDomain"]` for a list of + base server containers, and `["person","group","organizationalUnit","computer"]` for a list of contained objects. + Defaults to `["person","group","organizationalUnit","computer","container","builtinDomain"]`. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. The first level is the success to the AD server. The second Data level is the status of the actual request. + Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. + + Examples + -------- + ```json + { + "data": { + "data": [ + { + "accountExpiryTime": 910692730085, + "deletable": true, + "description": "This is a description of a user person", + "disabled": false, + "displayName": "John Doe", + "dn": "CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM", + "locked": false, + "mail": "jdoe@MY.EMAIL.COM", + "movable": true, + "name": "john", + "objectCategory": "person", + "passwordExpired": true, + "physicalDeliveryOfficeName": "official office of officers", + "primaryGroupToken": 0, + "renamable": true, + "sAMAccountName": "jdoe", + "showInAdvancedViewOnly": false, + "telephoneNumber": "123-444-5677" }, - "success": true - } - ``` + ], + "total": 99999 + }, + "success": true + } + ``` """ action = '"enum"' scope = '"one"' @@ -176,60 +173,51 @@ def create_new_user( change_password_next_logon: str = 'null', password_never_expire: str = 'true' ) -> dict[str, object]: - """Create a new user. - - Note: The user can be created in AD, but not able to log on until the next synchronization occurs. - - Note: Please note that synchronization with Synology is a separate step. - - Parameters - ---------- - logon_name : str - The desired username. E.g `jdoe`. - - email: str - The desired email. - - password : str - The plain-text password for the new user. E.g `Password123`. - - located_dn : str - The DN for the user. E.g `CN=Users,CN=MY,CN=DOMAIN,CN=COM`. - - description : str, optional - A description for the user. - - account_is_disabled : str - Set to 'true' if the account should be disabled Defaults to `False`. - - cannot_change_password : str, optional - Set to 'true' if the user cannot change the password Defaults to `False`. - - change_password_next_logon : str, optional - Set to 'true' if the user must change password on next logon Defaults to `False`. - - cannot_change_password : str, optional - Set to 'true' if the user cannot change the password Defaults to `False`. - - password_never_expire: str - Pwd Never Expire - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. The data dictionary contains an 'error', or it contains a 'dn' and a 'name'. - - Examples - -------- - ```json - { - 'data': { - 'dn': 'CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM', - 'name': 'NETBIOSNAME\\ababab' - }, - 'success': true - } - ``` + """ + Create a new user. + + Parameters + ---------- + logon_name : str + The desired username. E.g. `jdoe`. + email : str + The desired email. + password : str + The plain-text password for the new user. E.g. `Password123`. + located_dn : str + The DN for the user. E.g. `CN=Users,CN=MY,CN=DOMAIN,CN=COM`. + description : str, optional + A description for the user. + account_is_disabled : str + Set to 'true' if the account should be disabled. Defaults to `False`. + cannot_change_password : str, optional + Set to 'true' if the user cannot change the password. Defaults to `False`. + change_password_next_logon : str, optional + Set to 'true' if the user must change password on next logon. Defaults to `False`. + password_never_expire : str + Set to 'true' if the password never expires. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + + Notes + ----- + The user can be created in AD, but not able to log on until the next synchronization occurs. + Please note that synchronization with Synology is a separate step. + + Examples + -------- + ```json + { + 'data': { + 'dn': 'CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM', + 'name': 'NETBIOSNAME\\ababab' + }, + 'success': true + } + ``` """ api_name = "SYNO.ActiveDirectory.User" @@ -245,33 +233,36 @@ def create_new_user( def reset_password(self, username: str, ) -> dict[str, object]: - """Send a password reset email. - - This will trigger the password reset email from - Control Panel>Notification>Rules>System>Reset password for your account to be sent to the user. - - Info: In order to use this, Control Panel>User & Group>Advanced>"Allow non-administrator users to reset forgotten passwords via email" must be enabled. - - Parameters - ---------- - username : str - The username to reset. E.g. `My Group` - - Returns - ------- - dict[str, object] - The return object can be checked for the "success" to be a true or false. - - Examples - -------- - ```json - { - "data": { - "msg": 3 - }, - "success": true - } - ``` + """ + Send a password reset email. + + This will trigger the password reset email from + Control Panel>Notification>Rules>System>Reset password for your account to be sent to the user. + + Parameters + ---------- + username : str + The username to reset. E.g. `My Group`. + + Returns + ------- + dict[str, object] + The return object can be checked for the "success" to be a true or false. + + Notes + ----- + In order to use this, Control Panel>User & Group>Advanced>"Allow non-administrator users to reset forgotten passwords via email" must be enabled. + + Examples + -------- + ```json + { + "data": { + "msg": 3 + }, + "success": true + } + ``` """ api_name = 'SYNO.Auth.ForgotPwd' @@ -284,52 +275,49 @@ def reset_password(self, return self.request_data(api_name, api_path, req_param) def change_user_password(self, user_dn: str, password: str) -> dict[str, object]: - """Change the user's password. - - Info: This is a compound dual-level request where the synology API proxies your request to the Directory Server. - - Parameters - ---------- - user_dn: str - The user DN to be modified. eg. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM` - - password: str - The new password to be set. e.g. `Password123` - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "has_fail": false, - "result": [ + """ + Change the user's password. + + Parameters + ---------- + user_dn : str + The user DN to be modified. E.g. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM`. + password : str + The new password to be set. E.g. `Password123`. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + + Notes + ----- + This is a compound dual-level request where the synology API proxies your request to the Directory Server. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.ActiveDirectory.User", + "data": [ { - "api": "SYNO.ActiveDirectory.User", - "data": [ - { - "code": 0, - "msg": "update record successfully" - } - ], - "method": "set", - "success": true, - "version": 2 + "code": 0, + "msg": "update record successfully" } - ] - }, - "success": true - } - ``` - + ], + "method": "set", + "success": true, + "version": 2 + } + ] + }, + "success": true + } + ``` """ api_name = "SYNO.Entry.Request" info = {'maxVersion': 1, 'minVersion': 1, @@ -350,38 +338,30 @@ def create_new_group( type: Optional[str] = 'security', scope: Optional[str] = 'global' ) -> dict[str, object]: - """Create a new AD group. - - Parameters - ---------- - name : str - The name of the group. E.g. `My Group` - - located_dn : str - - The DN to place the group in. eg. `CN=Groups,DC=MY,DC=DOMAIN,DC=COM` - email : str, optional - The email address used to reference this group. - Defaults to `""` - - description : str, optional - A description of the AD Group. - Defaults to `""` - - type : str, optional - Example Options: `security`, `distribution` - - (definitions from https://docs.microsoft.com/en-us/microsoft-365/admin/create-groups/compare-groups?view=o365-worldwide ) - - `distribution` (Distribution groups) are used for sending email + """ + Create a new AD group. + + Parameters + ---------- + name : str + The name of the group. E.g. `My Group`. + located_dn : str + The DN to place the group in. E.g. `CN=Groups,DC=MY,DC=DOMAIN,DC=COM`. + email : str, optional + The email address used to reference this group. Defaults to `""`. + description : str, optional + A description of the AD Group. Defaults to `""`. + type : str, optional + Example Options: `security`, `distribution`. Defaults to `"security"`. + + (definitions from https://docs.microsoft.com/en-us/microsoft-365/admin/create-groups/compare-groups?view=o365-worldwide ) + - `distribution` (Distribution groups) are used for sending email notifications to a group of people. - - `security` - Security groups are used for granting access to resources + - `security` - Security groups are used for granting access to resources such as SharePoint sites. - Defaults to `"security"` - - scope : str, optional - Example Options : `local`, `global`, `universal` - + scope : str, optional + Example Options: `local`, `global`, `universal`. Defaults to `"global"`. (Definitions from https://www.netwrix.com/active_directory_group_management.html ) - `local` (Domain Local Groups) should be used to manage permissions to @@ -404,24 +384,22 @@ def create_new_group( is stored in the Global Catalog and replicated forest-wide. Don’t use universal groups if you have only one domain. - Defaults to `"global"` - - Returns - ------- - dict[str, object] - A success object, and data object containing the new dn and the netbios name of the group. - - Examples - -------- - ```json - { - 'data': { - 'dn': 'CN=My Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM', - 'name': 'NETBIOSNAME\\My Group' - }, - 'success': true - } - ``` + Returns + ------- + dict[str, object] + A success object, and data object containing the new dn and the netbios name of the group. + + Examples + -------- + ```json + { + 'data': { + 'dn': 'CN=My Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM', + 'name': 'NETBIOSNAME\\My Group' + }, + 'success': true + } + ``` """ api_name = 'SYNO.ActiveDirectory.Group' info = {'maxVersion': 1, 'minVersion': 1, @@ -432,50 +410,47 @@ def create_new_group( return self.request_data(api_name, api_path, req_param) def add_user_to_group(self, userDn: str, groupDn: str) -> dict[str, object]: - """Adds a user as a member of a group. - - Parameters - ---------- - userDn : str - The fully qualified dn to add. eg. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM` - - groupDn : str - the fully qualified dn of the group to which the user is to be added. e.g. `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM` - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.ActiveDirectory.Group.Member", - "data": { - "members": [ - "CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM" - ] - }, - "method": "add", - "success": true, - "version": 1 - } + """ + Add a user as a member of a group. + + Parameters + ---------- + userDn : str + The fully qualified dn to add. E.g. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM`. + groupDn : str + The fully qualified dn of the group to which the user is to be added. E.g. `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM`. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + The first level is the success to the AD server. The second Data level is the status of the actual request. + Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.ActiveDirectory.Group.Member", + "data": { + "members": [ + "CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM" ] - }, - "success": true - } - ``` + }, + "method": "add", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` """ - api_name = 'SYNO.Entry.Request' compound = '[{"api":"SYNO.ActiveDirectory.Group.Member","method":"add","version":"1","dn":"' + \ groupDn+'","members":["'+userDn+'"]}]' @@ -491,23 +466,24 @@ def add_user_to_group(self, userDn: str, groupDn: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def does_dn_exist(self, groupName: str) -> dict[str, object]: - """Checks if a container exists. This can be used to verifiy the username or group name is unique. - - Info: This will not check the container, only if a similarly named container already exists. - - Parameters - ---------- - groupName : str - The user, or group's name. e.g. `jdoe` or `My Cool Group` - - Fully Qualified Domain Name such as `CN=My Cool Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM` are not successful. - - Improper case such as `my cool group` instead of `My Cool Group` are successful - - Returns - ------- - dict[str, object] - `True` if the group exists. `False` if the group does not exist + """ + Check if a container exists. This can be used to verify the username or group name is unique. + + Parameters + ---------- + groupName : str + The user, or group's name. E.g. `jdoe` or `My Cool Group`. + Fully Qualified Domain Name such as `CN=My Cool Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM` are not successful. + Improper case such as `my cool group` instead of `My Cool Group` are successful. + + Returns + ------- + dict[str, object] + `True` if the group exists. `False` if the group does not exist. + + Notes + ----- + This will not check the container, only if a similarly named container already exists. """ api_name = 'SYNO.ActiveDirectory.Group' @@ -529,75 +505,67 @@ def modify_user_info(self, telephoneNumber: str = None, web: str = None ) -> dict[str, object]: - """Performs modification to user information within the Active Directory. - - Parameters - ---------- - user_dn : str - The user DN to be modified. eg. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM` - - firstName : str, optional - The First name of the user. e.g. `John` - - lastName : str, optional - The Last Name of the user. e.g. `Doe` - - displayName : str, optional - The Display name of the user. e.g. `John Doe` - - description : str, optional - The Descrition of the user. e.g. `The guy who just came in` - - initials : str, optional - The Initials of the user. e.g. `JD` - - physicalDeliveryOfficeName : str, optional - The office location in the user's place of business - - telephoneNumber : str, optional - The user's telephone number. - - web : str, optional - The user's website or location on the web where information can be obtained. - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "has_fail": true, - "result": [ - { - "api": "SYNO.ActiveDirectory.User", - "error": { - "code": 10104, - "errors": [ - { - "code": 10237, - "msg": "ldb updaterecords: modify" - } - ] - }, - "method": "set", - "success": false, - "version": 2 - } + """ + Modify user information within the Active Directory. + + Parameters + ---------- + user_dn : str, optional + The user DN to be modified. E.g. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM`. + firstName : str, optional + The First name of the user. E.g. `John`. + lastName : str, optional + The Last Name of the user. E.g. `Doe`. + displayName : str, optional + The Display name of the user. E.g. `John Doe`. + description : str, optional + The Description of the user. E.g. `The guy who just came in`. + initials : str, optional + The Initials of the user. E.g. `JD`. + physicalDeliveryOfficeName : str, optional + The office location in the user's place of business. + telephoneNumber : str, optional + The user's telephone number. + web : str, optional + The user's website or location on the web where information can be obtained. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + The first level is the success to the AD server. The second Data level is the status of the actual request. + Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. + + Examples + -------- + ```json + { + "data": { + "has_fail": true, + "result": [ + { + "api": "SYNO.ActiveDirectory.User", + "error": { + "code": 10104, + "errors": [ + { + "code": 10237, + "msg": "ldb updaterecords: modify" + } ] - }, - "success": true - } - ``` + }, + "method": "set", + "success": false, + "version": 2 + } + ] + }, + "success": true + } + ``` """ class Person: + """Represents a user object for Active Directory modifications.""" firstName lastName displayName @@ -633,58 +601,54 @@ class Person: return val def setEntryRequest(self, modificationAPI: str, method: str, nameOfObject: str, jsonObject: Any) -> dict[str, object]: - """Performs modification to an object within the Active Directory. - - Parameters - ---------- - modificationAPI : str - API to be used - - method : str - Method to be called - - nameOfObject : str - The user DN to be modified. eg. `"CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM"` - - jsonObject : str - The json Object to be added, eg, a user object where the - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "has_fail": true, - "result": [ - { - "api": "SYNO.ActiveDirectory.User", - "error": { - "code": 10104, - "errors": [ - { - "code": 10237, - "msg": "ldb updaterecords: modify" - } - ] - }, - "method": "set", - "success": false, - "version": 2 - } + """ + Modify an object within the Active Directory. + + Parameters + ---------- + modificationAPI : str + API to be used. + method : str + Method to be called. + nameOfObject : str + The user DN to be modified. E.g. `"CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM"`. + jsonObject : str + The json Object to be added, e.g., a user object. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + The first level is the success to the AD server. The second Data level is the status of the actual request. + Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. + + Examples + -------- + ```json + { + "data": { + "has_fail": true, + "result": [ + { + "api": "SYNO.ActiveDirectory.User", + "error": { + "code": 10104, + "errors": [ + { + "code": 10237, + "msg": "ldb updaterecords: modify" + } ] - }, - "success": true - } - ``` + }, + "method": "set", + "success": false, + "version": 2 + } + ] + }, + "success": true + } + ``` """ compound = [{"api": modificationAPI, "method": method, "version": 2, nameOfObject: [jsonObject]}] @@ -698,39 +662,38 @@ def setEntryRequest(self, modificationAPI: str, method: str, nameOfObject: str, return self.request_data(api_name, api_path, req_param, "post") def update_domain_records(self) -> dict[str, object]: - """Updates the Synology users and groups database with information from Directory Server. + """ + Update the Synology users and groups database with information from Directory Server. - This is a long-running and asynchronous task. You are given back a task_id, and you can use that task_id to check the status with the get_task_status(task_id) method. + This is a long-running and asynchronous task. You are given back a task_id, and you can use that task_id to check the status with the get_task_status(task_id) method. - Returns - ------- - dict[str, object] - The 'data' object contains the 'task_id' used to track with the getTaskStatus() method. + Returns + ------- + dict[str, object] + The 'data' object contains the 'task_id' used to track with the getTaskStatus() method. - The 'success' object will be true if the operation was successful. or false if failed. + Notes + ----- + Typical utilization of Update Domain requires starting the update job and waiting for + completion. Waiting involves using the getTaskStatus and can be accomplished via a busy-wait method such as the following: - Examples - -------- - ```json - { - "data": { - "task_id": "@administrators/DomainUpdate6146195136397F2" - }, - "success": true - } + ```python + updateResponse=directory.updateDomain() + status = directory.getTaskStatus(updateResponse['data']['task_id']) + while status['data']['status'] == 'updating': + status=directory.getTaskStatus(updateResponse['data']['task_id']) ``` - Note - ---- - Typical utilization of Update Domain requires starting the update job and waiting for - completion. Waiting involves using the getTaskStatus and can be accomplished via a busy-wait method such as the following: - - ```python - updateResponse=directory.updateDomain() - status = directory.getTaskStatus(updateResponse['data']['task_id']) - while status['data']['status'] == 'updating': - status=directory.getTaskStatus(updateResponse['data']['task_id']) - ``` + Examples + -------- + ```json + { + "data": { + "task_id": "@administrators/DomainUpdate6146195136397F2" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Directory.Domain' info = self.core_list[api_name] @@ -740,34 +703,34 @@ def update_domain_records(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_task_status(self, task_id: str) -> dict[str, object]: - """Gets the current status of a task running on the Directory Domain object. - - This is used to ensure the task is completed. For example, the primary utilization of this is when updating Synology's internal Domain user and group list. - - Until this method reports finish, the job is not completed, and it is not safe to operate under the assumption that users have been synchronized. - - Parameters - ---------- - task_id : str - The task ID to be tracked for status. - - Returns - ------- - dict[str, object] - The 'data' object contains the 'status' used to determine the current status. 'status' will be 'updating' or 'finish' if the job was started. - T - The 'success' object will be true if the operation was successful. or false if failed. - - Examples - -------- - ```json - { - 'data': { - 'status': 'updating' - }, - 'success': true - } - ``` + """ + Get the current status of a task running on the Directory Domain object. + + This is used to ensure the task is completed. For example, the primary utilization of this is when updating Synology's internal Domain user and group list. + + Until this method reports finish, the job is not completed, and it is not safe to operate under the assumption that users have been synchronized. + + Parameters + ---------- + task_id : str + The task ID to be tracked for status. + + Returns + ------- + dict[str, object] + The 'data' object contains the 'status' used to determine the current status. 'status' will be 'updating' or 'finish' if the job was started. + The 'success' object will be true if the operation was successful, or false if failed. + + Examples + -------- + ```json + { + 'data': { + 'status': 'updating' + }, + 'success': true + } + ``` """ api_name = 'SYNO.Core.Directory.Domain' @@ -778,51 +741,49 @@ def get_task_status(self, task_id: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def deleteItems(self, dnList: list[str]) -> dict[str, object]: - """Deletes an array of DNs from AD. - - Parameters - ---------- - dnList : list[str] - The fully qualified DN to be removed from the directory server. - eg. `["CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM","CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM"]` - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.ActiveDirectory.Polling", - "data": { - "data": [ - { - "dn": "CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM", - "status": {} - } - ], - "finished": true, - "total": 1 - }, - "method": "get", - "success": true, - "version": 1 - } - ] - }, - "success": true - } - ``` + """ + Delete an array of DNs from AD. + + Parameters + ---------- + dnList : list[str] + The fully qualified DN to be removed from the directory server. E.g. `["CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM","CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM"]`. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + The first level is the success to the AD server. The second Data level is the status of the actual request. + Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.ActiveDirectory.Polling", + "data": { + "data": [ + { + "dn": "CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM", + "status": {} + } + ], + "finished": true, + "total": 1 + }, + "method": "get", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.ActiveDirectory.Directory' info = {'maxVersion': 2, 'minVersion': 1, @@ -846,68 +807,71 @@ def deleteItems(self, dnList: list[str]) -> dict[str, object]: return returnValue def delete_item(self, dn: str) -> dict[str, object]: - """Deletes a DN from AD. - - Parameters - ---------- - dn : str - The fully qualified DN to be removed from the directory server. - eg. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM` or `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM` - - Returns - ------- - dict[str, object] - The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. - - The first level is the success to the AD server. The second Data level is the status of the actual request. - - Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. - - Examples - -------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.ActiveDirectory.Polling", - "data": { - "data": [ - { - "dn": "CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM", - "status": {} - } - ], - "finished": true, - "total": 1 - }, - "method": "get", - "success": true, - "version": 1 - } - ] - }, - "success": true - } - ``` + """ + Delete a DN from AD. + + Parameters + ---------- + dn : str + The fully qualified DN to be removed from the directory server. E.g. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM` or `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM`. + + Returns + ------- + dict[str, object] + The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. + The first level is the success to the AD server. The second Data level is the status of the actual request. + Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.ActiveDirectory.Polling", + "data": { + "data": [ + { + "dn": "CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM", + "status": {} + } + ], + "finished": true, + "total": 1 + }, + "method": "get", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` """ items = [] items.append(dn) return self.deleteItems(items) def entryRequest(self, task_id: str) -> Any: - """Some requests require an entry. + """ + Perform an entry request for a task. - Delete for example requires an entry. If an entry is required, the task will not complete without an Entry Request. + Some requests require an entry. Delete, for example, requires an entry. If an entry is required, the task will not complete without an Entry Request. - Parameters - ---------- - task_id: str - The ID of the task to be checked. This is provided when making a request. + Parameters + ---------- + task_id : str + The ID of the task to be checked. This is provided when making a request. + An example Task ID may look like this + `@administrators/Synoads_SYNO.ActiveDirectory.Directory_delete6145EA17C4F03DA9`. - An example Task ID may look like this - `@administrators/Synoads_SYNO.ActiveDirectory.Directory_delete6145EA17C4F03DA9` + Returns + ------- + Any + The result of the entry request. """ api_name = 'SYNO.Entry.Request' info = {'maxVersion': 1, 'minVersion': 1, From 5020359c133d4d75167e25bfb128d14b1fceeb58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:36:31 +0700 Subject: [PATCH 026/126] fix: directory_server.py add import for time module --- synology_api/directory_server.py | 1 + 1 file changed, 1 insertion(+) diff --git a/synology_api/directory_server.py b/synology_api/directory_server.py index 036500f0..75379cd0 100644 --- a/synology_api/directory_server.py +++ b/synology_api/directory_server.py @@ -2,6 +2,7 @@ from __future__ import annotations import json +import time from typing import Optional, Any from . import base_api From 91c6c17295a7f51763de43b6dabee0d2a5f7fdad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:46:57 +0700 Subject: [PATCH 027/126] fix: synology_api/docker_api.py update docstrings to comply with Numpydoc standards --- synology_api/docker_api.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/synology_api/docker_api.py b/synology_api/docker_api.py index 245fb11e..1db870c6 100644 --- a/synology_api/docker_api.py +++ b/synology_api/docker_api.py @@ -1,6 +1,4 @@ -""" -Docker API implementation for Synology NAS. -""" +"""Docker API implementation for Synology NAS.""" from __future__ import annotations from typing import Optional import json @@ -29,7 +27,6 @@ class Docker(base_api.BaseApi): - Get list of docker networks - Setters: - - - Actions: - Export container profile From 439a5994c16ab72c541e3531a4104571a2f4472e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:50:38 +0700 Subject: [PATCH 028/126] fix: synology_api/downloadstation.py update docstrings to comply with Numpydoc standards --- synology_api/downloadstation.py | 431 +++++++++++++++++++++++++++++++- 1 file changed, 430 insertions(+), 1 deletion(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index ce30c1e8..6d56e20e 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -1,9 +1,97 @@ +""" +Synology Download Station API wrapper. + +This module provides a Python interface for managing downloads, tasks, RSS feeds, and BT searches +on Synology NAS devices using the Download Station application. +""" + from __future__ import annotations from typing import Optional, Any from . import base_api class DownloadStation(base_api.BaseApi): + """ + Core Download Station API implementation for Synology NAS. + + This class provides methods to manage downloads, tasks, RSS feeds, and BT searches. + + Parameters + ---------- + ip_address : str + IP address or hostname of the Synology NAS. + port : str + Port number to connect to. + username : str + Username for authentication. + password : str + Password for authentication. + secure : bool, optional + Use HTTPS if True, HTTP if False (default is False). + cert_verify : bool, optional + Verify SSL certificates (default is False). + dsm_version : int, optional + DSM version (default is 7). + debug : bool, optional + Enable debug output (default is True). + otp_code : Optional[str], optional + One-time password for 2FA (default is None). + device_id : Optional[str], optional + Device ID (default is None). + device_name : Optional[str], optional + Device name (default is None). + interactive_output : bool, optional + Enable interactive output (default is True). + download_st_version : int, optional + Download Station API version (default is None). + + Methods + ------- + get_info() + Get Download Station info. + get_config() + Get Download Station config. + set_server_config(...) + Set Download Station server config. + schedule_info() + Get schedule info. + schedule_set_config(...) + Set schedule config. + tasks_list(...) + List download tasks. + tasks_info(...) + Get info for specific tasks. + tasks_source(...) + Download task source. + create_task(...) + Create a new download task. + delete_task(...) + Delete a download task. + pause_task(...) + Pause a download task. + resume_task(...) + Resume a download task. + edit_task(...) + Edit a download task. + get_statistic_info() + Get Download Station statistics. + get_rss_info_list(...) + Get RSS site info list. + refresh_rss_site(...) + Refresh RSS site. + rss_feed_list(...) + Get RSS feed list. + start_bt_search(...) + Start a BT search. + get_bt_search_results(...) + Get BT search results. + get_bt_search_category() + Get BT search categories. + clean_bt_search(...) + Clean BT search tasks. + get_bt_module() + Get BT search modules. + """ def __init__(self, ip_address: str, @@ -20,6 +108,38 @@ def __init__(self, interactive_output: bool = True, download_st_version: int = None ) -> None: + """ + Initialize the DownloadStation API wrapper. + + Parameters + ---------- + ip_address : str + IP address or hostname of the Synology NAS. + port : str + Port number to connect to. + username : str + Username for authentication. + password : str + Password for authentication. + secure : bool, optional + Use HTTPS if True, HTTP if False (default is False). + cert_verify : bool, optional + Verify SSL certificates (default is False). + dsm_version : int, optional + DSM version (default is 7). + debug : bool, optional + Enable debug output (default is True). + otp_code : Optional[str], optional + One-time password for 2FA (default is None). + device_id : Optional[str], optional + Device ID (default is None). + device_name : Optional[str], optional + Device name (default is None). + interactive_output : bool, optional + Enable interactive output (default is True). + download_st_version : int, optional + Download Station API version (default is None). + """ super(DownloadStation, self).__init__(ip_address, port, username, password, secure, cert_verify, dsm_version, debug, otp_code, device_id, device_name, 'DownloadStation') @@ -38,6 +158,14 @@ def __init__(self, self.download_st_version = '' def get_info(self) -> dict[str, object] | str: + """ + Get Download Station info. + + Returns + ------- + dict[str, object] or str + Download Station info. + """ api_name = 'SYNO.DownloadStation.Info' info = self.download_list[api_name] api_path = info['path'] @@ -46,6 +174,14 @@ def get_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_config(self) -> dict[str, object] | str: + """ + Get Download Station config. + + Returns + ------- + dict[str, object] or str + Download Station config. + """ api_name = 'SYNO.DownloadStation.Info' info = self.download_list[api_name] api_path = info['path'] @@ -66,7 +202,39 @@ def set_server_config(self, default_destination: Optional[str] = None, emule_default_destination: Optional[str] = None ) -> dict[str, object] | str: - + """ + Set Download Station server configuration. + + Parameters + ---------- + bt_max_download : Optional[int], optional + Maximum BT download speed. + bt_max_upload : Optional[int], optional + Maximum BT upload speed. + emule_max_download : Optional[int], optional + Maximum eMule download speed. + emule_max_upload : Optional[int], optional + Maximum eMule upload speed. + nzb_max_download : Optional[int], optional + Maximum NZB download speed. + http_max_download : Optional[int], optional + Maximum HTTP download speed. + ftp_max_download : Optional[int], optional + Maximum FTP download speed. + emule_enabled : Optional[bool], optional + Enable eMule. + unzip_service_enabled : Optional[bool], optional + Enable unzip service. + default_destination : Optional[str], optional + Default download destination. + emule_default_destination : Optional[str], optional + Default eMule download destination. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation.Info' info = self.download_list[api_name] api_path = info['path'] @@ -81,6 +249,14 @@ def set_server_config(self, return self.request_data(api_name, api_path, req_param) def schedule_info(self) -> dict[str, object] | str: + """ + Get Download Station schedule configuration. + + Returns + ------- + dict[str, object] or str + Schedule configuration. + """ api_name = 'SYNO.DownloadStation.Schedule' info = self.download_list[api_name] api_path = info['path'] @@ -89,6 +265,21 @@ def schedule_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def schedule_set_config(self, enabled: bool = False, emule_enabled: bool = False) -> dict[str, object] | str: + """ + Set Download Station schedule configuration. + + Parameters + ---------- + enabled : bool, optional + Enable schedule (default is False). + emule_enabled : bool, optional + Enable eMule schedule (default is False). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation.Schedule' info = self.download_list[api_name] api_path = info['path'] @@ -105,6 +296,23 @@ def tasks_list(self, offset: int = 0, limit: int = -1 ) -> dict[str, object] | str: + """ + List download tasks. + + Parameters + ---------- + additional_param : Optional[str or list[str]], optional + Additional fields to retrieve. + offset : int, optional + Offset for pagination (default is 0). + limit : int, optional + Maximum number of tasks to retrieve (default is -1). + + Returns + ------- + dict[str, object] or str + List of download tasks. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -121,6 +329,21 @@ def tasks_list(self, return self.request_data(api_name, api_path, req_param) def tasks_info(self, task_id, additional_param: Optional[str | list[str]] = None) -> dict[str, object] | str: + """ + Get information for specific download tasks. + + Parameters + ---------- + task_id : str or list[str] + Task ID(s). + additional_param : Optional[str or list[str]], optional + Additional fields to retrieve. + + Returns + ------- + dict[str, object] or str + Task information. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -140,6 +363,19 @@ def tasks_info(self, task_id, additional_param: Optional[str | list[str]] = None return self.request_data(api_name, api_path, req_param) def tasks_source(self, task_id) -> bytes: + """ + Download task source. + + Parameters + ---------- + task_id : str or list[str] + Task ID(s). + + Returns + ------- + bytes + Task source content. + """ # DownloadStation2 is required here api_name = 'SYNO.DownloadStation2.Task.Source' info = self.download_list[api_name] @@ -150,6 +386,21 @@ def tasks_source(self, task_id) -> bytes: return self.request_data(api_name, api_path, req_param, response_json=False).content def create_task(self, url, destination) -> dict[str, object] | str: + """ + Create a new download task. + + Parameters + ---------- + url : str + Download URL. + destination : str + Download destination. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -159,6 +410,21 @@ def create_task(self, url, destination) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def delete_task(self, task_id: str, force: bool = False) -> dict[str, object] | str: + """ + Delete a download task. + + Parameters + ---------- + task_id : str or list[str] + Task ID(s). + force : bool, optional + Force delete (default is False). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -171,6 +437,19 @@ def delete_task(self, task_id: str, force: bool = False) -> dict[str, object] | return self.request_data(api_name, api_path, param) def pause_task(self, task_id: str) -> dict[str, object] | str: + """ + Pause a download task. + + Parameters + ---------- + task_id : str or list[str] + Task ID(s). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -183,6 +462,19 @@ def pause_task(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, param) def resume_task(self, task_id: str) -> dict[str, object] | str: + """ + Resume a download task. + + Parameters + ---------- + task_id : str or list[str] + Task ID(s). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -195,6 +487,21 @@ def resume_task(self, task_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, param) def edit_task(self, task_id: str, destination: str = 'sharedfolder') -> dict[str, object] | str: + """ + Edit a download task. + + Parameters + ---------- + task_id : str or list[str] + Task ID(s). + destination : str, optional + New download destination (default is 'sharedfolder'). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] @@ -207,6 +514,14 @@ def edit_task(self, task_id: str, destination: str = 'sharedfolder') -> dict[str return self.request_data(api_name, api_path, param) def get_statistic_info(self) -> dict[str, object] | str: + """ + Get Download Station statistics. + + Returns + ------- + dict[str, object] or str + Statistics information. + """ api_name = 'SYNO.DownloadStation.Statistic' info = self.download_list[api_name] api_path = info['path'] @@ -215,6 +530,21 @@ def get_statistic_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, param) def get_rss_info_list(self, offset: Optional[int] = None, limit: Optional[int] = None) -> dict[str, object] | str: + """ + Get RSS site info list. + + Parameters + ---------- + offset : Optional[int], optional + Offset for pagination. + limit : Optional[int], optional + Maximum number of RSS sites to retrieve. + + Returns + ------- + dict[str, object] or str + RSS site info list. + """ api_name = 'SYNO.DownloadStation.RSS.Site' info = self.download_list[api_name] api_path = info['path'] @@ -228,6 +558,19 @@ def get_rss_info_list(self, offset: Optional[int] = None, limit: Optional[int] = return self.request_data(api_name, api_path, param) def refresh_rss_site(self, rss_id: Optional[str] = None) -> dict[str, object] | str: + """ + Refresh an RSS site. + + Parameters + ---------- + rss_id : Optional[str], optional + RSS site ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation.RSS.Site' info = self.download_list[api_name] api_path = info['path'] @@ -247,6 +590,23 @@ def rss_feed_list(self, offset: Optional[int] = None, limit: Optional[int] = None ) -> dict[str, object] | str: + """ + Get RSS feed list. + + Parameters + ---------- + rss_id : Optional[str], optional + RSS site ID. + offset : Optional[int], optional + Offset for pagination. + limit : Optional[int], optional + Maximum number of RSS feeds to retrieve. + + Returns + ------- + dict[str, object] or str + RSS feed list. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Feed' info = self.download_list[api_name] api_path = info['path'] @@ -266,6 +626,21 @@ def rss_feed_list(self, return self.request_data(api_name, api_path, param) def start_bt_search(self, keyword: Optional[str] = None, module: str = 'all') -> dict[str, object] | str: + """ + Start a BT search. + + Parameters + ---------- + keyword : Optional[str], optional + Search keyword. + module : str, optional + BT search module (default is 'all'). + + Returns + ------- + dict[str, object] or str + BT search task information or message. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.BTSearch' info = self.download_list[api_name] api_path = info['path'] @@ -302,6 +677,31 @@ def get_bt_search_results(self, filter_category: Optional[str] = None, filter_title: Optional[str] = None ) -> dict[str, object] | str: + """ + Get BT search results. + + Parameters + ---------- + taskid : Optional[str], optional + BT search task ID. + offset : Optional[int], optional + Offset for pagination. + limit : Optional[int], optional + Maximum number of results to retrieve. + sort_by : Optional[str], optional + Field to sort by. + sort_direction : Optional[str], optional + Sort direction. + filter_category : Optional[str], optional + Filter by category. + filter_title : Optional[str], optional + Filter by title. + + Returns + ------- + dict[str, object] or str + BT search results. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.BTSearch' info = self.download_list[api_name] api_path = info['path'] @@ -321,6 +721,14 @@ def get_bt_search_results(self, return self.request_data(api_name, api_path, param) def get_bt_search_category(self) -> dict[str, object] | str: + """ + Get BT search categories. + + Returns + ------- + dict[str, object] or str + BT search categories. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.BTSearch' info = self.download_list[api_name] api_path = info['path'] @@ -329,6 +737,19 @@ def get_bt_search_category(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, param) def clean_bt_search(self, taskid: Optional[str | list[str]] = None) -> dict[str, object] | str: + """ + Clean BT search tasks. + + Parameters + ---------- + taskid : Optional[str or list[str]], optional + BT search task ID(s). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.BTSearch' info = self.download_list[api_name] api_path = info['path'] @@ -347,6 +768,14 @@ def clean_bt_search(self, taskid: Optional[str | list[str]] = None) -> dict[str, return self.request_data(api_name, api_path, param) def get_bt_module(self) -> dict[str, object] | str: + """ + Get BT search modules. + + Returns + ------- + dict[str, object] or str + BT search modules. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.BTSearch' info = self.download_list[api_name] api_path = info['path'] From aec9ca24ef69c69e0d5a09c9fbc82451f56f2e5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:52:20 +0700 Subject: [PATCH 029/126] fix: synology_api/drive_admin_console.py update docstrings to comply with Numpydoc standards --- synology_api/drive_admin_console.py | 187 ++++++++++++++++++++++++++-- 1 file changed, 177 insertions(+), 10 deletions(-) diff --git a/synology_api/drive_admin_console.py b/synology_api/drive_admin_console.py index 298f68aa..6b6b7fa7 100644 --- a/synology_api/drive_admin_console.py +++ b/synology_api/drive_admin_console.py @@ -1,11 +1,32 @@ +""" +Synology Drive Admin Console API wrapper. + +This module provides a Python interface for managing Synology Drive Admin Console, +including status, configuration, connections, logs, shares, and settings. +""" + from __future__ import annotations from typing import Optional from . import base_api class AdminConsole(base_api.BaseApi): + """ + Synology Drive Admin Console API implementation. + + This class provides methods to retrieve and manage Synology Drive Admin Console status, + configuration, connections, logs, shares, and settings. + """ def status_info(self) -> dict[str, object] | str: + """ + Get Synology Drive status information. + + Returns + ------- + dict[str, object] or str + Status information. + """ api_name = 'SYNO.SynologyDrive' info = self.gen_list[api_name] api_path = info['path'] @@ -14,6 +35,14 @@ def status_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def config_info(self) -> dict[str, object] | str: + """ + Get Synology Drive configuration information. + + Returns + ------- + dict[str, object] or str + Configuration information. + """ api_name = 'SYNO.SynologyDrive.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -22,6 +51,14 @@ def config_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def connections(self) -> dict[str, object] | str: + """ + Get summary of Synology Drive connections. + + Returns + ------- + dict[str, object] or str + Connections summary. + """ api_name = 'SYNO.SynologyDrive.Connection' info = self.gen_list[api_name] api_path = info['path'] @@ -30,6 +67,14 @@ def connections(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def drive_check_user(self) -> dict[str, object] | str: + """ + Check user status in Synology Drive. + + Returns + ------- + dict[str, object] or str + User check result. + """ api_name = 'SYNO.SynologyDrive' info = self.gen_list[api_name] api_path = info['path'] @@ -38,6 +83,14 @@ def drive_check_user(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def active_connections(self) -> dict[str, object] | str: + """ + Get list of active Synology Drive connections. + + Returns + ------- + dict[str, object] or str + List of active connections. + """ api_name = 'SYNO.SynologyDrive.Connection' info = self.gen_list[api_name] api_path = info['path'] @@ -46,6 +99,14 @@ def active_connections(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def active_sync_connections(self) -> dict[str, object] | str: + """ + Get list of active Synology Drive ShareSync connections. + + Returns + ------- + dict[str, object] or str + List of active ShareSync connections. + """ api_name = 'SYNO.SynologyDriveShareSync.Connection' info = self.gen_list[api_name] api_path = info['path'] @@ -54,6 +115,14 @@ def active_sync_connections(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def share_active_list(self) -> dict[str, object] | str: + """ + Get list of active shares in Synology Drive. + + Returns + ------- + dict[str, object] or str + List of active shares. + """ api_name = 'SYNO.SynologyDrive.Share' info = self.gen_list[api_name] api_path = info['path'] @@ -61,16 +130,44 @@ def share_active_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) - def log(self, - share_type: str = 'all', - get_all: bool = False, - limit: int = 1000, - keyword: str = '', - date_from: int = 0, - date_to: int = 0, - username: str = '', - target: str = 'user' - ) -> dict[str, object] | str: + def log( + self, + share_type: str = 'all', + get_all: bool = False, + limit: int = 1000, + keyword: str = '', + date_from: int = 0, + date_to: int = 0, + username: str = '', + target: str = 'user' + ) -> dict[str, object] | str: + """ + Get Synology Drive logs. + + Parameters + ---------- + share_type : str, optional + Type of share to filter logs (default is 'all'). + get_all : bool, optional + Whether to get all logs (default is False). + limit : int, optional + Maximum number of logs to return (default is 1000). + keyword : str, optional + Keyword to filter logs (default is ''). + date_from : int, optional + Start date in epoch format (default is 0). + date_to : int, optional + End date in epoch format (default is 0). + username : str, optional + Username to filter logs (default is ''). + target : str, optional + Target type to filter logs (default is 'user'). + + Returns + ------- + dict[str, object] or str + Log information. + """ api_name = 'SYNO.SynologyDrive.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -89,6 +186,14 @@ def log(self, return self.request_data(api_name, api_path, req_param) def c2fs_share(self) -> dict[str, object] | str: + """ + Get list of C2FS shares. + + Returns + ------- + dict[str, object] or str + List of C2FS shares. + """ api_name = 'SYNO.C2FS.Share' info = self.gen_list[api_name] api_path = info['path'] @@ -97,6 +202,14 @@ def c2fs_share(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def settings(self) -> dict[str, object] | str: + """ + Get Synology Drive settings. + + Returns + ------- + dict[str, object] or str + Settings information. + """ api_name = 'SYNO.SynologyDrive.Settings' info = self.gen_list[api_name] api_path = info['path'] @@ -105,6 +218,14 @@ def settings(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def db_usage(self) -> dict[str, object] | str: + """ + Get Synology Drive database usage. + + Returns + ------- + dict[str, object] or str + Database usage information. + """ api_name = 'SYNO.SynologyDrive.DBUsage' info = self.gen_list[api_name] api_path = info['path'] @@ -113,6 +234,14 @@ def db_usage(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def delete_status(self) -> dict[str, object] | str: + """ + Get status of deleted nodes in Synology Drive. + + Returns + ------- + dict[str, object] or str + Delete status information. + """ api_name = 'SYNO.SynologyDrive.Node.Delete' info = self.gen_list[api_name] api_path = info['path'] @@ -121,6 +250,14 @@ def delete_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def file_property_transfer_status(self) -> dict[str, object] | str: + """ + Get file property transfer status for User Home migration. + + Returns + ------- + dict[str, object] or str + File property transfer status. + """ api_name = 'SYNO.SynologyDrive.Migration.UserHome' info = self.gen_list[api_name] api_path = info['path'] @@ -129,6 +266,23 @@ def file_property_transfer_status(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def user_sync_profile(self, user: str = '', start: int = 0, limit: str | int = 'null') -> dict[str, object] | str: + """ + Get user sync profile(s). + + Parameters + ---------- + user : str, optional + Username to filter profiles (default is ''). + start : int, optional + Start index for pagination (default is 0). + limit : str or int, optional + Maximum number of profiles to return (default is 'null'). + + Returns + ------- + dict[str, object] or str + User sync profile information. + """ api_name = 'SYNO.SynologyDrive.Profiles' info = self.gen_list[api_name] api_path = info['path'] @@ -138,6 +292,19 @@ def user_sync_profile(self, user: str = '', start: int = 0, limit: str | int = ' return self.request_data(api_name, api_path, req_param) def index_pause(self, time_pause: int = 60) -> dict[str, object] | str: + """ + Pause native client index for a specified duration. + + Parameters + ---------- + time_pause : int, optional + Pause duration in seconds (default is 60). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.SynologyDrive.Index' info = self.gen_list[api_name] api_path = info['path'] From 9491057c12930f669745def50876b8558e7b9962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Fri, 11 Jul 2025 21:55:57 +0700 Subject: [PATCH 030/126] fix: synology_api/error_codes.py update docstrings to comply with Numpydoc standards --- synology_api/error_codes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/synology_api/error_codes.py b/synology_api/error_codes.py index 551546f3..97e97552 100644 --- a/synology_api/error_codes.py +++ b/synology_api/error_codes.py @@ -1,3 +1,4 @@ +"""Synology API Error Codes.""" # source: pages 8 and 16 on PDF: # https://global.download.synology.com/download/Document/Software/DeveloperGuide/Os/DSM/All/enu/DSM_Login_Web_API_Guide_enu.pdf From c37dff60b955698eb60a11c6143afea07dd8ca11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:23:58 +0700 Subject: [PATCH 031/126] fix: synology_api/event_scheduler.py update docstrings to comply with Numpydoc standards --- synology_api/event_scheduler.py | 546 ++++++++++++++++---------------- 1 file changed, 278 insertions(+), 268 deletions(-) diff --git a/synology_api/event_scheduler.py b/synology_api/event_scheduler.py index 40cfd201..1e683fa9 100644 --- a/synology_api/event_scheduler.py +++ b/synology_api/event_scheduler.py @@ -1,3 +1,9 @@ +""" +Event Scheduler API module. + +This module provides the EventScheduler class for managing event-based tasks and power schedules +on Synology NAS devices via the SYNO.Core.EventScheduler API. +""" from __future__ import annotations from . import base_api from .core_sys_info import SysInfo @@ -6,26 +12,36 @@ class EventScheduler(base_api.BaseApi): - """Event Scheduler API implementation. - - This API provides functionality solely related to Event Tasks. For scheduled tasks, check `TaskScheduler`. - - Supported methods: - - Getters: - - Get task results - - Get result output - - Setters: - - Set task settings - - Set power schedule - - Actions: - - Enable task - - Disable task - - Run task - - Delete task - - Create task + """ + Event Scheduler API implementation. + + This API provides functionality solely related to Event Tasks. For scheduled tasks, check `TaskScheduler`. + + Methods + ------- + Getters: + - Get task results + - Get result output + Setters: + - Set task settings + - Set power schedule + Actions: + - Enable task + - Disable task + - Run task + - Delete task + - Create task """ def __get_root_token(self) -> str: + """ + Get the SynoConfirmPWToken for root operations. + + Returns + ------- + str + The SynoConfirmPWToken if successful, otherwise an empty string. + """ sys_info = SysInfo(ip_address=self.session._ip_address, port=self.session._port, username=self.session._username, password=self.session._password, secure=self.session._secure, cert_verify=self.session._verify, dsm_version=self.session._version, debug=self.session._debug, otp_code=self.session._otp_code, application=self.application) @@ -39,42 +55,43 @@ def get_task_results( self, task_name: str ) -> dict[str, object] | str: - """Retrieve the results list for a specific task. - - Parameters - ---------- - task_name : str - Name of the Event task to enable/disable. - - Returns - ------- - dict[str, object] - A dictionary containing the task results. - - Examples - -------- - ```json - { - "data": [ - { - "event_fire_time": "2024-09-13 03:17:47", - "exit_info": { - "exit_code": 0, - "exit_type": "stop" - }, - "extra": {}, - "pid": 16058, - "result_id": 115, - "run_time_env": {}, - "start_time": "2024-09-13 03:17:47", - "stop_time": "2024-09-13 03:17:47", - "task_name": "asd", - "trigger_event": "on_demand" - } - ], - "success": true - } - ``` + """ + Retrieve the results list for a specific task. + + Parameters + ---------- + task_name : str + Name of the Event task to enable/disable. + + Returns + ------- + dict[str, object] + A dictionary containing the task results. + + Examples + -------- + ```json + { + "data": [ + { + "event_fire_time": "2024-09-13 03:17:47", + "exit_info": { + "exit_code": 0, + "exit_type": "stop" + }, + "extra": {}, + "pid": 16058, + "result_id": 115, + "run_time_env": {}, + "start_time": "2024-09-13 03:17:47", + "stop_time": "2024-09-13 03:17:47", + "task_name": "asd", + "trigger_event": "on_demand" + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.EventScheduler' info = self.gen_list[api_name] @@ -92,32 +109,32 @@ def get_result_output( task_name: str, result_id: int ) -> dict[str, object] | str: - """Retrieve the output for a given result. - - Parameters - ---------- - task_name : str - Name of the Event task to enable/disable. - - result_id : int - ID of the result to retrieve. From get_task_results(). - - Returns - ------- - dict[str, object] - A dictionary containing the result output. - - Examples - -------- - ```json - { - "data": { - "script_in": "hello", - "script_out": "/volume3/datastore/scripts_output/asd/1726190267/script.log: line 1: hello: command not found\\n" - }, - "success": true - } - ``` + """ + Retrieve the output for a given result. + + Parameters + ---------- + task_name : str + Name of the Event task to enable/disable. + result_id : int + ID of the result to retrieve. From get_task_results(). + + Returns + ------- + dict[str, object] + A dictionary containing the result output. + + Examples + -------- + ```json + { + "data": { + "script_in": "hello", + "script_out": "/volume3/datastore/scripts_output/asd/1726190267/script.log: line 1: hello: command not found\\n" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.EventScheduler' info = self.gen_list[api_name] @@ -136,29 +153,28 @@ def task_set_enable( task_name: str, enable: bool ) -> dict[str, object] | str: - """Enable or disable Event task. - - Parameters - ---------- - task_name : str - Name of the Event task to enable/disable. - - enable (bool): - Wheter to enable (`True`) or disable (`False`) the task. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the action. - - Examples - -------- - ```json - { - "success": true - } - ``` - + """ + Enable or disable Event task. + + Parameters + ---------- + task_name : str + Name of the Event task to enable/disable. + enable : bool + Whether to enable (`True`) or disable (`False`) the task. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the action. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.EventScheduler' info = self.gen_list[api_name] @@ -176,25 +192,26 @@ def task_run( self, task_name: str ) -> dict[str, object] | str: - """Run a specific Event task. - - Parameters - ---------- - task_name : str - Name of the Event task to run. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the task execution. - - Examples - -------- - ```json - { - "success": true - } - ``` + """ + Run a specific Event task. + + Parameters + ---------- + task_name : str + Name of the Event task to run. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the task execution. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.EventScheduler' @@ -212,26 +229,26 @@ def task_delete( self, task_name: str ) -> dict[str, object] | str: - """Delete a specific Event task. - - Parameters - ---------- - task_name : str - Name of the Event task to run. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the task deletion. - - Examples - -------- - ```json - ---------- - { - "success": true - } - ``` + """ + Delete a specific Event task. + + Parameters + ---------- + task_name : str + Name of the Event task to run. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the task deletion. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.EventScheduler' @@ -257,61 +274,51 @@ def task_create_or_set( notify_email: str = '', notify_only_on_error: bool = False ) -> dict[str, object] | str: - """Create or modify an event-based task. - - Parameters - ---------- - action : str - Action to perform on the task. - - Possible values: - - `create` -> Creates a new task. - - `set` -> Modify an existing task. - - task_name : str - The name of the task. - - owner : dict[str, str] - Dictionary containing the owner's ID and name (e.g., `{"1026": "user1"}`). - - You can get the user UID by running `synouser --get your_user` in your NAS CLI. - - For root privileges, pass `{"0":"root"}`. - - trigger_event : str - The event that triggers the task. - - Possible values: - - `shutdown` - - `bootup` - - script : str - The script to be executed when the task is triggered. - - depend_on_task : list[str], optional - A list of event triggered task names that this task depends on (i.e., tasks that will be run before this one). Defaults to `[]`. - - enable : bool, optional - Whether to enable the task. Defaults to `True`. - - notify_email : str, optional - Email address to send notifications to. Defaults to `""`, thus disabling the notification feature. - - notify_only_on_error : bool, optional - If `True`, notifications are only sent when an error occurs. Defaults to `False`. - - Returns - ------- - dict[str, object] - A dictionary containing the result of the task creation or modification, or a strnig in case of an error. - - Examples - -------- - ```json - { - "success": true - } - ``` + """ + Create or modify an event-based task. + + Parameters + ---------- + action : str + Action to perform on the task. + + Possible values: + - `create` -> Create a new task. + - `set` -> Modify an existing task. + task_name : str + The name of the task. + owner : dict[str, str] + Dictionary containing the owner's ID and name (e.g., `{"1026": "user1"}`). + You can get the user UID by running `synouser --get your_user` in your NAS CLI. + For root privileges, pass `{"0":"root"}`. + trigger_event : str + The event that triggers the task. + Possible values: + - `shutdown` + - `bootup` + script : str + The script to be executed when the task is triggered. + depend_on_task : list[str], optional + A list of event triggered task names that this task depends on (i.e., tasks that will be run before this one). Defaults to `[]`. + enable : bool, optional + Whether to enable the task. Defaults to `True`. + notify_email : str, optional + Email address to send notifications to. Defaults to `""`, thus disabling the notification feature. + notify_only_on_error : bool, optional + If `True`, notifications are only sent when an error occurs. Defaults to `False`. + + Returns + ------- + dict[str, object] + A dictionary containing the result of the task creation or modification, or a string in case of an error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ if action != 'create' and action != 'set': return {'error': f'action <{action}> is not valid.'} @@ -348,55 +355,57 @@ def task_create_or_set( return self.request_data(api_name, api_path, req_param) def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: List[dict] = []) -> dict: - """Set the power schedule, poweron tasks and poweroff tasks - - Parameters - ---------- - poweron_tasks : List[dict], optional - List of tasks for power on. Defaults to `[]` - Example of a task: - ```python - { - "enabled": True, # Enable or not the task - "hour": 13, # Hour 0-23 - "min": 59, # Minutes 0-59 - "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) - } - ``` - poweroff_tasks : List[dict], optional - List of tasks for power off. Defaults to `[]` - Example of a task: - ```python - { - "enabled": True, # Enable or not the task - "hour": 13, # Hour 0-23 - "min": 59, # Minutes 0-59 - "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) - } - ``` - Returns - ------- - dict - List of tasks in power schedule - - Examples - -------- - ```json + """ + Set the power schedule, poweron tasks and poweroff tasks. + + Parameters + ---------- + poweron_tasks : List[dict], optional + List of tasks for power on. Defaults to `[]`. + Example of a task: + ```python { - "data": { - "poweroff_tasks": [], - "poweron_tasks": [ - { - "enabled": true, - "hour": 0, - "min": 0, - "weekdays": "1,2,3,4,5" - } - ] - }, - "success": true + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) } - ``` + ```. + poweroff_tasks : List[dict], optional + List of tasks for power off. Defaults to `[]`. + Example of a task: + ```python + { + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) + } + ```. + + Returns + ------- + dict + List of tasks in power schedule. + + Examples + -------- + ```json + { + "data": { + "poweroff_tasks": [], + "poweron_tasks": [ + { + "enabled": true, + "hour": 0, + "min": 0, + "weekdays": "1,2,3,4,5" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.PowerSchedule' @@ -412,31 +421,32 @@ def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: Lis return self.request_data(api_name, api_path, req_param) def load_power_schedule(self) -> dict: - """Load the power schedule, poweron tasks and poweroff tasks - - Returns - ------- - dict - List of tasks in power schedule - - Examples - -------- - ```json - { - "data": { - "poweroff_tasks": [], - "poweron_tasks": [ - { - "enabled": true, - "hour": 0, - "min": 0, - "weekdays": "1,2,3,4,5" - } - ] - }, - "success": true - } - ``` + """ + Load the power schedule, poweron tasks and poweroff tasks. + + Returns + ------- + dict + List of tasks in power schedule. + + Examples + -------- + ```json + { + "data": { + "poweroff_tasks": [], + "poweron_tasks": [ + { + "enabled": true, + "hour": 0, + "min": 0, + "weekdays": "1,2,3,4,5" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.PowerSchedule' From b7ab6678a8a85730e3cfee21f22ba765ccdf7382 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:30:46 +0700 Subject: [PATCH 032/126] fix: synology_api/exceptions.py update docstrings to comply with Numpydoc standards --- synology_api/exceptions.py | 685 +++++++++++++++++++++++++++++++++++-- 1 file changed, 649 insertions(+), 36 deletions(-) diff --git a/synology_api/exceptions.py b/synology_api/exceptions.py index aa12cd9a..5653dac2 100644 --- a/synology_api/exceptions.py +++ b/synology_api/exceptions.py @@ -1,12 +1,38 @@ +""" +Exception classes for Synology API. + +This module defines custom exception classes for handling errors and error codes +returned by various Synology API endpoints. +""" + from .error_codes import error_codes, auth_error_codes, download_station_error_codes, file_station_error_codes, core_error_codes from .error_codes import virtualization_error_codes # Base exception: class SynoBaseException(Exception): - """Base class for an exception. Defines error_message.""" + """ + Base class for an exception. Defines error_message. + + Parameters + ---------- + error_message : str + The error message describing the exception. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_message: str, *args: object) -> None: + """ + Initialize SynoBaseException. + + Parameters + ---------- + error_message : str + The error message describing the exception. + *args : object + Additional arguments to pass to the base Exception. + """ super().__init__(*args) self.error_message = error_message return @@ -14,34 +40,110 @@ def __init__(self, error_message: str, *args: object) -> None: # Classes to reraise Exceptions from requests. class SynoConnectionError(SynoBaseException): - """Class to raise when a connection error occurs.""" + """ + Exception raised when a connection error occurs. + + Parameters + ---------- + error_message : str + The error message describing the connection error. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_message: str, *args: object) -> None: + """ + Initialize SynoConnectionError. + + Parameters + ---------- + error_message : str + The error message describing the connection error. + *args : object + Additional arguments to pass to the base Exception. + """ super().__init__(error_message=error_message, *args) return class HTTPError(SynoBaseException): - """Class to raise when a http error occurs.""" + """ + Exception raised when an HTTP error occurs. + + Parameters + ---------- + error_message : str + The error message describing the HTTP error. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_message: str, *args: object) -> None: + """ + Initialize HTTPError. + + Parameters + ---------- + error_message : str + The error message describing the HTTP error. + *args : object + Additional arguments to pass to the base Exception. + """ super().__init__(error_message, *args) return class JSONDecodeError(SynoBaseException): - """Class to raise when server fails to send JSON.""" + """ + Exception raised when the server fails to send valid JSON. + + Parameters + ---------- + error_message : str + The error message describing the JSON decode error. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_message: str, *args: object) -> None: + """ + Initialize JSONDecodeError. + + Parameters + ---------- + error_message : str + The error message describing the JSON decode error. + *args : object + Additional arguments to pass to the base Exception. + """ super().__init__(error_message, *args) return # Classes for when we receive an error code in the JSON from the server. class LoginError(SynoBaseException): - """Class for an error during login.""" + """ + Exception raised for an error during login. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize LoginError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code: int = error_code if error_code not in error_codes.keys(): super().__init__(error_message=auth_error_codes[error_code], *args) @@ -51,9 +153,28 @@ def __init__(self, error_code: int, *args: object) -> None: class LogoutError(SynoBaseException): - """Class for an error during logout.""" + """ + Exception raised for an error during logout. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize LogoutError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code: int = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -63,9 +184,28 @@ def __init__(self, error_code: int, *args: object) -> None: class DownloadStationError(SynoBaseException): - """Class for an error during a download station request.""" + """ + Exception raised for an error during a Download Station request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize DownloadStationError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code: int = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -78,9 +218,28 @@ def __init__(self, error_code: int, *args: object) -> None: class FileStationError(SynoBaseException): - """Class for an error during a file station request.""" + """ + Exception raised for an error during a File Station request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize FileStationError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code: int = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -93,9 +252,28 @@ def __init__(self, error_code: int, *args: object) -> None: class VirtualizationError(SynoBaseException): - """Class for an error during a virtualization request.""" + """ + Exception raised for an error during a virtualization request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize VirtualizationError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -108,10 +286,28 @@ def __init__(self, error_code: int, *args: object) -> None: class AudioStationError(SynoBaseException): - """Class for an error during an audio station request. NOTE: I can't find any documentation on the audio station - webAPI errors numbers and their respective messages.""" + """ + Exception raised for an error during an Audio Station request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize AudioStationError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -121,10 +317,28 @@ def __init__(self, error_code: int, *args: object) -> None: class ActiveBackupError(SynoBaseException): - """Class for an error during ActiveBackup request. NOTE: I can't find any documentation on error codes or their - respective messages.""" + """ + Exception raised for an error during an Active Backup request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize ActiveBackupError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -133,10 +347,28 @@ def __init__(self, error_code: int, *args: object) -> None: class ActiveBackupMicrosoftError(SynoBaseException): - """Class for an error during ActiveBackupMicrosoft request. NOTE: I can't find any documentation on error codes or their - respective messages.""" + """ + Exception raised for an error during an Active Backup Microsoft request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize ActiveBackupMicrosoftError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -145,9 +377,28 @@ def __init__(self, error_code: int, *args: object) -> None: class BackupError(SynoBaseException): - """Class for an error during backup request. NOTE: Again I can't find error code documentation.""" + """ + Exception raised for an error during a backup request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize BackupError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -157,9 +408,28 @@ def __init__(self, error_code: int, *args: object) -> None: class CertificateError(SynoBaseException): - """Class for an error during Core.Certificate request. NOTE: Lacking documentation.""" + """ + Exception raised for an error during a Core.Certificate request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize CertificateError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code]) @@ -169,9 +439,28 @@ def __init__(self, error_code: int, *args: object) -> None: class CloudSyncError(SynoBaseException): - """Class for an error during SYNO.CloudSync request. NOTE: Lacking documentation.""" + """ + Exception raised for an error during a SYNO.CloudSync request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize CloudSyncError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code]) @@ -181,9 +470,28 @@ def __init__(self, error_code: int, *args: object) -> None: class DHCPServerError(SynoBaseException): - """Class for an error during a DHCPServer request.""" + """ + Exception raised for an error during a DHCPServer request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize DHCPServerError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -193,9 +501,28 @@ def __init__(self, error_code: int, *args: object) -> None: class DirectoryServerError(SynoBaseException): - """Class for an error during a directory server request. NOTE: No docs on errors.""" + """ + Exception raised for an error during a Directory Server request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize DirectoryServerError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -205,9 +532,28 @@ def __init__(self, error_code: int, *args: object) -> None: class DockerError(SynoBaseException): - """Class for an error during a docker request. NOTE: No docs on errors.""" + """ + Exception raised for an error during a Docker request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize DockerError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -217,9 +563,28 @@ def __init__(self, error_code: int, *args: object) -> None: class DriveAdminError(SynoBaseException): - """Class for an error during a drive admin request. NOTE: No error docs.""" + """ + Exception raised for an error during a Drive Admin request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize DriveAdminError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -229,9 +594,28 @@ def __init__(self, error_code: int, *args: object) -> None: class LogCenterError(SynoBaseException): - """Class for an error during a LogCenter request. NOTE: No docs on errors.... again.""" + """ + Exception raised for an error during a LogCenter request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize LogCenterError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -241,9 +625,28 @@ def __init__(self, error_code: int, *args: object) -> None: class NoteStationError(SynoBaseException): - """Class for an error during a NoteStation request. NOTE: No error docs.""" + """ + Exception raised for an error during a NoteStation request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize NoteStationError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -253,9 +656,28 @@ def __init__(self, error_code: int, *args: object) -> None: class OAUTHError(SynoBaseException): - """Class for an error during a OAUTH request. NOTE: No error docs.""" + """ + Exception raised for an error during an OAUTH request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize OAUTHError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -265,9 +687,28 @@ def __init__(self, error_code: int, *args: object) -> None: class PhotosError(SynoBaseException): - """Class for an error during a Photos request. NOTE: No error docs.""" + """ + Exception raised for an error during a Photos request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize PhotosError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -277,9 +718,28 @@ def __init__(self, error_code: int, *args: object) -> None: class SecurityAdvisorError(SynoBaseException): - """Class for an error during a SecurityAdvisor request. NOTE: What docs?""" + """ + Exception raised for an error during a SecurityAdvisor request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize SecurityAdvisorError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -289,9 +749,28 @@ def __init__(self, error_code: int, *args: object) -> None: class TaskSchedulerError(SynoBaseException): - """Class for an error during TaskScheduler request. NOTE:... no docs on errors....""" + """ + Exception raised for an error during a TaskScheduler request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize TaskSchedulerError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -301,9 +780,28 @@ def __init__(self, error_code: int, *args: object) -> None: class EventSchedulerError(SynoBaseException): - """Class for an error during EventScheduler request. NOTE:... no docs on errors....""" + """ + Exception raised for an error during an EventScheduler request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize EventSchedulerError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -313,9 +811,28 @@ def __init__(self, error_code: int, *args: object) -> None: class UniversalSearchError(SynoBaseException): - """Class for an error during UniversalSearch request. NOTE:... no docs on errors....""" + """ + Exception raised for an error during a UniversalSearch request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize UniversalSearchError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -325,9 +842,28 @@ def __init__(self, error_code: int, *args: object) -> None: class USBCopyError(SynoBaseException): - """Class for an error during a USBCopy request. NOTE: No docs on errors.""" + """ + Exception raised for an error during a USBCopy request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize USBCopyError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -336,9 +872,28 @@ def __init__(self, error_code: int, *args: object) -> None: class VPNError(SynoBaseException): - """Class for an error during a VPN request. NOTE: No docs on errors.""" + """ + Exception raised for an error during a VPN request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize VPNError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -348,10 +903,28 @@ def __init__(self, error_code: int, *args: object) -> None: class CoreError(SynoBaseException): - """Class for an error during a SYNO.Core.* + """ + Exception raised for an error during a SYNO.Core.* request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize CoreError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in core_error_codes.keys(): super().__init__(error_message=core_error_codes[error_code], *args) @@ -361,11 +934,28 @@ def __init__(self, error_code: int, *args: object) -> None: class CoreSysInfoError(SynoBaseException): - """Class for an error during a 'SYNO.Backup.Service.NetworkBackup', SYNO.Storage.*, - 'SYNO.Finder.FileIndexing.Status', 'SYNO.S2S.Server.Pair', SYNO.ResourceMonitor.* + """ + Exception raised for an error during a CoreSysInfoError request. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. """ def __init__(self, error_code: int, *args: object) -> None: + """ + Initialize CoreSysInfoError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code if error_code in error_codes.keys(): super().__init__(error_message=error_codes[error_code], *args) @@ -375,9 +965,32 @@ def __init__(self, error_code: int, *args: object) -> None: class UndefinedError(SynoBaseException): - """Class for undefined errors.""" + """ + Exception raised for undefined errors. + + Parameters + ---------- + error_code : int + The error code returned by the API. + api_name : str + The name of the API where the error occurred. + *args : object + Additional arguments to pass to the base Exception. + """ def __init__(self, error_code: int, api_name: str, *args: object) -> None: + """ + Initialize UndefinedError. + + Parameters + ---------- + error_code : int + The error code returned by the API. + api_name : str + The name of the API where the error occurred. + *args : object + Additional arguments to pass to the base Exception. + """ self.error_code = error_code self.api_name = api_name super().__init__(error_message="Undefined Error: API: %s, Code: %i" % From cff35021d4be4df23179145769d4ca1a01a75673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:36:22 +0700 Subject: [PATCH 033/126] fix: synology_api/filestation.py update docstrings to comply with Numpydoc standards --- synology_api/filestation.py | 910 +++++++++++++++++++++++++++++++++++- 1 file changed, 893 insertions(+), 17 deletions(-) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index 6c36dfd3..2daac609 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -1,3 +1,10 @@ +""" +FileStation API module. + +This module provides the FileStation class for interacting with Synology NAS FileStation API, +allowing file management, search, upload, download, and background task operations. +""" + from __future__ import annotations from typing import Optional, Any import os @@ -15,6 +22,39 @@ class FileStation(base_api.BaseApi): + """ + FileStation API implementation. + + Provides methods to interact with Synology NAS FileStation API for file and folder operations, + search, upload, download, and background task management. + + Parameters + ---------- + ip_address : str + IP address of the Synology NAS. + port : str + Port number for the connection. + username : str + Username for authentication. + password : str + Password for authentication. + secure : bool, optional + Use HTTPS if True, HTTP otherwise. Default is False. + cert_verify : bool, optional + Verify SSL certificates if True. Default is False. + dsm_version : int, optional + DSM version of the Synology NAS. Default is 7. + debug : bool, optional + Enable debug output if True. Default is True. + otp_code : str, optional + One-time password for 2-step verification. Default is None. + device_id : str, optional + Device ID for authentication. Default is None. + device_name : str, optional + Name of the device. Default is None. + interactive_output : bool, optional + If True, enables interactive output. Default is False. + """ def __init__(self, ip_address: str, @@ -30,7 +70,36 @@ def __init__(self, device_name: Optional[str] = None, interactive_output: bool = True ) -> None: - + """ + Initialize FileStation API client. + + Parameters + ---------- + ip_address : str + IP address or hostname of the Synology NAS. + port : str + Port number for the API. + username : str + Username for authentication. + password : str + Password for authentication. + secure : bool, optional + Use HTTPS if True, HTTP if False. Default is False. + cert_verify : bool, optional + Verify SSL certificates if True. Default is False. + dsm_version : int, optional + DSM version. Default is 7. + debug : bool, optional + Enable debug output. Default is True. + otp_code : str, optional + One-time password for 2FA, if required. + device_id : str, optional + Device ID for authentication. + device_name : str, optional + Device name for authentication. + interactive_output : bool, optional + If True, outputs are formatted for interactive use. Default is True. + """ super(FileStation, self).__init__(ip_address, port, username, password, secure, cert_verify, dsm_version, debug, otp_code, device_id, device_name, 'FileStation') @@ -56,6 +125,14 @@ def __init__(self, self.interactive_output: bool = interactive_output def get_info(self) -> dict[str, object] | str: + """ + Get FileStation information. + + Returns + ------- + dict[str, object] or str + FileStation information or error message. + """ api_name = 'SYNO.FileStation.Info' info = self.file_station_list[api_name] api_path = info['path'] @@ -71,7 +148,29 @@ def get_list_share(self, sort_direction: Optional[str] = None, onlywritable: bool = False ) -> dict[str, object] | str: - + """ + List shared folders. + + Parameters + ---------- + additional : str or list of str, optional + Additional attributes to include. + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + onlywritable : bool, optional + If True, only writable shares are listed. + + Returns + ------- + dict[str, object] or str + List of shared folders or error message. + """ api_name = 'SYNO.FileStation.List' info = self.file_station_list[api_name] api_path = info['path'] @@ -102,7 +201,35 @@ def get_file_list(self, filetype: Optional[str] = None, goto_path: Optional[str] = None, additional: Optional[str | list[str]] = None) -> dict[str, object] | str: - + """ + List files in a folder. + + Parameters + ---------- + folder_path : str, optional + Path to the folder. + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + pattern : str, optional + Pattern to filter files. + filetype : str, optional + File type filter. + goto_path : str, optional + Path to go to. + additional : str or list of str, optional + Additional attributes to include. + + Returns + ------- + dict[str, object] or str + List of files or error message. + """ api_name = 'SYNO.FileStation.List' info = self.file_station_list[api_name] api_path = info['path'] @@ -122,7 +249,7 @@ def get_file_list(self, if additional is None: additional = ['real_path', 'size', 'owner', 'time'] - #if type(additional) is list: + # if type(additional) is list: # additional = ','.join(additional) req_param['additional'] = additional @@ -133,6 +260,21 @@ def get_file_info(self, path: Optional[str] = None, additional: Optional[str | list[str]] = None ) -> dict[str, object] | str: + """ + Get information about a file or files. + + Parameters + ---------- + path : str or list of str, optional + Path(s) to the file(s). + additional : str or list of str, optional + Additional attributes to include. + + Returns + ------- + dict[str, object] or str + File information or error message. + """ api_name = 'SYNO.FileStation.List' info = self.file_station_list[api_name] api_path = info['path'] @@ -177,7 +319,47 @@ def search_start(self, owner: Optional[str] = None, group: Optional[str] = None ) -> dict[str, object] | str: - + """ + Start a search task. + + Parameters + ---------- + folder_path : str, optional + Path to the folder where the search will start. + recursive : bool, optional + If True, the search will be recursive. + pattern : str, optional + Pattern to search for. + extension : str, optional + File extension to filter by. + filetype : str, optional + File type filter. + size_from : int, optional + Minimum file size. + size_to : int, optional + Maximum file size. + mtime_from : str or int, optional + Minimum modification time (Unix timestamp or formatted string). + mtime_to : str or int, optional + Maximum modification time (Unix timestamp or formatted string). + crtime_from : str or int, optional + Minimum creation time (Unix timestamp or formatted string). + crtime_to : str or int, optional + Maximum creation time (Unix timestamp or formatted string). + atime_from : str or int, optional + Minimum access time (Unix timestamp or formatted string). + atime_to : str or int, optional + Maximum access time (Unix timestamp or formatted string). + owner : str, optional + Owner filter. + group : str, optional + Group filter. + + Returns + ------- + dict[str, object] or str + Search task ID or error message. + """ api_name = 'SYNO.FileStation.Search' info = self.file_station_list[api_name] api_path = info['path'] @@ -234,6 +416,31 @@ def get_search_list(self, offset: Optional[int] = None, additional: Optional[str | list[str]] = None ) -> dict[str, object] | str: + """ + Get the results of a search task. + + Parameters + ---------- + task_id : str + Task ID of the search task. + filetype : str, optional + File type filter. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + offset : int, optional + Offset for pagination. + additional : str or list of str, optional + Additional attributes to include. + + Returns + ------- + dict[str, object] or str + Search results or error message. + """ api_name = 'SYNO.FileStation.Search' info = self.file_station_list[api_name] api_path = info['path'] @@ -264,6 +471,19 @@ def get_search_list(self, return self.request_data(api_name, api_path, req_param) def stop_search_task(self, taskid: str) -> dict[str, object] | str: + """ + Stop a search task. + + Parameters + ---------- + taskid : str + Task ID of the search task to stop. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Search' info = self.file_station_list[api_name] api_path = info['path'] @@ -278,6 +498,14 @@ def stop_search_task(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def stop_all_search_task(self) -> str: + """ + Stop all running search tasks. + + Returns + ------- + str + Confirmation message. + """ api_name = 'SYNO.FileStation.Search' info = self.file_station_list[api_name] api_path = info['path'] @@ -303,7 +531,29 @@ def get_mount_point_list(self, sort_direction: Optional[str] = None, additional: Optional[str | list[str]] = None ) -> dict[str, object] | str: - + """ + List mount points. + + Parameters + ---------- + mount_type : str, optional + Type of mount point to filter by. + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + additional : str or list of str, optional + Additional attributes to include. + + Returns + ------- + dict[str, object] or str + List of mount points or error message. + """ api_name = 'SYNO.FileStation.VirtualFolder' info = self.file_station_list[api_name] api_path = info['path'] @@ -334,7 +584,27 @@ def get_favorite_list(self, status_filter: Optional[str] = None, additional: Optional[str | list[str]] = None ) -> dict[str, object] | str: - + """ + List favorite files and folders. + + Parameters + ---------- + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + status_filter : str, optional + Status filter. + additional : str or list of str, optional + Additional attributes to include. + + Returns + ------- + dict[str, object] or str + List of favorites or error message. + """ api_name = 'SYNO.FileStation.Favorite' info = self.file_station_list[api_name] api_path = info['path'] @@ -360,6 +630,23 @@ def add_a_favorite(self, name: Optional[str] = None, index: Optional[int] = None ) -> dict[str, object] | str: + """ + Add a file or folder to favorites. + + Parameters + ---------- + path : str + Path to the file or folder. + name : str, optional + Name for the favorite. + index : int, optional + Index for the favorite. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Favorite' info = self.file_station_list[api_name] api_path = info['path'] @@ -376,6 +663,19 @@ def add_a_favorite(self, return self.request_data(api_name, api_path, req_param) def delete_a_favorite(self, path: Optional[str] = None) -> dict[str, object] | str: + """ + Delete a favorite. + + Parameters + ---------- + path : str, optional + Path to the favorite to delete. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Favorite' info = self.file_station_list[api_name] api_path = info['path'] @@ -389,6 +689,14 @@ def delete_a_favorite(self, path: Optional[str] = None) -> dict[str, object] | s return self.request_data(api_name, api_path, req_param) def clear_broken_favorite(self) -> dict[str, object] | str: + """ + Clear broken favorites. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Favorite' info = self.file_station_list[api_name] api_path = info['path'] @@ -397,6 +705,21 @@ def clear_broken_favorite(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object] | str: + """ + Edit the name of a favorite. + + Parameters + ---------- + path : str + Path to the favorite. + new_name : str + New name for the favorite. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Favorite' info = self.file_station_list[api_name] api_path = info['path'] @@ -415,6 +738,21 @@ def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object] | st return self.request_data(api_name, api_path, req_param) def replace_all_favorite(self, path: str | list[str], name: str | list[str]): + """ + Replace all favorites with new paths and names. + + Parameters + ---------- + path : str or list of str + New path or list of new paths for the favorites. + name : str or list of str + New name or list of new names for the favorites. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Favorite' info = self.file_station_list[api_name] api_path = info['path'] @@ -439,6 +777,19 @@ def replace_all_favorite(self, path: str | list[str], name: str | list[str]): return self.request_data(api_name, api_path, req_param) def start_dir_size_calc(self, path: str) -> dict[str, object] | str: + """ + Start a directory size calculation task. + + Parameters + ---------- + path : str + Path to the directory. + + Returns + ------- + dict[str, object] or str + Task ID or error message. + """ api_name = 'SYNO.FileStation.DirSize' info = self.file_station_list[api_name] api_path = info['path'] @@ -473,6 +824,19 @@ def start_dir_size_calc(self, path: str) -> dict[str, object] | str: return output def stop_dir_size_calc(self, taskid: str) -> str: + """ + Stop a directory size calculation task. + + Parameters + ---------- + taskid : str + Task ID of the size calculation task to stop. + + Returns + ------- + str + Confirmation message. + """ api_name = 'SYNO.FileStation.DirSize' info = self.file_station_list[api_name] api_path = info['path'] @@ -490,6 +854,19 @@ def stop_dir_size_calc(self, taskid: str) -> str: return 'The task has been stopped' def get_dir_status(self, taskid: Optional[str] = None) -> dict[str, object] | str: + """ + Get the status of a directory size calculation task. + + Parameters + ---------- + taskid : str, optional + Task ID of the size calculation task. + + Returns + ------- + dict[str, object] or str + Task status or error message. + """ api_name = 'SYNO.FileStation.DirSize' info = self.file_station_list[api_name] api_path = info['path'] @@ -502,6 +879,19 @@ def get_dir_status(self, taskid: Optional[str] = None) -> dict[str, object] | st return self.request_data(api_name, api_path, req_param) def start_md5_calc(self, file_path: str) -> str | dict[str, object]: + """ + Start an MD5 calculation task. + + Parameters + ---------- + file_path : str + Path to the file. + + Returns + ------- + str or dict[str, object] + Task ID or error message. + """ api_name = 'SYNO.FileStation.MD5' info = self.file_station_list[api_name] api_path = info['path'] @@ -526,6 +916,19 @@ def start_md5_calc(self, file_path: str) -> str | dict[str, object]: return output def get_md5_status(self, taskid: Optional[str] = None) -> str | dict[str, object]: + """ + Get the status of an MD5 calculation task. + + Parameters + ---------- + taskid : str, optional + Task ID of the MD5 calculation task. + + Returns + ------- + str or dict[str, object] + Task status or error message. + """ api_name = 'SYNO.FileStation.MD5' info = self.file_station_list[api_name] api_path = info['path'] @@ -542,6 +945,19 @@ def get_md5_status(self, taskid: Optional[str] = None) -> str | dict[str, object return self.request_data(api_name, api_path, req_param) def stop_md5_calc(self, taskid: str) -> str: + """ + Stop an MD5 calculation task. + + Parameters + ---------- + taskid : str + Task ID of the MD5 calculation task to stop. + + Returns + ------- + str + Confirmation message. + """ api_name = 'SYNO.FileStation.DirSize' info = self.file_station_list[api_name] api_path = info['path'] @@ -564,6 +980,25 @@ def check_permissions(self, overwrite: Optional[bool] = None, create_only: Optional[bool] = None ) -> dict[str, object] | str: + """ + Check permissions for a file or folder. + + Parameters + ---------- + path : str + Path to the file or folder. + filename : str + Name of the file. + overwrite : bool, optional + If True, overwriting is allowed. + create_only : bool, optional + If True, only creation is allowed. + + Returns + ------- + dict[str, object] or str + Permission check result or error message. + """ api_name = 'SYNO.FileStation.CheckPermission' info = self.file_station_list[api_name] api_path = info['path'] @@ -590,6 +1025,29 @@ def upload_file(self, verify: bool = False, progress_bar: bool = True ) -> str | tuple[int, dict[str, object]]: + """ + Upload a file to the server. + + Parameters + ---------- + dest_path : str + Destination path on the server. + file_path : str + Path to the file to upload. + create_parents : bool, optional + If True, parent folders will be created. + overwrite : bool, optional + If True, existing files will be overwritten. + verify : bool, optional + If True, SSL certificates will be verified. + progress_bar : bool, optional + If True, shows a progress bar during upload. + + Returns + ------- + str or tuple[int, dict[str, object]] + Upload result or error message. + """ api_name = 'SYNO.FileStation.Upload' info = self.file_station_list[api_name] api_path = info['path'] @@ -644,6 +1102,19 @@ def upload_file(self, return r.json() def get_shared_link_info(self, link_id: str) -> dict[str, object] | str: + """ + Get information about a shared link. + + Parameters + ---------- + link_id : str + ID of the shared link. + + Returns + ------- + dict[str, object] or str + Shared link information or error message. + """ api_name = 'SYNO.FileStation.Sharing' info = self.file_station_list[api_name] api_path = info['path'] @@ -663,7 +1134,27 @@ def get_shared_link_list(self, sort_direction: Optional[str] = None, force_clean: Optional[bool] = None ) -> dict[str, object] | str: - + """ + List shared links. + + Parameters + ---------- + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + force_clean : bool, optional + If True, forces a clean of the shared link list. + + Returns + ------- + dict[str, object] or str + List of shared links or error message. + """ api_name = 'SYNO.FileStation.Sharing' info = self.file_station_list[api_name] api_path = info['path'] @@ -683,6 +1174,27 @@ def create_sharing_link(self, date_available: Optional[str | int] = None, expire_times: int = 0 ) -> dict[str, object] | str: + """ + Create a shared link. + + Parameters + ---------- + path : str + Path to the file or folder to share. + password : str, optional + Password for the shared link. + date_expired : str or int, optional + Expiration date for the shared link (Unix timestamp or formatted string). + date_available : str or int, optional + Availability date for the shared link (Unix timestamp or formatted string). + expire_times : int, optional + Number of times the link can be accessed before expiring. + + Returns + ------- + dict[str, object] or str + Shared link details or error message. + """ api_name = 'SYNO.FileStation.Sharing' info = self.file_station_list[api_name] api_path = info['path'] @@ -706,6 +1218,19 @@ def create_sharing_link(self, return self.request_data(api_name, api_path, req_param) def delete_shared_link(self, link_id: str) -> dict[str, object] | str: + """ + Delete a shared link. + + Parameters + ---------- + link_id : str + ID of the shared link to delete. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Sharing' info = self.file_station_list[api_name] api_path = info['path'] @@ -719,6 +1244,14 @@ def delete_shared_link(self, link_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def clear_invalid_shared_link(self) -> dict[str, object] | str: + """ + Clear invalid shared links. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Sharing' info = self.file_station_list[api_name] api_path = info['path'] @@ -733,6 +1266,27 @@ def edit_shared_link(self, date_available: Optional[str | int] = None, expire_times: int = 0 ) -> dict[str, object] | str: + """ + Edit a shared link. + + Parameters + ---------- + link_id : str + ID of the shared link to edit. + password : str, optional + New password for the shared link. + date_expired : str or int, optional + New expiration date for the shared link (Unix timestamp or formatted string). + date_available : str or int, optional + New availability date for the shared link (Unix timestamp or formatted string). + expire_times : int, optional + New number of times the link can be accessed before expiring. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Sharing' info = self.file_station_list[api_name] api_path = info['path'] @@ -763,6 +1317,25 @@ def create_folder(self, force_parent: Optional[bool] = None, additional: Optional[str | list[str]] = None ) -> str | dict[str, object]: + """ + Create a new folder. + + Parameters + ---------- + folder_path : str or list of str + Path or list of paths where the folder should be created. + name : str or list of str + Name or list of names for the new folder. + force_parent : bool, optional + If True, parent folders will be created if they don't exist. + additional : str or list of str, optional + Additional attributes to include. + + Returns + ------- + str or dict[str, object] + Creation result or error message. + """ api_name = 'SYNO.FileStation.CreateFolder' info = self.file_station_list[api_name] api_path = info['path'] @@ -811,6 +1384,25 @@ def rename_folder(self, additional: Optional[str | list[str]] = None, search_taskid: Optional[str] = None ) -> dict[str, object] | str: + """ + Rename a folder. + + Parameters + ---------- + path : str or list of str + Current path or list of paths of the folder(s) to rename. + name : str or list of str + New name or list of new names for the folder(s). + additional : str or list of str, optional + Additional attributes to include. + search_taskid : str, optional + Task ID of a search task. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Rename' info = self.file_station_list[api_name] api_path = info['path'] @@ -859,6 +1451,29 @@ def start_copy_move(self, accurate_progress: Optional[bool] = None, search_taskid: Optional[str] = None ) -> str | dict[str, object]: + """ + Start a copy or move task. + + Parameters + ---------- + path : str or list of str + Source path or list of source paths to copy or move. + dest_folder_path : str or list of str + Destination folder path or list of destination folder paths. + overwrite : bool, optional + If True, existing files will be overwritten. + remove_src : bool, optional + If True, source files will be removed after copying. + accurate_progress : bool, optional + If True, shows accurate progress. + search_taskid : str, optional + Task ID of a search task. + + Returns + ------- + str or dict[str, object] + Task ID or error message. + """ api_name = 'SYNO.FileStation.CopyMove' info = self.file_station_list[api_name] api_path = info['path'] @@ -907,6 +1522,19 @@ def start_copy_move(self, return output def get_copy_move_status(self, taskid: str) -> dict[str, object] | str: + """ + Get the status of a copy or move task. + + Parameters + ---------- + taskid : str + Task ID of the copy or move task. + + Returns + ------- + dict[str, object] or str + Task status or error message. + """ api_name = 'SYNO.FileStation.CopyMove' info = self.file_station_list[api_name] api_path = info['path'] @@ -920,6 +1548,19 @@ def get_copy_move_status(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def stop_copy_move_task(self, taskid: str) -> dict[str, object] | str: + """ + Stop a copy or move task. + + Parameters + ---------- + taskid : str + Task ID of the copy or move task to stop. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.CopyMove' info = self.file_station_list[api_name] api_path = info['path'] @@ -940,6 +1581,25 @@ def start_delete_task(self, recursive: Optional[bool] = None, search_taskid: Optional[str] = None ) -> dict[str, object] | str: + """ + Start a delete task. + + Parameters + ---------- + path : str or list of str + Path or list of paths to the file or folder to delete. + accurate_progress : bool, optional + If True, shows accurate progress. + recursive : bool, optional + If True, deletes folders recursively. + search_taskid : str, optional + Task ID of a search task. + + Returns + ------- + dict[str, object] or str + Task ID or error message. + """ api_name = 'SYNO.FileStation.Delete' info = self.file_station_list[api_name] api_path = info['path'] @@ -976,6 +1636,19 @@ def start_delete_task(self, return output def get_delete_status(self, taskid: str) -> dict[str, object] | str: + """ + Get the status of a delete task. + + Parameters + ---------- + taskid : str + Task ID of the delete task. + + Returns + ------- + dict[str, object] or str + Task status or error message. + """ api_name = 'SYNO.FileStation.Delete' info = self.file_station_list[api_name] api_path = info['path'] @@ -989,6 +1662,19 @@ def get_delete_status(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def stop_delete_task(self, taskid: str) -> dict[str, object] | str: + """ + Stop a delete task. + + Parameters + ---------- + taskid : str + Task ID of the delete task to stop. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Delete' info = self.file_station_list[api_name] api_path = info['path'] @@ -1007,6 +1693,25 @@ def delete_blocking_function(self, path: str, recursive: Optional[bool] = None, search_taskid: Optional[str] = None) -> dict[str, object] | str: + """ + Delete a file or folder (blocking function). + + This function will stop your script until done! Do not interrupt. + + Parameters + ---------- + path : str or list of str + Path or list of paths to the file or folder to delete. + recursive : bool, optional + If True, deletes folders recursively. + search_taskid : str, optional + Task ID of a search task. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Delete' info = self.file_station_list[api_name] api_path = info['path'] @@ -1042,6 +1747,33 @@ def start_extract_task(self, password: Optional[str] = None, item_id: Optional[str] = None ) -> dict[str, object] | str: + """ + Start an extract task. + + Parameters + ---------- + file_path : str + Path to the archive file. + dest_folder_path : str + Destination folder path where the files will be extracted. + overwrite : bool, optional + If True, existing files will be overwritten. + keep_dir : bool, optional + If True, the original directory structure will be kept. + create_subfolder : bool, optional + If True, a subfolder will be created for the extracted files. + codepage : str, optional + Codepage for the extraction. + password : str, optional + Password for the archive, if required. + item_id : str, optional + Item ID for the extraction task. + + Returns + ------- + dict[str, object] or str + Task ID or error message. + """ api_name = 'SYNO.FileStation.Extract' info = self.file_station_list[api_name] api_path = info['path'] @@ -1074,6 +1806,19 @@ def start_extract_task(self, return output def get_extract_status(self, taskid: str) -> dict[str, object] | str: + """ + Get the status of an extract task. + + Parameters + ---------- + taskid : str + Task ID of the extract task. + + Returns + ------- + dict[str, object] or str + Task status or error message. + """ api_name = 'SYNO.FileStation.Extract' info = self.file_station_list[api_name] api_path = info['path'] @@ -1087,6 +1832,19 @@ def get_extract_status(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def stop_extract_task(self, taskid: str) -> dict[str, object] | str: + """ + Stop an extract task. + + Parameters + ---------- + taskid : str + Task ID of the extract task to stop. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Extract' info = self.file_station_list[api_name] api_path = info['path'] @@ -1111,6 +1869,33 @@ def get_file_list_of_archive(self, password: Optional[str] = None, item_id: Optional[str] = None ) -> dict[str, object] | str: + """ + Get the list of files in an archive. + + Parameters + ---------- + file_path : str + Path to the archive file. + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + codepage : str, optional + Codepage for the file list. + password : str, optional + Password for the archive, if required. + item_id : str, optional + Item ID for the archive. + + Returns + ------- + dict[str, object] or str + List of files in the archive or error message. + """ api_name = 'SYNO.FileStation.Extract' info = self.file_station_list[api_name] api_path = info['path'] @@ -1134,6 +1919,29 @@ def start_file_compression(self, compress_format: Optional[str] = None, password: Optional[str] = None ) -> dict[str, object] | str | tuple[str]: + """ + Start a file compression task. + + Parameters + ---------- + path : str or list of str + Path or list of paths to the file or folder to compress. + dest_file_path : str + Destination file path for the compressed file. + level : int, optional + Compression level. + mode : str, optional + Compression mode. + compress_format : str, optional + Compression format. + password : str, optional + Password for the compressed file, if required. + + Returns + ------- + dict[str, object] or str + Task ID or error message. + """ api_name = 'SYNO.FileStation.Compress' info = self.file_station_list[api_name] api_path = info['path'] @@ -1179,6 +1987,19 @@ def start_file_compression(self, return output def get_compress_status(self, taskid: str) -> dict[str, object] | str: + """ + Get the status of a file compression task. + + Parameters + ---------- + taskid : str + Task ID of the compression task. + + Returns + ------- + dict[str, object] or str + Task status or error message. + """ api_name = 'SYNO.FileStation.Compress' info = self.file_station_list[api_name] api_path = info['path'] @@ -1192,6 +2013,19 @@ def get_compress_status(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def stop_compress_task(self, taskid: str) -> dict[str, object] | str: + """ + Stop a file compression task. + + Parameters + ---------- + taskid : str + Task ID of the compression task to stop. + + Returns + ------- + dict[str, object] or str + Response from the API or error message. + """ api_name = 'SYNO.FileStation.Compress' info = self.file_station_list[api_name] api_path = info['path'] @@ -1211,6 +2045,27 @@ def get_list_of_all_background_task(self, sort_direction: Optional[str] = None, api_filter: Optional[str] = None ) -> dict[str, object] | str: + """ + Get a list of all background tasks. + + Parameters + ---------- + offset : int, optional + Offset for pagination. + limit : int, optional + Limit for pagination. + sort_by : str, optional + Field to sort by. + sort_direction : str, optional + Sort direction ('asc' or 'desc'). + api_filter : str, optional + API filter. + + Returns + ------- + dict[str, object] or str + List of background tasks or error message. + """ api_name = 'SYNO.FileStation.BackgroundTask' info = self.file_station_list[api_name] api_path = info['path'] @@ -1237,7 +2092,27 @@ def get_file(self, chunk_size: int = 8192, verify: bool = False ) -> Optional[str]: - + """ + Download a file from the server. + + Parameters + ---------- + path : str + Path to the file on the server. + mode : str + Mode for downloading the file ('open' to open in browser, 'download' to download to disk). + dest_path : str, optional + Destination path on the local machine (for 'download' mode). + chunk_size : int, optional + Chunk size for downloading. + verify : bool, optional + If True, SSL certificates will be verified. + + Returns + ------- + Optional[str] + None if successful, error message otherwise. + """ api_name = 'SYNO.FileStation.Download' info = self.file_station_list[api_name] api_path = info['path'] @@ -1276,17 +2151,18 @@ def get_file(self, return io.BytesIO(r.content) def generate_file_tree(self, folder_path: str, tree: Tree) -> None: - """Generate the file tree based on the folder path you give, you need to create the root node before call this function + """ + Generate the file tree based on the folder path you give. - Parameters - ---------- - folder_path : str - Folder path to generate file tree - tree : Tree - Instance of the Tree of lib \"Treelib\" + You need to create the root node before calling this function. + Parameters + ---------- + folder_path : str + Folder path to generate file tree. + tree : Tree + Instance of the Tree from the `treelib` library. """ - api_name = 'hotfix' # fix for docs_parser.py issue data: dict = self.get_file_list( From e143562d34b0ced481b518d3f1ea5f35956c2798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:43:10 +0700 Subject: [PATCH 034/126] fix: synology_api/log_center.py update docstrings to comply with Numpydoc standards --- synology_api/log_center.py | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/synology_api/log_center.py b/synology_api/log_center.py index f9335ce1..20c80e0c 100644 --- a/synology_api/log_center.py +++ b/synology_api/log_center.py @@ -1,11 +1,31 @@ +""" +Log Center API wrapper for Synology DSM. + +This module provides a class to interact with the Synology Log Center API. +""" + from __future__ import annotations from typing import Optional from . import base_api class LogCenter(base_api.BaseApi): + """ + Interface for Synology Log Center API. + + Provides methods to interact with log center features such as retrieving logs, + client status, remote archives, and storage settings. + """ def logcenter(self) -> dict[str, object] | str: + """ + Retrieve the list of log center receive rules. + + Returns + ------- + dict[str, object] or str + The API response containing the receive rules or an error message. + """ api_name = 'SYNO.LogCenter.RecvRule' info = self.gen_list[api_name] api_path = info['path'] @@ -14,6 +34,14 @@ def logcenter(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def client_status_cnt(self) -> dict[str, object] | str: + """ + Retrieve the count status from the syslog client. + + Returns + ------- + dict[str, object] or str + The API response containing the count status or an error message. + """ api_name = 'SYNO.Core.SyslogClient.Status' info = self.gen_list[api_name] api_path = info['path'] @@ -22,6 +50,14 @@ def client_status_cnt(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def client_status_eps(self) -> dict[str, object] | str: + """ + Retrieve the EPS (events per second) status from the syslog client. + + Returns + ------- + dict[str, object] or str + The API response containing the EPS status or an error message. + """ api_name = 'SYNO.Core.SyslogClient.Status' info = self.gen_list[api_name] api_path = info['path'] @@ -30,6 +66,14 @@ def client_status_eps(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def remote_log_archives(self) -> dict[str, object] | str: + """ + Retrieve the list of remote log archive subfolders. + + Returns + ------- + dict[str, object] or str + The API response containing remote archive subfolders or an error message. + """ api_name = 'SYNO.LogCenter.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -39,6 +83,14 @@ def remote_log_archives(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def display_logs(self) -> dict[str, object] | str: + """ + Retrieve the list of logs from the syslog client. + + Returns + ------- + dict[str, object] or str + The API response containing the logs or an error message. + """ api_name = 'SYNO.Core.SyslogClient.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -47,6 +99,14 @@ def display_logs(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def setting_storage_list(self) -> dict[str, object] | str: + """ + Retrieve the log center storage settings. + + Returns + ------- + dict[str, object] or str + The API response containing storage settings or an error message. + """ api_name = 'SYNO.LogCenter.Setting.Storage' info = self.gen_list[api_name] api_path = info['path'] @@ -55,6 +115,14 @@ def setting_storage_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def registry_send_list(self) -> dict[str, object] | str: + """ + Retrieve the list of log center client registry send settings. + + Returns + ------- + dict[str, object] or str + The API response containing registry send settings or an error message. + """ api_name = 'SYNO.LogCenter.Client' info = self.gen_list[api_name] api_path = info['path'] @@ -63,6 +131,14 @@ def registry_send_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def history(self) -> dict[str, object] | str: + """ + Retrieve the log center history. + + Returns + ------- + dict[str, object] or str + The API response containing the log center history or an error message. + """ api_name = 'SYNO.LogCenter.History' info = self.gen_list[api_name] api_path = info['path'] From 535fe47f2e61aad0e148507594a1f325d1839837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:46:05 +0700 Subject: [PATCH 035/126] fix: synology_api/notestation.py update docstrings to comply with Numpydoc standards --- synology_api/notestation.py | 89 +++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/synology_api/notestation.py b/synology_api/notestation.py index dbd91238..129d302d 100644 --- a/synology_api/notestation.py +++ b/synology_api/notestation.py @@ -1,11 +1,31 @@ +""" +NoteStation API wrapper for Synology DSM. + +This module provides a class to interact with the Synology NoteStation API. +""" + from __future__ import annotations from typing import Optional from . import base_api class NoteStation(base_api.BaseApi): + """ + Interface for Synology NoteStation API. + + Provides methods to interact with NoteStation features such as retrieving settings, + notebooks, tags, shortcuts, todos, smart notes, and individual notes. + """ def settings_info(self) -> dict[str, object] | str: + """ + Retrieve NoteStation settings information. + + Returns + ------- + dict[str, object] or str + The API response containing settings information or an error message. + """ api_name = 'SYNO.NoteStation.Setting' info = self.gen_list[api_name] api_path = info['path'] @@ -23,6 +43,14 @@ def settings_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param)''' def info(self) -> dict[str, object] | str: + """ + Retrieve NoteStation general information. + + Returns + ------- + dict[str, object] or str + The API response containing general information or an error message. + """ api_name = 'SYNO.NoteStation.Info' info = self.gen_list[api_name] api_path = info['path'] @@ -31,6 +59,14 @@ def info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def notebooks_info(self) -> dict[str, object] | str: + """ + Retrieve the list of notebooks. + + Returns + ------- + dict[str, object] or str + The API response containing the list of notebooks or an error message. + """ api_name = 'SYNO.NoteStation.Notebook' info = self.gen_list[api_name] api_path = info['path'] @@ -39,6 +75,14 @@ def notebooks_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def tags_info(self) -> dict[str, object] | str: + """ + Retrieve the list of tags. + + Returns + ------- + dict[str, object] or str + The API response containing the list of tags or an error message. + """ api_name = 'SYNO.NoteStation.Tag' info = self.gen_list[api_name] api_path = info['path'] @@ -47,6 +91,14 @@ def tags_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def shortcuts(self) -> dict[str, object] | str: + """ + Retrieve the list of shortcuts. + + Returns + ------- + dict[str, object] or str + The API response containing the list of shortcuts or an error message. + """ api_name = 'SYNO.NoteStation.Shortcut' info = self.gen_list[api_name] api_path = info['path'] @@ -55,6 +107,14 @@ def shortcuts(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def todo(self) -> dict[str, object] | str: + """ + Retrieve the list of todo items. + + Returns + ------- + dict[str, object] or str + The API response containing the list of todo items or an error message. + """ api_name = 'SYNO.NoteStation.Todo' info = self.gen_list[api_name] api_path = info['path'] @@ -64,6 +124,14 @@ def todo(self) -> dict[str, object] | str: # TODO need to investigate for additional params def smart(self) -> dict[str, object] | str: + """ + Retrieve the list of smart notes. + + Returns + ------- + dict[str, object] or str + The API response containing the list of smart notes or an error message. + """ api_name = 'SYNO.NoteStation.Smart' info = self.gen_list[api_name] api_path = info['path'] @@ -72,6 +140,14 @@ def smart(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def note_list(self) -> dict[str, object] | str: + """ + Retrieve the list of notes. + + Returns + ------- + dict[str, object] or str + The API response containing the list of notes or an error message. + """ api_name = 'SYNO.NoteStation.Note' info = self.gen_list[api_name] api_path = info['path'] @@ -80,6 +156,19 @@ def note_list(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def specific_note_id(self, note_id) -> dict[str, object] | str: + """ + Retrieve a specific note by its ID. + + Parameters + ---------- + note_id : str or int + The ID of the note to retrieve. + + Returns + ------- + dict[str, object] or str + The API response containing the note data or an error message. + """ api_name = 'SYNO.NoteStation.Note' info = self.gen_list[api_name] api_path = info['path'] From 125f21e3dca81117070ba0475eb40d4edfe1c916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:47:12 +0700 Subject: [PATCH 036/126] fix: synology_api/oauth.py update docstrings to comply with Numpydoc standards --- synology_api/oauth.py | 56 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/synology_api/oauth.py b/synology_api/oauth.py index b87f4382..5d91bd3f 100644 --- a/synology_api/oauth.py +++ b/synology_api/oauth.py @@ -1,11 +1,37 @@ +""" +OAuth API wrapper for Synology DSM. + +This module provides a class to interact with the Synology OAuth API. +""" + from __future__ import annotations from typing import Optional from . import base_api class OAuth(base_api.BaseApi): + """ + Interface for Synology OAuth API. + + Provides methods to interact with OAuth clients, tokens, and logs. + """ def clients(self, offset: int = 0, limit: int = 20) -> dict[str, object] | str: + """ + Retrieve the list of OAuth clients. + + Parameters + ---------- + offset : int, optional + The starting index of the client list. Default is 0. + limit : int, optional + The maximum number of clients to retrieve. Default is 20. + + Returns + ------- + dict[str, object] or str + The API response containing the list of clients or an error message. + """ api_name = 'SYNO.OAUTH.Client' info = self.gen_list[api_name] api_path = info['path'] @@ -15,6 +41,21 @@ def clients(self, offset: int = 0, limit: int = 20) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def tokens(self, offset: int = 0, limit: int = 20) -> dict[str, object] | str: + """ + Retrieve the list of OAuth tokens. + + Parameters + ---------- + offset : int, optional + The starting index of the token list. Default is 0. + limit : int, optional + The maximum number of tokens to retrieve. Default is 20. + + Returns + ------- + dict[str, object] or str + The API response containing the list of tokens or an error message. + """ api_name = 'SYNO.OAUTH.Token' info = self.gen_list[api_name] api_path = info['path'] @@ -24,6 +65,21 @@ def tokens(self, offset: int = 0, limit: int = 20) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def logs(self, offset: int = 0, limit: int = 20) -> dict[str, object] | str: + """ + Retrieve the list of OAuth logs. + + Parameters + ---------- + offset : int, optional + The starting index of the log list. Default is 0. + limit : int, optional + The maximum number of logs to retrieve. Default is 20. + + Returns + ------- + dict[str, object] or str + The API response containing the list of logs or an error message. + """ api_name = 'SYNO.OAUTH.Log' info = self.gen_list[api_name] api_path = info['path'] From 76bbc6f1bc3e670d1b4337d4ba7e45a99671e02a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:53:40 +0700 Subject: [PATCH 037/126] fix: synology_api/photos.py update docstrings to comply with Numpydoc standards --- synology_api/photos.py | 472 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 435 insertions(+), 37 deletions(-) diff --git a/synology_api/photos.py b/synology_api/photos.py index 8e937c6e..8cd10c21 100755 --- a/synology_api/photos.py +++ b/synology_api/photos.py @@ -1,3 +1,9 @@ +""" +Photos API wrapper for Synology DSM. + +This module provides a class to interact with the Synology Photos API. +""" + from __future__ import annotations from typing import Optional, Any from . import base_api @@ -5,6 +11,37 @@ class Photos(base_api.BaseApi): + """ + Interface for Synology Photos API. + + Provides methods to interact with Photos features such as retrieving user info, + folders, albums, sharing, and items. + + Parameters + ---------- + ip_address : str + The IP address or hostname of the Synology NAS. + port : str + The port number to connect to. + username : str + The username for authentication. + password : str + The password for authentication. + secure : bool, optional + Whether to use HTTPS. Default is False. + cert_verify : bool, optional + Whether to verify SSL certificates. Default is False. + dsm_version : int, optional + DSM version. Default is 7. + debug : bool, optional + Enable debug output. Default is True. + otp_code : str, optional + One-time password for 2FA, if required. + device_id : str, optional + Device ID for the session. + device_name : str, optional + Device name for the session. + """ def __init__(self, ip_address: str, @@ -19,6 +56,34 @@ def __init__(self, device_id: Optional[str] = None, device_name: Optional[str] = None ) -> None: + """ + Initialize the Photos API interface. + + Parameters + ---------- + ip_address : str + The IP address or hostname of the Synology NAS. + port : str + The port number to connect to. + username : str + The username for authentication. + password : str + The password for authentication. + secure : bool, optional + Whether to use HTTPS. Default is False. + cert_verify : bool, optional + Whether to verify SSL certificates. Default is False. + dsm_version : int, optional + DSM version. Default is 7. + debug : bool, optional + Enable debug output. Default is True. + otp_code : str, optional + One-time password for 2FA, if required. + device_id : str, optional + Device ID for the session. + device_name : str, optional + Device name for the session. + """ super(Photos, self).__init__(ip_address, port, username, password, secure, cert_verify, dsm_version, debug, otp_code, device_id, device_name, 'FotoStation') @@ -32,6 +97,14 @@ def __init__(self, self._userinfo: Any = None def get_userinfo(self) -> Any: + """ + Retrieve user information for the current session. + + Returns + ------- + Any + The user information data. + """ if self._userinfo is not None: return self._userinfo @@ -44,6 +117,19 @@ def get_userinfo(self) -> Any: return self._userinfo def get_folder(self, folder_id: int = 0) -> dict[str, object] | str: + """ + Retrieve information about a specific folder. + + Parameters + ---------- + folder_id : int, optional + The ID of the folder. Default is 0. + + Returns + ------- + dict[str, object] or str + The folder information or an error message. + """ api_name = 'SYNO.Foto.Browse.Folder' info = self.photos_list[api_name] api_path = info['path'] @@ -58,6 +144,25 @@ def list_folders(self, offset: int = 0, additional: str | list[str] = None ) -> dict[str, object] | str: + """ + List folders in Personal Space. + + Parameters + ---------- + folder_id : int, optional + The parent folder ID. Default is 0. + limit : int, optional + Maximum number of folders to return. Default is 1000. + offset : int, optional + Number of folders to skip. Default is 0. + additional : str or list of str, optional + Additional fields to include. + + Returns + ------- + dict[str, object] or str + The list of folders or an error message. + """ return self._list_folders(folder_id, limit, offset, additional, 'SYNO.Foto.Browse.Folder') def list_teams_folders(self, @@ -66,10 +171,50 @@ def list_teams_folders(self, offset: int = 0, additional: Optional[str | list[str]] = None ) -> dict[str, object] | str: + """ + List folders in Team Space. + + Parameters + ---------- + folder_id : int, optional + The parent folder ID. Default is 0. + limit : int, optional + Maximum number of folders to return. Default is 2000. + offset : int, optional + Number of folders to skip. Default is 0. + additional : str or list of str, optional + Additional fields to include. + + Returns + ------- + dict[str, object] or str + The list of team folders or an error message. + """ return self._list_folders(folder_id, limit, offset, additional, 'SYNO.FotoTeam.Browse.Folder') def _list_folders(self, folder_id: int, limit: int, offset: int, additional: Optional[str | list[str]], api_name: str) -> Any: + """ + Internal method to list folders. + + Parameters + ---------- + folder_id : int + The parent folder ID. + limit : int + Maximum number of folders to return. + offset : int + Number of folders to skip. + additional : str or list of str, optional + Additional fields to include. + api_name : str + API name to use. + + Returns + ------- + Any + The API response. + """ if additional is None: additional = [] info = self.photos_list[api_name] @@ -80,12 +225,53 @@ def _list_folders(self, folder_id: int, limit: int, offset: int, additional: Opt return self.request_data(api_name, api_path, req_param) def count_folders(self, folder_id: int = 0) -> dict[str, object] | str: + """ + Count folders in Personal Space. + + Parameters + ---------- + folder_id : int, optional + The parent folder ID. Default is 0. + + Returns + ------- + dict[str, object] or str + The count of folders or an error message. + """ return self._count_folders(folder_id, 'SYNO.Foto.Browse.Folder') def count_team_folders(self, folder_id: int = 0) -> dict[str, object] | str: + """ + Count folders in Team Space. + + Parameters + ---------- + folder_id : int, optional + The parent folder ID. Default is 0. + + Returns + ------- + dict[str, object] or str + The count of team folders or an error message. + """ return self._count_folders(folder_id, 'SYNO.FotoTeam.Browse.Folder') def _count_folders(self, folder_id: int, api_name: str) -> Any: + """ + Internal method to count folders. + + Parameters + ---------- + folder_id : int + The parent folder ID. + api_name : str + API name to use. + + Returns + ------- + Any + The API response. + """ info = self.photos_list[api_name] api_path = info['path'] req_param = {'version': info['maxVersion'], @@ -94,12 +280,55 @@ def _count_folders(self, folder_id: int, api_name: str) -> Any: return self.request_data(api_name, api_path, req_param) def lookup_folder(self, path: str) -> dict[str, object] | str: + """ + Lookup a folder by path in Personal Space. + + Parameters + ---------- + path : str + The folder path. + + Returns + ------- + dict[str, object] or str + The folder information or None if not found. + """ return self._lookup_folder(path, 'SYNO.FotoBrowse.Folder', 'SYNO.Foto.Browse.Folder') def lookup_team_folder(self, path: str) -> dict[str, object] | str: + """ + Lookup a folder by path in Team Space. + + Parameters + ---------- + path : str + The folder path. + + Returns + ------- + dict[str, object] or str + The folder information or None if not found. + """ return self._lookup_folder(path, 'SYNO.FotoTeam.Browse.Folder', 'SYNO.FotoTeam.Browse.Folder') def _lookup_folder(self, path: str, api_name_count: str, api_name_list: str) -> Optional[dict[str, object]]: + """ + Internal method to lookup a folder by path. + + Parameters + ---------- + path : str + The folder path. + api_name_count : str + API name for counting folders. + api_name_list : str + API name for listing folders. + + Returns + ------- + dict[str, object] or None + The folder information or None if not found. + """ parent = 0 found_path = '' folder = '' @@ -124,6 +353,21 @@ def _lookup_folder(self, path: str, api_name_count: str, api_name_list: str) -> return folder def get_album(self, album_id: str, additional: Optional[str | list[str]] = None) -> dict[str, object] | str: + """ + Retrieve information about a specific album. + + Parameters + ---------- + album_id : str + The album ID. + additional : str or list of str, optional + Additional fields to include. + + Returns + ------- + dict[str, object] or str + The album information or an error message. + """ if not isinstance(album_id, list): album_id = [album_id] if additional is None: @@ -137,6 +381,21 @@ def get_album(self, album_id: str, additional: Optional[str | list[str]] = None) return self.request_data(api_name, api_path, req_param) def list_albums(self, offset: int = 0, limit: int = 100) -> dict[str, object] | str: + """ + List albums. + + Parameters + ---------- + offset : int, optional + Number of albums to skip. Default is 0. + limit : int, optional + Maximum number of albums to return. Default is 100. + + Returns + ------- + dict[str, object] or str + The list of albums or an error message. + """ api_name = 'SYNO.Foto.Browse.Album' info = self.photos_list[api_name] api_path = info['path'] @@ -150,6 +409,23 @@ def suggest_condition(self, condition: Optional[list[str]] = None, user_id: Optional[str] = None ) -> dict[str, object] | str: + """ + Suggest album conditions based on a keyword. + + Parameters + ---------- + keyword : str + The keyword to suggest conditions for. + condition : list of str, optional + List of conditions to use. Default is ['general_tag']. + user_id : str, optional + User ID to use. If None, uses the current user. + + Returns + ------- + dict[str, object] or str + The suggested conditions or an error message. + """ if condition is None: condition = ['general_tag'] if user_id is None: @@ -164,6 +440,21 @@ def suggest_condition(self, return self.request_data(api_name, api_path, req_param) def create_album(self, name: str, condition: list[str]) -> dict[str, object] | str: + """ + Create a new album with the specified condition. + + Parameters + ---------- + name : str + The name of the album. + condition : list of str + The condition for the album. + + Returns + ------- + dict[str, object] or str + The API response for album creation. + """ api_name = 'SYNO.Foto.Browse.ConditionAlbum' info = self.photos_list[api_name] api_path = info['path'] @@ -173,6 +464,19 @@ def create_album(self, name: str, condition: list[str]) -> dict[str, object] | s return self.request_data(api_name, api_path, req_param) def delete_album(self, album_id: str) -> dict[str, object] | str: + """ + Delete an album by ID. + + Parameters + ---------- + album_id : str + The album ID. + + Returns + ------- + dict[str, object] or str + The API response for album deletion. + """ if not isinstance(album_id, list): album_id = [album_id] api_name = 'SYNO.Foto.Browse.Album' @@ -184,6 +488,21 @@ def delete_album(self, album_id: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def set_album_condition(self, folder_id: int, condition: list[str]) -> dict[str, object] | str: + """ + Set the condition for an album. + + Parameters + ---------- + folder_id : int + The folder ID. + condition : list of str + The condition to set. + + Returns + ------- + dict[str, object] or str + The API response for setting the condition. + """ api_name = 'SYNO.Foto.Browse.ConditionAlbum' info = self.photos_list[api_name] api_path = info['path'] @@ -198,6 +517,25 @@ def share_album(self, enabled: bool = True, expiration: int | str = 0 ) -> Any: + """ + Share an album with specified permissions. + + Parameters + ---------- + album_id : str + The album ID. + permission : str or list of str, optional + Permissions to set. + enabled : bool, optional + Whether sharing is enabled. Default is True. + expiration : int or str, optional + Expiration time for the share. Default is 0. + + Returns + ------- + Any + The API response for sharing the album. + """ self._share('SYNO.Foto.Sharing.Passphrase', policy='album', permission=permission, album_id=album_id, enabled=enabled, expiration=expiration) @@ -207,6 +545,25 @@ def share_team_folder(self, enabled: bool = True, expiration: int | str = 0 ) -> Any: + """ + Share a team folder with specified permissions. + + Parameters + ---------- + folder_id : int + The folder ID. + permission : str, optional + Permissions to set. + enabled : bool, optional + Whether sharing is enabled. Default is True. + expiration : int or str, optional + Expiration time for the share. Default is 0. + + Returns + ------- + Any + The API response for sharing the team folder. + """ self._share('SYNO.FotoTeam.Sharing.Passphrase', policy='folder', permission=permission, folder_id=folder_id, enabled=enabled, expiration=expiration) @@ -217,6 +574,27 @@ def _share(self, expiration: int | str, **kwargs ) -> dict[str, object] | Any: + """ + Internal method to share an album or folder. + + Parameters + ---------- + api_name : str + API name to use. + policy : str + Sharing policy. + permission : str + Permissions to set. + expiration : int or str + Expiration time for the share. + **kwargs + Additional keyword arguments. + + Returns + ------- + dict[str, object] or Any + The API response for sharing. + """ info = self.photos_list[api_name] api_path = info['path'] req_param = {'version': info['maxVersion'], @@ -236,6 +614,19 @@ def _share(self, return self.request_data(api_name, api_path, req_param) def list_shareable_users_and_groups(self, team_space_sharable_list: bool = False) -> dict[str, object] | str: + """ + List users and groups that can be shared with. + + Parameters + ---------- + team_space_sharable_list : bool, optional + Whether to include team space sharable list. Default is False. + + Returns + ------- + dict[str, object] or str + The list of users and groups or an error message. + """ api_name = 'SYNO.Foto.Sharing.Misc' info = self.photos_list[api_name] api_path = info['path'] @@ -247,44 +638,35 @@ def list_shareable_users_and_groups(self, team_space_sharable_list: bool = False def list_item_in_folders(self, offset: int = 0, limit: int = 0, folder_id: int = 0, sort_by: str = 'filename', sort_direction: str = 'desc', type: str = None, passphrase: str = None, additional: list = None) -> dict[str, object] | str: - """List all items in all folders in Personal Space - - Parameters - ---------- - offset : int - Specify how many shared folders are skipped before beginning to return listed shared folders. - - limit : int - Number of shared folders requested. Set to `0` to list all shared folders. - - folder_id : int - ID of folder - - sort_by : str, optional - Possible values: - - `filename` - - `filesize` - - `takentime` - - `item_type` - - sort_direction : str, optional - Possible values: `asc` or `desc`. Defaults to: `desc` - - passphrase : str, optional - Passphrase for a shared album - - additional : list[str] - Possible values: - `["thumbnail","resolution", "orientation", "video_convert", "video_meta", "provider_user_id", "exif", "tag", "description", "gps", "geocoding_id", "address", "person"]` - - type : str - Possible values: - - `photo`: Photo - - `video`: Video - - `live`: iPhone live photos' - """ - + List all items in all folders in Personal Space. + + Parameters + ---------- + offset : int + Specify how many shared folders are skipped before beginning to return listed shared folders. + limit : int + Number of shared folders requested. Set to `0` to list all shared folders. + folder_id : int + ID of folder. + sort_by : str, optional + Possible values: 'filename', 'filesize', 'takentime', 'item_type'. + sort_direction : str, optional + Possible values: 'asc' or 'desc'. Defaults to: 'desc'. + type : str, optional + Possible values: 'photo', 'video', 'live'. + passphrase : str, optional + Passphrase for a shared album. + additional : list, optional + Additional fields to include. + Possible values: + `["thumbnail","resolution", "orientation", "video_convert", "video_meta", "provider_user_id", "exif", "tag", "description", "gps", "geocoding_id", "address", "person"]`. + + Returns + ------- + dict[str, object] or str + The list of items or an error message. + """ api_name = 'SYNO.Foto.Browse.Item' info = self.photos_list[api_name] api_path = info['path'] @@ -301,6 +683,14 @@ def list_item_in_folders(self, offset: int = 0, limit: int = 0, folder_id: int = return self.request_data(api_name, api_path, req_param) def list_search_filters(self) -> dict[str, object] | str: + """ + List available search filters. + + Returns + ------- + dict[str, object] or str + The list of search filters or an error message. + """ api_name = 'SYNO.Foto.Search.Filter' info = self.photos_list[api_name] api_path = info['path'] @@ -309,6 +699,14 @@ def list_search_filters(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_guest_settings(self) -> dict[str, object] | str: + """ + Retrieve guest settings for Photos. + + Returns + ------- + dict[str, object] or str + The guest settings or an error message. + """ api_name = 'SYNO.Foto.Setting.Guest' info = self.photos_list[api_name] api_path = info['path'] From bc761e1e430d8882a41fe4a885488ef14142a8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 11:55:14 +0700 Subject: [PATCH 038/126] fix: synology_api/security_advisor.py update docstrings to comply with Numpydoc standards --- synology_api/security_advisor.py | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/synology_api/security_advisor.py b/synology_api/security_advisor.py index 18e4e128..03301d4e 100644 --- a/synology_api/security_advisor.py +++ b/synology_api/security_advisor.py @@ -1,11 +1,31 @@ +""" +Security Advisor API wrapper for Synology DSM. + +This module provides a class to interact with the Synology Security Advisor API. +""" + from __future__ import annotations from typing import Optional from . import base_api class SecurityAdvisor(base_api.BaseApi): + """ + Interface for Synology Security Advisor API. + + Provides methods to retrieve general info, scan results, checklists, + login activity, and configuration for Security Advisor. + """ def general_info(self) -> dict[str, object] | str: + """ + Retrieve general information about Security Advisor location configuration. + + Returns + ------- + dict[str, object] or str + The API response containing location configuration or an error message. + """ api_name = 'SYNO.SecurityAdvisor.Conf.Location' info = self.gen_list[api_name] api_path = info['path'] @@ -14,6 +34,14 @@ def general_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def security_scan(self) -> dict[str, object] | str: + """ + Retrieve the current security scan configuration. + + Returns + ------- + dict[str, object] or str + The API response containing security scan configuration or an error message. + """ api_name = 'SYNO.Core.SecurityScan.Conf' info = self.core_list[api_name] api_path = info['path'] @@ -22,6 +50,14 @@ def security_scan(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def checklist(self) -> dict[str, object] | str: + """ + Retrieve the checklist for the Security Advisor. + + Returns + ------- + dict[str, object] or str + The API response containing the checklist or an error message. + """ api_name = 'SYNO.SecurityAdvisor.Conf.Checklist' info = self.gen_list[api_name] api_path = info['path'] @@ -31,6 +67,21 @@ def checklist(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def login_activity(self, offset: int = 0, limit: int = 20) -> dict[str, object] | str: + """ + Retrieve login activity records. + + Parameters + ---------- + offset : int, optional + The starting index of the login activity list. Default is 0. + limit : int, optional + The maximum number of records to retrieve. Default is 20. + + Returns + ------- + dict[str, object] or str + The API response containing login activity records or an error message. + """ api_name = 'SYNO.SecurityAdvisor.LoginActivity' info = self.gen_list[api_name] api_path = info['path'] @@ -40,6 +91,14 @@ def login_activity(self, offset: int = 0, limit: int = 20) -> dict[str, object] return self.request_data(api_name, api_path, req_param) def advisor_config(self) -> dict[str, object] | str: + """ + Retrieve Security Advisor configuration. + + Returns + ------- + dict[str, object] or str + The API response containing advisor configuration or an error message. + """ api_name = 'SYNO.SecurityAdvisor.Conf' info = self.gen_list[api_name] api_path = info['path'] @@ -48,6 +107,14 @@ def advisor_config(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def scan_config(self) -> dict[str, object] | str: + """ + Retrieve custom group enumeration for security scan configuration. + + Returns + ------- + dict[str, object] or str + The API response containing custom group enumeration or an error message. + """ api_name = 'SYNO.Core.SecurityScan.Conf' info = self.gen_list[api_name] api_path = info['path'] From 1dc34d619f0b9a3f03000995d4830ec908173099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 12:00:39 +0700 Subject: [PATCH 039/126] fix: synology_api/snapshot.py update docstrings to comply with Numpydoc standards --- synology_api/snapshot.py | 1678 +++++++++++++++++++------------------- 1 file changed, 829 insertions(+), 849 deletions(-) diff --git a/synology_api/snapshot.py b/synology_api/snapshot.py index 8716a8f4..80bd45a9 100644 --- a/synology_api/snapshot.py +++ b/synology_api/snapshot.py @@ -1,3 +1,10 @@ +""" +Snapshot Replication API wrapper for Synology DSM. + +This module provides a class to interact with the Synology Snapshot Replication APIs. +The implementation is based on network inspection, as there is no official documentation. +""" + from __future__ import annotations from typing import Optional from . import base_api @@ -5,59 +12,61 @@ class Snapshot(base_api.BaseApi): - """Class for interacting with Snapshot Replication APIs. - - This class implements APIs to manage snapshots. - There is no documentation for these APIs, so the implementation is based on network inspection. - - Supported methods: - - Getters: - - Get all share/LUN snapshots - - Get all replications - - Get all LUNs - - - Setters: - - Set snapshot attributes - - - Actions: - - Create share/LUN snapshot (WORM support only for share snaps ATM) - - Delete share/LUN snapshot - - Sync replication - - Examples - -------- - List snapshots for a share/LUN: - ```python - from synology_api import snapshot - ss = snapshot.Snapshot('IP', 'PORT', 'USER', 'PASSWORD') - - resp_share = ss.list_snapshots('share_name') - resp_lun = ss.list_snapshots_lun('src_lun_uuid') - - print(resp_share, resp_lun) - ``` - - Create a snapshot for a share/LUN: - ```python - resp_share = ss.create_snapshot('share_name') - resp_lun = create_snapshot_lun('lun_id') - - print(resp_share, resp_lun) - ``` - - Delete snapshots for a share: - ```python - resp_share = ss.delete_snapshots('share_name', ['snapshot_name']) - resp_lun = ss.delete_snapshots_lun(['snapshot_uuid']) - - print(resp_share, resp_lun) - ``` - - Set attributes for a snapshot: - ```python - resp = ss.set_snapshot_attr('share_name', 'snapshot_name', description='new description', lock=True) - print(resp) - ``` + """ + Class for interacting with Snapshot Replication APIs. + + This class implements APIs to manage snapshots. + There is no documentation for these APIs, so the implementation is based on network inspection. + + Methods + ------- + Getters: + - Get all share/LUN snapshots + - Get all replications + - Get all LUNs + + Setters: + - Set snapshot attributes + + Actions: + - Create share/LUN snapshot (WORM support only for share snaps ATM) + - Delete share/LUN snapshot + - Sync replication + + Examples + -------- + List snapshots for a share/LUN: + ```python + from synology_api import snapshot + ss = snapshot.Snapshot('IP', 'PORT', 'USER', 'PASSWORD') + + resp_share = ss.list_snapshots('share_name') + resp_lun = ss.list_snapshots_lun('src_lun_uuid') + + print(resp_share, resp_lun) + ``` + + Create a snapshot for a share/LUN: + ```python + resp_share = ss.create_snapshot('share_name') + resp_lun = create_snapshot_lun('lun_id') + + print(resp_share, resp_lun) + ``` + + Delete snapshots for a share: + ```python + resp_share = ss.delete_snapshots('share_name', ['snapshot_name']) + resp_lun = ss.delete_snapshots_lun(['snapshot_uuid']) + + print(resp_share, resp_lun) + ``` + + Set attributes for a snapshot: + ```python + resp = ss.set_snapshot_attr('share_name', 'snapshot_name', description='new description', lock=True) + print(resp) + ``` """ def list_snapshots( @@ -68,67 +77,58 @@ def list_snapshots( offset: int = 0, limit: int = -1 ) -> dict[str, object]: - """List snapshots for a share. - - Parameters - ---------- - share_name : str - Name of the share to list snapshots for. - - attribute_filter : list[str], optional - List of attributes filter to apply. Defaults to `[]` (no filter). - - - Each attribute filter is a string in the format of `"attr==value"` or `"attr=value"` and optionally prefixed with `!` to negate the filter. - - - The following are examples of valid attribute filters: - - `["!hide==true", "desc==abc"]` -> hide is not true and desc is exactly abc. - - `["desc=abc"]` -> desc has abc in it. - - additional_attribute : list[str], optional - List of snapshot attributes whose values are included in the response. Defaults to `[]` (only time is returned). - - - Note that not all attributes are available via API. The following are confirmed to work: - - `"desc"` - - `"lock"` - - `"worm_lock"` - - `"schedule_snapshot"` - - offset : int, optional - Offset to start listing from. Defaults to `0`. - - limit : int, optional - Number of snapshots to return. Defaults to `-1` (all). - - Returns - ------- - dict[str, object] - API response if successful, error message if not. + """ + List snapshots for a share. + + Parameters + ---------- + share_name : str + Name of the share to list snapshots for. + attribute_filter : list[str], optional + List of attributes filter to apply. Defaults to `[]` (no filter). + Each attribute filter is a string in the format of `"attr==value"` or `"attr=value"` and optionally prefixed with `!` to negate the filter. + The following are examples of valid attribute filters: + - `["!hide==true", "desc==abc"]` -> hide is not true and desc is exactly abc. + - `["desc=abc"]` -> desc has abc in it. + additional_attribute : list[str], optional + List of snapshot attributes whose values are included in the response. Defaults to `[]` (only time is returned). + Note that not all attributes are available via API. The following are confirmed to work: + - `"desc"` + - `"lock"` + - `"worm_lock"` + - `"schedule_snapshot"` + offset : int, optional + Offset to start listing from. Defaults to `0`. + limit : int, optional + Number of snapshots to return. Defaults to `-1` (all). + + Returns + ------- + dict[str, object] + API response if successful, error message if not. - Examples - -------- - ```json - { - "data": { - "snapshots": [ - { - "desc": "", - "lock": true, - "schedule_snapshot": false, - "time": "GMT+09-2023.09.11-23.23.40", - "worm_lock": true, - "worm_lock_begin": "1694442321", - "worm_lock_day": "1", - "worm_lock_end": "1694528721" - } - ], - "total": 1 - }, - "success": true - } - ``` + Examples + -------- + ```json + { + "data": { + "snapshots": [ + { + "desc": "", + "lock": true, + "schedule_snapshot": false, + "time": "GMT+09-2023.09.11-23.23.40", + "worm_lock": true, + "worm_lock_begin": "1694442321", + "worm_lock_day": "1", + "worm_lock_end": "1694528721" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Share.Snapshot' @@ -154,86 +154,83 @@ def list_snapshots_lun( src_lun_uuid: str, additional: list[str] = ["locked_app_keys", "is_worm_locked"] ) -> dict[str, object]: - """List snapshots for a LUN. - - Parameters - ---------- - src_lun_uuid : str - UUID of the source LUN to list snapshots for. - - additional : list[str], optional - Additional fields to retrieve. Specify `[]` to get only basic information. - - Defaults to `["locked_app_keys", "is_worm_locked"]` - - - Possible values: - - `"locked_app_keys"` -> If snapshot is preserved by the system, the locking package key will be returned. - - `"is_worm_locked"` -> Whether the snapshot is locked by WORM. - - Returns - ------- - dict[str, object] - Dictionary containing the LUN snapshots information. + """ + List snapshots for a LUN. + + Parameters + ---------- + src_lun_uuid : str + UUID of the source LUN to list snapshots for. + additional : list[str], optional + Additional fields to retrieve. Specify `[]` to get only basic information. + Defaults to `["locked_app_keys", "is_worm_locked"]` + Possible values: + - `"locked_app_keys"` -> If snapshot is preserved by the system, the locking package key will be returned. + - `"is_worm_locked"` -> Whether the snapshot is locked by WORM. + + Returns + ------- + dict[str, object] + Dictionary containing the LUN snapshots information. - Examples - -------- - ```json - { - "data": { - "count": 2, - "snapshots": [ - { - "create_time": 1742739365, - "description": "test", - "is_app_consistent": false, - "is_user_locked": true, - "is_worm_locked": false, - "locked_app_keys": [], - "mapped_size": 0, - "name": "SnapShot-1", - "parent_lun_id": 6, - "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "root_path": "/volume2", - "snapshot_id": 1, - "snapshot_time": 1742739365, - "status": "Healthy", - "taken_by": "user", - "total_size": 1073741824, - "type": 2, - "uuid": "fb388ec7-f23a-4011-8d24-08ad9b1fef34", - "version": "d4236543-510f-4269-ae73-7bc789aaa763", - "worm_lock_day": "0" - }, - { - "create_time": 1742833700, - "description": "Snapshot taken by [Synology API]", - "is_app_consistent": false, - "is_user_locked": false, - "is_worm_locked": false, - "locked_app_keys": [ - "SnapshotReplication-synodr-657f3c72-f357-400d-96df-bb8ae4e5051f" - ], - "mapped_size": 0, - "name": "SnapShot-2", - "parent_lun_id": 6, - "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "root_path": "/volume2", - "snapshot_id": 2, - "snapshot_time": 1742833700, - "status": "Healthy", - "taken_by": "user", - "total_size": 1073741824, - "type": 2, - "uuid": "e981770c-f56d-4cb2-b7a7-4c4b11ba8eaa", - "version": "58ee3b1a-192d-46fe-9cf3-0960e2a8670b", - "worm_lock_day": "0" - } - ] - }, - "success": true - } - ``` + Examples + -------- + ```json + { + "data": { + "count": 2, + "snapshots": [ + { + "create_time": 1742739365, + "description": "test", + "is_app_consistent": false, + "is_user_locked": true, + "is_worm_locked": false, + "locked_app_keys": [], + "mapped_size": 0, + "name": "SnapShot-1", + "parent_lun_id": 6, + "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "root_path": "/volume2", + "snapshot_id": 1, + "snapshot_time": 1742739365, + "status": "Healthy", + "taken_by": "user", + "total_size": 1073741824, + "type": 2, + "uuid": "fb388ec7-f23a-4011-8d24-08ad9b1fef34", + "version": "d4236543-510f-4269-ae73-7bc789aaa763", + "worm_lock_day": "0" + }, + { + "create_time": 1742833700, + "description": "Snapshot taken by [Synology API]", + "is_app_consistent": false, + "is_user_locked": false, + "is_worm_locked": false, + "locked_app_keys": [ + "SnapshotReplication-synodr-657f3c72-f357-400d-96df-bb8ae4e5051f" + ], + "mapped_size": 0, + "name": "SnapShot-2", + "parent_lun_id": 6, + "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "root_path": "/volume2", + "snapshot_id": 2, + "snapshot_time": 1742833700, + "status": "Healthy", + "taken_by": "user", + "total_size": 1073741824, + "type": 2, + "uuid": "e981770c-f56d-4cb2-b7a7-4c4b11ba8eaa", + "version": "58ee3b1a-192d-46fe-9cf3-0960e2a8670b", + "worm_lock_day": "0" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ISCSI.LUN' @@ -276,187 +273,178 @@ def list_luns( "snapshot_info", ] ) -> dict[str, object]: - """List available LUNs - - Parameters - ---------- - types : list[str], optional - Type of LUNS to retrieve. - - - Defaults to `[ "BLOCK", "FILE", "THIN", "ADV", "SINK", "CINDER", "CINDER_BLUN", "CINDER_BLUN_THICK", "BLUN", "BLUN_THICK", "BLUN_SINK", "BLUN_THICK_SINK" ]`. - - - Possible values: - - `"BLOCK"` - - `"FILE"` - - `"THIN"` - - `"ADV"` - - `"SINK"` - - `"CINDER"` - - `"CINDER_BLUN"` - - `"CINDER_BLUN_THICK"` - - `"BLUN"` - - `"BLUN_THICK"` - - `"BLUN_SINK"` - - `"BLUN_THICK_SINK"` - - additional_info : list[str], optional - Additional LUN information to include in the response. Specify `[]` to get only basic information. - - - Defaults to `[ "is_action_locked", "is_mapped", "extent_size", "allocated_size", "status", "allow_bkpobj", "flashcache_status", "family_config", "snapshot_info" ]`. - - - Possible values: - - `"is_action_locked"` - - `"is_mapped"` - - `"extent_size"` - - `"allocated_size"` - - `"status"` - - `"allow_bkpobj"` - - `"flashcache_status"` - - `"family_config"` - - `"snapshot_info"` - - Returns - ------- - dict[str, object] - A dictionary containing a list of LUNs present in the system. + """ + List available LUNs. + + Parameters + ---------- + types : list[str], optional + Type of LUNS to retrieve. + Defaults to `[ "BLOCK", "FILE", "THIN", "ADV", "SINK", "CINDER", "CINDER_BLUN", "CINDER_BLUN_THICK", "BLUN", "BLUN_THICK", "BLUN_SINK", "BLUN_THICK_SINK" ]`. + Possible values: + - `"BLOCK"` + - `"FILE"` + - `"THIN"` + - `"ADV"` + - `"SINK"` + - `"CINDER"` + - `"CINDER_BLUN"` + - `"CINDER_BLUN_THICK"` + - `"BLUN"` + - `"BLUN_THICK"` + - `"BLUN_SINK"` + - `"BLUN_THICK_SINK"` + additional_info : list[str], optional + Additional LUN information to include in the response. Specify `[]` to get only basic information. + Defaults to `[ "is_action_locked", "is_mapped", "extent_size", "allocated_size", "status", "allow_bkpobj", "flashcache_status", "family_config", "snapshot_info" ]`. + Possible values: + - `"is_action_locked"` + - `"is_mapped"` + - `"extent_size"` + - `"allocated_size"` + - `"status"` + - `"allow_bkpobj"` + - `"flashcache_status"` + - `"family_config"` + - `"snapshot_info"` + + Returns + ------- + dict[str, object] + A dictionary containing a list of LUNs present in the system. - Examples - -------- - ```json - { - "data": { - "luns": [ - { - "allocated_size": 0, - "block_size": 512, - "create_from": "", - "description": "", - "dev_attribs": [ - { - "dev_attrib": "emulate_3pc", - "enable": 1 - }, - { - "dev_attrib": "emulate_tpws", - "enable": 1 - }, - { - "dev_attrib": "emulate_caw", - "enable": 1 - }, - { - "dev_attrib": "emulate_tpu", - "enable": 1 - }, - { - "dev_attrib": "emulate_fua_write", - "enable": 0 - }, - { - "dev_attrib": "emulate_sync_cache", - "enable": 0 - }, - { - "dev_attrib": "can_snapshot", - "enable": 1 - } - ], - "dev_attribs_bitmap": 31, - "dev_config": "", - "dev_qos": { - "dev_limit": 0, - "dev_reservation": 0, - "dev_weight": 0, - "iops_enable": 0 + Examples + -------- + ```json + { + "data": { + "luns": [ + { + "allocated_size": 0, + "block_size": 512, + "create_from": "", + "description": "", + "dev_attribs": [ + { + "dev_attrib": "emulate_3pc", + "enable": 1 }, - "direct_io_pattern": 0, - "extent_size": 0, - "family_config": { - "parent_lun_name": "", - "parent_lun_uuid": "", - "parent_snapshot_time": 0, - "parent_snapshot_uuid": "" + { + "dev_attrib": "emulate_tpws", + "enable": 1 }, - "flashcache_id": -1, - "flashcache_status": "no_cache", - "is_action_locked": false, - "is_mapped": true, - "location": "/volume2", - "lun_id": 6, - "name": "LUN-1", - "restored_time": 0, - "retention": null, - "scheduled_task": [ - { - "general": { - "snap_rotate": true, - "snap_type": "app", - "task_enabled": false, - "task_name": "Task LUN-1", - "tid": -1, - "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - }, - "schedule": { - "date": "2025/3/24", - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "min": 0, - "monthly_week": [], - "next_trigger_time": "", - "repeat": 0, - "repeat_hour": 0, - "repeat_hour_store_config": null, - "repeat_min": 0, - "repeat_min_store_config": null, - "week_name": "0,1,2,3,4,5,6" - } + { + "dev_attrib": "emulate_caw", + "enable": 1 + }, + { + "dev_attrib": "emulate_tpu", + "enable": 1 + }, + { + "dev_attrib": "emulate_fua_write", + "enable": 0 + }, + { + "dev_attrib": "emulate_sync_cache", + "enable": 0 + }, + { + "dev_attrib": "can_snapshot", + "enable": 1 + } + ], + "dev_attribs_bitmap": 31, + "dev_config": "", + "dev_qos": { + "dev_limit": 0, + "dev_reservation": 0, + "dev_weight": 0, + "iops_enable": 0 + }, + "direct_io_pattern": 0, + "extent_size": 0, + "family_config": { + "parent_lun_name": "", + "parent_lun_uuid": "", + "parent_snapshot_time": 0, + "parent_snapshot_uuid": "" + }, + "flashcache_id": -1, + "flashcache_status": "no_cache", + "is_action_locked": false, + "is_mapped": true, + "location": "/volume2", + "lun_id": 6, + "name": "LUN-1", + "restored_time": 0, + "retention": null, + "scheduled_task": [ + { + "general": { + "snap_rotate": true, + "snap_type": "app", + "task_enabled": false, + "task_name": "Task LUN-1", + "tid": -1, + "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + }, + "schedule": { + "date": "2025/3/24", + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "min": 0, + "monthly_week": [], + "next_trigger_time": "", + "repeat": 0, + "repeat_hour": 0, + "repeat_hour_store_config": null, + "repeat_min": 0, + "repeat_min_store_config": null, + "week_name": "0,1,2,3,4,5,6" } - ], - "size": 1073741824, - "snapshots": [ - { - "create_time": 1742739365, - "description": "test", - "is_app_consistent": false, - "is_user_locked": true, - "mapped_size": 0, - "name": "SnapShot-1", - "parent_lun_id": 6, - "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "root_path": "/volume2", - "snapshot_id": 1, - "snapshot_time": 1742739365, - "status": { - "progress": { - "percent": -1, - "step": "waiting" - }, - "type": "Healthy" + } + ], + "size": 1073741824, + "snapshots": [ + { + "create_time": 1742739365, + "description": "test", + "is_app_consistent": false, + "is_user_locked": true, + "mapped_size": 0, + "name": "SnapShot-1", + "parent_lun_id": 6, + "parent_uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "root_path": "/volume2", + "snapshot_id": 1, + "snapshot_time": 1742739365, + "status": { + "progress": { + "percent": -1, + "step": "waiting" }, - "taken_by": "user", - "total_size": 1073741824, - "type": 2, - "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "version": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - } - ], - "status": "normal", - "type": 263, - "type_str": "BLUN", - "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "vpd_unit_sn": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - } - ] - }, - "success": true - } - ``` - + "type": "Healthy" + }, + "taken_by": "user", + "total_size": 1073741824, + "type": 2, + "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "version": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + } + ], + "status": "normal", + "type": 263, + "type_str": "BLUN", + "uuid": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "vpd_unit_sn": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ISCSI.LUN' @@ -486,331 +474,328 @@ def list_replication_plans( "retention_lock_report" ] ) -> dict[str, object]: - """List replication plans. - - Parameters - ---------- - additional_info : list[str], optional - List of additional information to include in the response. Specify `[]` to get only basic information. - - - Defaults to `["sync_policy", "sync_report", "main_site_info", "dr_site_info", "can_do", "op_info", "last_op_info", "topology", "testfailover_info", "retention_lock_report"]`. - - - Possible values: - - `"sync_policy"` -> Information about the sync policy as schedule, retention, lock, etc. - - `"sync_report"` -> Information about the previous runs and their results / error count. - - `"main_site_info"` -> Information about the main site. - - `"dr_site_info"` -> Information about the destination site. - - `"can_do"` -> Information about the actions that can be performed on the replication plan. - - `"op_info"` -> Information about the current operation (restoring / syncing / etc.). - - `"last_op_info"` -> Information about the last operation. - - `"topology"` -> Information about the replication topology (main / dr site & plan information). - - `"testfailover_info"` -> Information about the previous test failover operation. - - `"retention_lock_report"` -> Information about the first / last snapshot. - - Returns - ------- - dict[str, object] - API response if successful, error message if not + """ + List replication plans. + + Parameters + ---------- + additional_info : list[str], optional + List of additional information to include in the response. Specify `[]` to get only basic information. + Defaults to `["sync_policy", "sync_report", "main_site_info", "dr_site_info", "can_do", "op_info", "last_op_info", "topology", "testfailover_info", "retention_lock_report"]`. + Possible values: + - `"sync_policy"` -> Information about the sync policy as schedule, retention, lock, etc. + - `"sync_report"` -> Information about the previous runs and their results / error count. + - `"main_site_info"` -> Information about the main site. + - `"dr_site_info"` -> Information about the destination site. + - `"can_do"` -> Information about the actions that can be performed on the replication plan. + - `"op_info"` -> Information about the current operation (restoring / syncing / etc.). + - `"last_op_info"` -> Information about the last operation. + - `"topology"` -> Information about the replication topology (main / dr site & plan information). + - `"testfailover_info"` -> Information about the previous test failover operation. + - `"retention_lock_report"` -> Information about the first / last snapshot. + + Returns + ------- + dict[str, object] + API response if successful, error message if not. - Examples - -------- - ```json - { - "data": { - "plans": [{ - "additional": { - "can_do": { - "can_cleanup_testfailover": false, - "can_delete": true, - "can_edit": true, - "can_export": false, - "can_failover": false, - "can_import": false, - "can_switchover": true, - "can_sync": true, - "can_testfailover": true, - "candidate_reprotect_new_mainsite": null - }, - "dr_site_info": { - "hostname": "hostname", - "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "op_info": { - "op_progress": { - "percentage": -1 - }, - "op_status": 1 - }, - "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "role": 2, - "status": 1, - "target_id": "api-1", - "target_name": "api-1" - }, - "last_op_info": { - "err_code": 0, - "is_success": true, - "op_status": 16, - "update_time": 1742739562 - }, - "main_site_info": { - "hostname": "hostname", - "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "op_info": { - "op_progress": { - "percentage": -1 - }, - "op_status": 1 + Examples + -------- + ```json + { + "data": { + "plans": [{ + "additional": { + "can_do": { + "can_cleanup_testfailover": false, + "can_delete": true, + "can_edit": true, + "can_export": false, + "can_failover": false, + "can_import": false, + "can_switchover": true, + "can_sync": true, + "can_testfailover": true, + "candidate_reprotect_new_mainsite": null + }, + "dr_site_info": { + "hostname": "hostname", + "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "op_info": { + "op_progress": { + "percentage": -1 }, - "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "role": 1, - "status": 1, - "target_id": "api", - "target_name": "api" + "op_status": 1 }, + "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "role": 2, + "status": 1, + "target_id": "api-1", + "target_name": "api-1" + }, + "last_op_info": { + "err_code": 0, + "is_success": true, + "op_status": 16, + "update_time": 1742739562 + }, + "main_site_info": { + "hostname": "hostname", + "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", "op_info": { "op_progress": { "percentage": -1 }, "op_status": 1 }, - "retention_lock_report": { - "first_snapshot": "GMT+01-2025.03.23-15.17.39", - "last_snapshot": "GMT+01-2025.03.23-15.18.46", - "retain_first": false + "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "role": 1, + "status": 1, + "target_id": "api", + "target_name": "api" + }, + "op_info": { + "op_progress": { + "percentage": -1 }, - "sync_policy": { - "enabled": true, - "is_app_aware": false, - "is_send_encrypted": false, - "is_sync_local_snapshots": false, - "mode": 2, - "next_trigger_time": 1742770800, - "notify_time_in_min": 720, - "readable_next_trigger_time": "Mon Mar 24 00:00:00 2025", - "schedule": { - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "min": 0, - "repeat_hour": 0, - "repeat_min": 0, - "week_name": "0,1,2,3,4,5,6" - }, - "sync_window": { - "enabled": false, - "window": [ - 16777215, - 16777215, - 16777215, - 16777215, - 16777215, - 16777215, - 16777215 - ] - }, - "worm_lock_day": 7, - "worm_lock_enable": false, - "worm_lock_notify_time": 0 + "op_status": 1 + }, + "retention_lock_report": { + "first_snapshot": "GMT+01-2025.03.23-15.17.39", + "last_snapshot": "GMT+01-2025.03.23-15.18.46", + "retain_first": false + }, + "sync_policy": { + "enabled": true, + "is_app_aware": false, + "is_send_encrypted": false, + "is_sync_local_snapshots": false, + "mode": 2, + "next_trigger_time": 1742770800, + "notify_time_in_min": 720, + "readable_next_trigger_time": "Mon Mar 24 00:00:00 2025", + "schedule": { + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "min": 0, + "repeat_hour": 0, + "repeat_min": 0, + "week_name": "0,1,2,3,4,5,6" }, - "sync_report": { - "fail_sync_count": 0, - "recent_records": [ - { - "begin_time": 1742739460, - "current_speed": 0, - "data_size_byte": 750513392, - "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "elapsed_time": 37, - "extra": { - "site_task": { - "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "task_op": 2 - } - }, - "finish_time": 1742739497, - "is_done": true, - "is_stopped": false, - "is_success": true, - "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "readable_begin_time": "Sun Mar 23 15:17:40 2025", - "readable_finish_time": "Sun Mar 23 15:18:17 2025", - "snapshot_version": "GMT+01-2025.03.23-15.17.39", - "sync_size_byte": 750513392, - "total_size_byte": 750513392, - "update_time": 1742739497, - "version": 3 + "sync_window": { + "enabled": false, + "window": [ + 16777215, + 16777215, + 16777215, + 16777215, + 16777215, + 16777215, + 16777215 + ] + }, + "worm_lock_day": 7, + "worm_lock_enable": false, + "worm_lock_notify_time": 0 + }, + "sync_report": { + "fail_sync_count": 0, + "recent_records": [ + { + "begin_time": 1742739460, + "current_speed": 0, + "data_size_byte": 750513392, + "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "elapsed_time": 37, + "extra": { + "site_task": { + "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "task_op": 2 + } + }, + "finish_time": 1742739497, + "is_done": true, + "is_stopped": false, + "is_success": true, + "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "readable_begin_time": "Sun Mar 23 15:17:40 2025", + "readable_finish_time": "Sun Mar 23 15:18:17 2025", + "snapshot_version": "GMT+01-2025.03.23-15.17.39", + "sync_size_byte": 750513392, + "total_size_byte": 750513392, + "update_time": 1742739497, + "version": 3 + }, + { + "begin_time": 1742739528, + "current_speed": 0, + "data_size_byte": 8210, + "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "elapsed_time": 28, + "extra": { + "site_task": { + "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "task_op": 2 + } }, - { - "begin_time": 1742739528, - "current_speed": 0, - "data_size_byte": 8210, - "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "elapsed_time": 28, - "extra": { - "site_task": { - "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "task_op": 2 - } + "finish_time": 1742739556, + "is_done": true, + "is_stopped": false, + "is_success": true, + "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "readable_begin_time": "Sun Mar 23 15:18:48 2025", + "readable_finish_time": "Sun Mar 23 15:19:16 2025", + "snapshot_version": "GMT+01-2025.03.23-15.18.46", + "sync_size_byte": 8210, + "total_size_byte": 8210, + "update_time": 1742739556, + "version": 3 + } + ], + "success_sync_count": 2, + "syncing_record": null, + "total_success_sync_size_byte": 750521602, + "total_success_sync_time_sec": 65 + }, + "testfailover_info": null, + "topology": { + "links": [ + { + "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + } + ], + "sites": [ + { + "addr": "", + "hostname": "hostname", + "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "plans": [ + { + "additional": { + "sync_policy": { + "enabled": true, + "is_app_aware": false, + "is_send_encrypted": false, + "is_sync_local_snapshots": false, + "mode": 2, + "next_trigger_time": 1742770800, + "notify_time_in_min": 720, + "readable_next_trigger_time": "Mon Mar 24 00:00:00 2025", + "schedule": { + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "min": 0, + "repeat_hour": 0, + "repeat_min": 0, + "week_name": "0,1,2,3,4,5,6" + }, + "sync_window": { + "enabled": false, + "window": [ + 16777215, + 16777215, + 16777215, + 16777215, + 16777215, + 16777215, + 16777215 + ] + }, + "worm_lock_day": 7, + "worm_lock_enable": false, + "worm_lock_notify_time": 0 + } + }, + "is_to_local": true, + "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "remote_target_name": "api-1", + "role": 1, + "status": 1, + "target_id": "api", + "target_name": "api" }, - "finish_time": 1742739556, - "is_done": true, - "is_stopped": false, - "is_success": true, - "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "readable_begin_time": "Sun Mar 23 15:18:48 2025", - "readable_finish_time": "Sun Mar 23 15:19:16 2025", - "snapshot_version": "GMT+01-2025.03.23-15.18.46", - "sync_size_byte": 8210, - "total_size_byte": 8210, - "update_time": 1742739556, - "version": 3 - } - ], - "success_sync_count": 2, - "syncing_record": null, - "total_success_sync_size_byte": 750521602, - "total_success_sync_time_sec": 65 - }, - "testfailover_info": null, - "topology": { - "links": [ - { - "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" - } - ], - "sites": [ - { - "addr": "", - "hostname": "hostname", - "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "plans": [ - { - "additional": { - "sync_policy": { - "enabled": true, - "is_app_aware": false, - "is_send_encrypted": false, - "is_sync_local_snapshots": false, - "mode": 2, - "next_trigger_time": 1742770800, - "notify_time_in_min": 720, - "readable_next_trigger_time": "Mon Mar 24 00:00:00 2025", - "schedule": { - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "min": 0, - "repeat_hour": 0, - "repeat_min": 0, - "week_name": "0,1,2,3,4,5,6" - }, - "sync_window": { - "enabled": false, - "window": [ - 16777215, - 16777215, - 16777215, - 16777215, - 16777215, - 16777215, - 16777215 - ] - }, - "worm_lock_day": 7, - "worm_lock_enable": false, - "worm_lock_notify_time": 0 - } - }, - "is_to_local": true, - "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "remote_target_name": "api-1", - "role": 1, - "status": 1, - "target_id": "api", - "target_name": "api" + ], + "status": 1 + }, + { + "addr": "", + "hostname": "hostname2", + "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "plans": [ + { + "additional": { + "sync_policy": { + "enabled": true, + "is_app_aware": false, + "is_send_encrypted": true, + "is_sync_local_snapshots": false, + "mode": 2, + "next_trigger_time": 1742770800, + "notify_time_in_min": 720, + "readable_next_trigger_time": "Mon Mar 24 00:00:00 2025", + "schedule": { + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "min": 0, + "repeat_hour": 0, + "repeat_min": 0, + "week_name": "0,1,2,3,4,5,6" + }, + "sync_window": { + "enabled": false, + "window": [ + 16777215, + 16777215, + 16777215, + 16777215, + 16777215, + 16777215, + 16777215 + ] + }, + "worm_lock_day": 7, + "worm_lock_enable": false, + "worm_lock_notify_time": 0 + } }, - ], - "status": 1 - }, - { - "addr": "", - "hostname": "hostname2", - "node_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "plans": [ - { - "additional": { - "sync_policy": { - "enabled": true, - "is_app_aware": false, - "is_send_encrypted": true, - "is_sync_local_snapshots": false, - "mode": 2, - "next_trigger_time": 1742770800, - "notify_time_in_min": 720, - "readable_next_trigger_time": "Mon Mar 24 00:00:00 2025", - "schedule": { - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "min": 0, - "repeat_hour": 0, - "repeat_min": 0, - "week_name": "0,1,2,3,4,5,6" - }, - "sync_window": { - "enabled": false, - "window": [ - 16777215, - 16777215, - 16777215, - 16777215, - 16777215, - 16777215, - 16777215 - ] - }, - "worm_lock_day": 7, - "worm_lock_enable": false, - "worm_lock_notify_time": 0 - } - }, - "is_to_local": false, - "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "remote_target_name": "api", - "role": 2, - "status": 1, - "target_id": "api", - "target_name": "api" - } - ], - "status": 1 - } - ], - "target": { - "target_id": "api", - "target_type": 2 + "is_to_local": false, + "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "remote_target_name": "api", + "role": 2, + "status": 1, + "target_id": "api", + "target_name": "api" + } + ], + "status": 1 } + ], + "target": { + "target_id": "api", + "target_type": 2 } - }, - "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "is_to_local": true, - "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "role": 1, - "role_str": "mainsite", - "solution_type": 1, - "sync_mode": 2, - "target_id": "api", - "target_type": 2 - }] - }, - "success": true - } - ``` + } + }, + "dr_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "is_to_local": true, + "main_site": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "plan_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "role": 1, + "role_str": "mainsite", + "solution_type": 1, + "sync_mode": 2, + "target_id": "api", + "target_type": 2 + }] + }, + "success": true + } + ``` """ api_name = 'SYNO.DR.Plan' @@ -833,40 +818,36 @@ def create_snapshot( immutable: bool = False, immutable_days: int = 7, ) -> dict[str, object]: - """Create a snapshot for a share. - - Parameters - ---------- - share_name : str - Name of the share to create a snapshot for. - - description : str, optional - Description of the snapshot. Defaults to `""`. - - lock : bool, optional - Whether to lock the snapshot. Defaults to `False`. - - immutable : bool, optional - Whether to make the snapshot immutable. Defaults to `False`. - - immutable_days : int, optional - Number of days to make the snapshot immutable for. Defaults to `7`. - - Must be greater than `0`. Mandatory if immutable is `True`. - - Returns - ------- - dict[str, object] - API response if successful, error message if not. + """ + Create a snapshot for a share. + + Parameters + ---------- + share_name : str + Name of the share to create a snapshot for. + description : str, optional + Description of the snapshot. Defaults to `""`. + lock : bool, optional + Whether to lock the snapshot. Defaults to `False`. + immutable : bool, optional + Whether to make the snapshot immutable. Defaults to `False`. + immutable_days : int, optional + Number of days to make the snapshot immutable for. Defaults to `7`. + Must be greater than `0`. Mandatory if immutable is `True`. + + Returns + ------- + dict[str, object] + API response if successful, error message if not. - Examples - -------- - ```json - { - "data": "GMT+09-2023.09.12-00.33.20", - "success": true - } - ``` + Examples + -------- + ```json + { + "data": "GMT+09-2023.09.12-00.33.20", + "success": true + } + ``` """ api_name = 'SYNO.Core.Share.Snapshot' @@ -898,30 +879,32 @@ def delete_snapshots( share_name: str, snapshots: list[str] ) -> dict[str, object]: - """Delete snapshots for a share. - - Warning: This action removes data from the file system. Use with caution. + """ + Delete snapshots for a share. - Parameters - ---------- - share_name : str - Name of the share to delete snapshots for. + Parameters + ---------- + share_name : str + Name of the share to delete snapshots for. + snapshots : list[str] + List of snapshots to delete. - snapshots : list[str] - List of snapshots to delete. + Returns + ------- + dict[str, object] + API response if successful, error message if not. - Returns - ------- - dict[str, object] - API response if successful, error message if not. + Notes + ----- + Warning: This action removes data from the file system. Use with caution. - Examples - -------- - ```json - { - "success": true - } - ``` + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.Share.Snapshot' @@ -946,41 +929,37 @@ def set_snapshot_attr( immutable: Optional[bool] = None, immutable_days: Optional[int] = None ) -> dict[str, object]: - """Set attributes for a snapshot. - - Parameters - ---------- - share_name : str - Name of the share to set attributes for - - snapshot : str - Name of the snapshot to set attributes for - - description : str, optional - Description of the snapshot. Defaults to `None` (no change). - - lock : bool, optional - Whether to lock the snapshot. Defaults to `None` (no change). - - immutable : bool, optional - Whether to make the snapshot immutable. Defaults to `None` (no change). - - immutable_days : int, optional - Number of days to make the snapshot immutable for. Defaults to `None` (no change). - Must be greater than `0`. Mandatory if immutable is `True`. - - Returns - ------- - dict[str, object] - API response if successful, error message if not. + """ + Set attributes for a snapshot. + + Parameters + ---------- + share_name : str + Name of the share to set attributes for. + snapshot : str + Name of the snapshot to set attributes for. + description : str, optional + Description of the snapshot. Defaults to `None` (no change). + lock : bool, optional + Whether to lock the snapshot. Defaults to `None` (no change). + immutable : bool, optional + Whether to make the snapshot immutable. Defaults to `None` (no change). + immutable_days : int, optional + Number of days to make the snapshot immutable for. Defaults to `None` (no change). + Must be greater than `0`. Mandatory if immutable is `True`. + + Returns + ------- + dict[str, object] + API response if successful, error message if not. - Examples - -------- - ```json - { - "success": true - } - ``` + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.Share.Snapshot' @@ -1020,31 +999,30 @@ def sync_replication( lock_snapshot: bool = True, description: str = "Snapshot taken by [Synology API]", ) -> dict[str, object]: - """Trigger a sync for a replication plan. - - Parameters - ---------- - plan_id : str - ID of the replication plan to sync. - - lock_snapshot : bool, optional - Whether to lock the snapshot to prevent rotation. Defaults to `True`. - - description : str, optional - Description of the snapshot. Defaults to `Snapshot taken by [Synology API]`. - - Returns - ------- - dict[str, object] - API response if successful + """ + Trigger a sync for a replication plan. + + Parameters + ---------- + plan_id : str + ID of the replication plan to sync. + lock_snapshot : bool, optional + Whether to lock the snapshot to prevent rotation. Defaults to `True`. + description : str, optional + Description of the snapshot. Defaults to `Snapshot taken by [Synology API]`. + + Returns + ------- + dict[str, object] + API response if successful. - Examples - -------- - ```json - { - "success": true - } - ``` + Examples + -------- + ```json + { + "success": true + } + ``` """ plans = self.list_replication_plans( @@ -1078,40 +1056,40 @@ def create_snapshot_lun( lock: bool = True, app_aware: bool = True ) -> dict[str, object]: - """Create a snapshot for a LUN. - - Note: At the moment, it does not support creating WORM snapshots. - - Parameters - ---------- - lun_id : str - ID of the LUN to create a snapshot for - - description : str, optional - Description of the snapshot. Defaults to `Snapshot taken by [Synology API]`. - - lock : bool, optional - Whether to lock the snapshot. Defaults to `True`. - - app_aware : bool, optional - Whether to make the snapshot application aware. Defaults to `True`. - - Returns - ------- - dict[str, object] - API response if successful + """ + Create a snapshot for a LUN. + + Parameters + ---------- + lun_id : str + ID of the LUN to create a snapshot for. + description : str, optional + Description of the snapshot. Defaults to `Snapshot taken by [Synology API]`. + lock : bool, optional + Whether to lock the snapshot. Defaults to `True`. + app_aware : bool, optional + Whether to make the snapshot application aware. Defaults to `True`. + + Returns + ------- + dict[str, object] + API response if successful. + + Notes + ----- + At the moment, it does not support creating WORM snapshots. - Examples - -------- - ```json - { - "data": { - "snapshot_id": 4, - "snapshot_uuid": "31aa7808-9ffc-4689-bb70-262bb1665c9b" - }, - "success": true - } - ``` + Examples + -------- + ```json + { + "data": { + "snapshot_id": 4, + "snapshot_uuid": "31aa7808-9ffc-4689-bb70-262bb1665c9b" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ISCSI.LUN' @@ -1130,41 +1108,43 @@ def create_snapshot_lun( return self.request_data(api_name, api_path, req_param) def delete_snapshots_lun(self, snapshot_uuids: list[str]) -> dict[str, object]: - """Delete snapshots for a LUN. - - Warning: This action removes data from the file system. Use with caution. - - Parameters - ---------- - snapshot_uuids : list[str] - List of UUIDs of the snapshots to delete. - - Returns - ------- - dict[str, object] - API response if successful. + """ + Delete snapshots for a LUN. + Parameters + ---------- + snapshot_uuids : list[str] + List of UUIDs of the snapshots to delete. - If deletion fails, an error code is returned alonside the snapshot uuid: - ```json - { - "data": [ - { - "5c9bf4a7-05ea-4cb8-b9e0-e0b0ca1186b0": 18990540 - } - ], - "success": true - } - ``` + Returns + ------- + dict[str, object] + API response if successful. - Examples - -------- + If deletion fails, an error code is returned alongside the snapshot uuid: ```json { - "data": [], + "data": [ + { + "5c9bf4a7-05ea-4cb8-b9e0-e0b0ca1186b0": 18990540 + } + ], "success": true } - ``` + ```. + + Notes + ----- + Warning: This action removes data from the file system. Use with caution. + + Examples + -------- + ```json + { + "data": [], + "success": true + } + ``` """ api_name = 'SYNO.Core.ISCSI.LUN' From c9ce3d79be34ca0df7d35cd82d2b1556798f0129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 17:40:30 +0700 Subject: [PATCH 040/126] fix: synology_api/surveillancestation.py update docstrings to comply with Numpydoc standards --- synology_api/surveillancestation.py | 5919 ++++++++++++++++++++++++++- 1 file changed, 5845 insertions(+), 74 deletions(-) diff --git a/synology_api/surveillancestation.py b/synology_api/surveillancestation.py index bfb91e76..1ca96fa6 100644 --- a/synology_api/surveillancestation.py +++ b/synology_api/surveillancestation.py @@ -1,11 +1,27 @@ +"""Synology Surveillance Station API Wrapper.""" from __future__ import annotations from typing import Optional, Any from . import base_api class SurveillanceStation(base_api.BaseApi): + """ + API wrapper for Synology Surveillance Station. + + Provides methods to interact with Surveillance Station features such as retrieving + station information and saving camera configurations. + """ def surveillance_station_info(self) -> dict[str, object] | str: + """ + Retrieve information about the Surveillance Station. + + Returns + ------- + dict[str, object] or str + A dictionary containing Surveillance Station information, or a string + with error details if the request fails. + """ api_name = 'SYNO.SurveillanceStation.Info' info = self.gen_list[api_name] api_path = info['path'] @@ -40,6 +56,71 @@ def camera_save(self, id: str = None, enableLowProfile: bool = None, recordSchedule: list[int] = None, rtspPathTimeout: int = None) -> dict[str, object] | str: + """ + Save or update camera configuration. + + Parameters + ---------- + id : str, optional + Camera ID. + name : str, optional + Camera name. + dsld : int, optional + Device slot ID. + newName : str, optional + New camera name. + ip : str, optional + Camera IP address. + port : int, optional + Camera port. + vendor : str, optional + Camera vendor. + model : str, optional + Camera model. + userName : str, optional + Username for camera authentication. + password : str, optional + Password for camera authentication. + videoCodec : int, optional + Video codec type. + audioCodec : int, optional + Audio codec type. + tvStandard : int, optional + TV standard. + channel : str, optional + Channel identifier. + userDefinePath : str, optional + User-defined path. + fov : str, optional + Field of view. + streamXX : Any, optional + Stream configuration. + recordTime : int, optional + Recording time. + preRecordTime : int, optional + Pre-recording time. + postRecordTime : int, optional + Post-recording time. + enableRecordingKeepDays : bool, optional + Enable recording retention by days. + recordingKeepDays : int, optional + Number of days to keep recordings. + enableRecordingKeepSize : bool, optional + Enable recording retention by size. + recordingKeepSize : int, optional + Maximum size for recordings. + enableLowProfile : bool, optional + Enable low profile recording. + recordSchedule : list of int, optional + Recording schedule. + rtspPathTimeout : int, optional + RTSP path timeout. + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -62,7 +143,37 @@ def camera_list(self, idList: str = None, streamInfo: bool = None, blPrivilege: bool = None, camStm: int = None) -> dict[str, object] | str: - + """ + Retrieve a list of cameras from Surveillance Station. + + Parameters + ---------- + idList : str, optional + Comma-separated list of camera IDs to filter. + offset : int, optional + The starting index for the camera list. + limit : int, optional + The maximum number of cameras to return. + blFromCamList : bool, optional + Whether to retrieve from the camera list. + blIncludeDeletedCam : bool, optional + Whether to include deleted cameras. + privCamType : str, optional + Filter by camera privilege type. + basic : bool, optional + Whether to return only basic information. + streamInfo : bool, optional + Whether to include stream information. + blPrivilege : bool, optional + Whether to include privilege information. + camStm : int, optional + Camera stream type. + + Returns + ------- + dict[str, object] or str + Dictionary containing camera list information, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -87,21 +198,44 @@ def get_camera_info(self, deviceOutCap: bool = True, fisheye: bool = True, camAppInfo: bool = True) -> dict[str, object] | str: - ''' - This function return information about a camera. - - cameraIds : This parameter is named cameraIds in the API documentation but it refer to 1 camera ID - - privCamType: int = 1 - SYNO.SS.CamPriv.LIVEVIEW = 1; - SYNO.SS.CamPriv.PLAYBACK = 2; - SYNO.SS.CamPriv.LENS = 4; - SYNO.SS.CamPriv.AUDIO = 8; - SYNO.SS.CamPriv.DIGIOUT = 16; - - All other parameters must be let to default value - ''' - + """ + Return information about a camera. + + Parameters + ---------- + cameraIds : int, optional + Camera ID. Although named cameraIds in the API, it refers to a single camera ID. + privCamType : int, default=1 + Camera privilege type. Possible values: + 1: LIVEVIEW + 2: PLAYBACK + 4: LENS + 8: AUDIO + 16: DIGIOUT + blIncludeDeletedCam : bool, default=True + Whether to include deleted cameras. + basic : bool, default=True + Whether to return only basic information. + streamInfo : bool, default=True + Whether to include stream information. + optimize : bool, default=True + Whether to optimize the returned data. + ptz : bool, default=True + Whether to include PTZ (Pan-Tilt-Zoom) information. + eventDetection : bool, default=True + Whether to include event detection information. + deviceOutCap : bool, default=True + Whether to include device output capabilities. + fisheye : bool, default=True + Whether to include fisheye camera information. + camAppInfo : bool, default=True + Whether to include camera application information. + + Returns + ------- + dict[str, object] or str + Dictionary containing camera information, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -117,7 +251,21 @@ def get_camera_info(self, def camera_list_group(self, offset: int = None, limit: int = None) -> dict[str, object] | str: - + """ + Retrieve a list of camera groups from Surveillance Station. + + Parameters + ---------- + offset : int, optional + The starting index for the camera group list. + limit : int, optional + The maximum number of camera groups to return. + + Returns + ------- + dict[str, object] or str + Dictionary containing camera group information, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -135,9 +283,25 @@ def get_snapshot(self, name: str = None, dsld: int = None, profileType: int = 1) -> str: - ''' By default, the profileType is 1, which is the default profile. - Binary data is returned, so the response is not a json object. - ''' + """ + Retrieve a snapshot image from a camera. + + Parameters + ---------- + id : Any, optional + Camera identifier. + name : str, optional + Camera name. + dsld : int, optional + Device slot ID. + profileType : int, default=1 + Profile type for the snapshot (1 is the default profile). + + Returns + ------- + str + Binary data of the snapshot image. The response is not a JSON object. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -154,6 +318,21 @@ def get_snapshot(self, def enable_camera(self, idList: str = None, blIncludeDeletedCam: bool = False) -> dict[str, object] | str: + """ + Enable one or more cameras by their IDs. + + Parameters + ---------- + idList : str, optional + Comma-separated list of camera IDs to enable. + blIncludeDeletedCam : bool, optional + Whether to include deleted cameras in the operation. Default is False. + + Returns + ------- + dict[str, object] or str + Result of the enable operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -169,6 +348,21 @@ def enable_camera(self, def disable_camera(self, idList: str = None, blIncludeDeletedCam: bool = False) -> dict[str, object] | str: + """ + Disable one or more cameras by their IDs. + + Parameters + ---------- + idList : str, optional + Comma-separated list of camera IDs to disable. + blIncludeDeletedCam : bool, optional + Whether to include deleted cameras in the operation. Default is False. + + Returns + ------- + dict[str, object] or str + Result of the disable operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -183,6 +377,19 @@ def disable_camera(self, # TODO not working def get_capability_by_cam_id(self, cameraId: Any = None) -> dict[str, object] | str: + """ + Retrieve the capability information for a specific camera by its ID. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera for which to retrieve capability information. + + Returns + ------- + dict[str, object] or str + A dictionary containing the camera's capability information, or a string with error details if the request fails. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -193,6 +400,19 @@ def get_capability_by_cam_id(self, cameraId: Any = None) -> dict[str, object] | # TODO not working def count_occupied_size(self, camId: int = None) -> dict[str, object] | str: + """ + Retrieve the occupied storage size for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to retrieve the occupied size. + + Returns + ------- + dict[str, object] or str + A dictionary containing the occupied size information, or a string with error details if the request fails. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -203,6 +423,19 @@ def count_occupied_size(self, camId: int = None) -> dict[str, object] | str: # TODO not working def is_shortcut_valid(self, cameraId: int = None) -> dict[str, object] | str: + """ + Check if a camera shortcut is valid. + + Parameters + ---------- + cameraId : int, optional + The ID of the camera to validate the shortcut for. + + Returns + ------- + dict[str, object] or str + A dictionary with the validation result, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -212,6 +445,19 @@ def is_shortcut_valid(self, cameraId: int = None) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_live_path(self, idList: int = None) -> dict[str, object] | str: + """ + Retrieve the live view path for one or more cameras. + + Parameters + ---------- + idList : int, optional + Camera ID or comma-separated list of camera IDs for which to retrieve the live view path. + + Returns + ------- + dict[str, object] or str + Dictionary containing the live view path information, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera' info = self.gen_list[api_name] api_path = info['path'] @@ -221,6 +467,19 @@ def get_live_path(self, idList: int = None) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def audio_event_enum(self, camId: int = None) -> dict[str, object] | str: + """ + Enumerate audio events for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to enumerate audio events. + + Returns + ------- + dict[str, object] or str + Dictionary containing audio event enumeration, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -231,6 +490,19 @@ def audio_event_enum(self, camId: int = None) -> dict[str, object] | str: # TODO not working def alarm_event_enum(self, camId: int = None) -> dict[str, object] | str: + """ + Enumerate alarm events for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to enumerate alarm events. + + Returns + ------- + dict[str, object] or str + Dictionary containing alarm event enumeration, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -246,6 +518,31 @@ def md_parameter_save(self, camId: int = None, threshold: int = None, objectSize: int = None, percentage: int = None) -> dict[str, object] | str: + """ + Save motion detection parameters for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to save motion detection parameters. + source : int, optional + The source channel or stream index. + mode : int, optional + The motion detection mode. + sensitivity : int, optional + Sensitivity level for motion detection. + threshold : int, optional + Threshold value for motion detection. + objectSize : int, optional + Minimum object size to trigger detection. + percentage : int, optional + Minimum percentage of the detection area to trigger detection. + + Returns + ------- + dict[str, object] or str + Result of the save operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -259,6 +556,19 @@ def md_parameter_save(self, camId: int = None, return self.request_data(api_name, api_path, req_param) def motion_event_enum(self, camId: int = None) -> dict[str, object] | str: + """ + Enumerate motion events for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to enumerate motion events. + + Returns + ------- + dict[str, object] or str + Dictionary containing motion event enumeration, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -273,7 +583,27 @@ def motion_parameter_save(self, mode: int = None, keep: bool = None, level: int = None) -> dict[str, object] | str: - + """ + Save advanced motion detection parameters for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to save motion detection parameters. + source : int, optional + The source channel or stream index. + mode : int, optional + The motion detection mode. + keep : bool, optional + Whether to keep the current settings. + level : int, optional + Sensitivity level for advanced motion detection. + + Returns + ------- + dict[str, object] or str + Result of the save operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -291,7 +621,25 @@ def di_parameter_save(self, idx: int = None, keep: bool = None, normal: int = None) -> dict[str, object] | str: - + """ + Save digital input (DI) parameters for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to save DI parameters. + idx : int, optional + The index of the DI channel. + keep : bool, optional + Whether to keep the current DI settings. + normal : int, optional + The normal state value for the DI channel. + + Returns + ------- + dict[str, object] or str + Result of the save operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -309,7 +657,23 @@ def alarm_sts_polling(self, timeOut: int = None, # TODO not working keep: Any = None) -> dict[str, object] | str: - + """ + Poll the alarm status for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to poll alarm status. + timeOut : int, optional + Timeout value for the polling operation. + keep : Any, optional + Reserved for future use or additional options (currently not working). + + Returns + ------- + dict[str, object] or str + Dictionary containing alarm status polling result, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -328,7 +692,25 @@ def td_parameter_save(self, source: int = None, keep: Any = None, duration: int = None) -> dict[str, object] | str: - + """ + Save tamper detection (TD) parameters for a specific camera. + + Parameters + ---------- + camId : int, optional + The ID of the camera for which to save tamper detection parameters. + source : int, optional + The source channel or stream index. + keep : Any, optional + Whether to keep the current settings (reserved for future use). + duration : int, optional + Duration for the tamper detection event. + + Returns + ------- + dict[str, object] or str + Result of the save operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Event' info = self.gen_list[api_name] api_path = info['path'] @@ -342,7 +724,19 @@ def td_parameter_save(self, return self.request_data(api_name, api_path, req_param) def enumerate_camera_group(self, privCamType: int = None) -> dict[str, object] | str: - + """ + Enumerate camera groups in Surveillance Station. + + Parameters + ---------- + privCamType : int, optional + Camera privilege type to filter groups. + + Returns + ------- + dict[str, object] or str + Dictionary containing camera group enumeration, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Group' info = self.gen_list[api_name] api_path = info['path'] @@ -353,6 +747,19 @@ def enumerate_camera_group(self, privCamType: int = None) -> dict[str, object] | # TODO to check def save_specific_group(self, groupList: Any = None) -> dict[str, object] | str: + """ + Save or update a specific camera group in Surveillance Station. + + Parameters + ---------- + groupList : Any, optional + The list of groups to be saved or updated. + + Returns + ------- + dict[str, object] or str + Result of the save operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Group' info = self.gen_list[api_name] api_path = info['path'] @@ -362,6 +769,19 @@ def save_specific_group(self, groupList: Any = None) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def delete_specific_groups(self, Id: int = None) -> dict[str, object] | str: + """ + Delete specific camera groups in Surveillance Station. + + Parameters + ---------- + Id : int, optional + The ID of the camera group to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Group' info = self.gen_list[api_name] api_path = info['path'] @@ -376,6 +796,27 @@ def enumerate_group_information(self, camServerId: int = None, camlist: Any = None, # TODO not working actFromHost: bool = None) -> dict[str, object] | str: + """ + Enumerate group information for camera import in Surveillance Station. + + Parameters + ---------- + camServerId : int, optional + The ID of the camera server. + shareName : str, optional + The name of the shared folder. + archiveName : str, optional + The name of the archive. + camlist : Any, optional + List of cameras to include. + actFromHost : bool, optional + Whether the action is performed from the host. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the group information enumeration as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Import' info = self.gen_list[api_name] api_path = info['path'] @@ -392,6 +833,23 @@ def enumerate_camera_from_archive(self, shareName: str = None, archiveName: str = None, serverId: int = None) -> dict[str, object] | str: + """ + Enumerate cameras from a specified archive in Surveillance Station. + + Parameters + ---------- + shareName : str, optional + The name of the shared folder containing the archive. + archiveName : str, optional + The name of the archive to enumerate cameras from. + serverId : int, optional + The ID of the server associated with the archive. + + Returns + ------- + dict[str, object] or str + A dictionary containing camera enumeration details, or a string with error details if the request fails. + """ api_name = 'SYNO.SurveillanceStation.Camera.Import' info = self.gen_list[api_name] api_path = info['path'] @@ -407,6 +865,19 @@ def enumerate_camera_from_archive(self, def enumerate_archive_from_folder(self, # TODO not working shareName: str = None) -> dict[str, object] | str: + """ + Enumerate archives from a specified folder in Surveillance Station. + + Parameters + ---------- + shareName : str, optional + The name of the shared folder containing the archives. + + Returns + ------- + dict[str, object] or str + A dictionary containing archive enumeration details, or a string with error details if the request fails. + """ api_name = 'SYNO.SurveillanceStation.Camera.Import' info = self.gen_list[api_name] api_path = info['path'] @@ -429,6 +900,33 @@ def check_available_size_of_sdcard(self, model: str = None, # TODO not working ch: str = None) -> dict[str, object] | str: + """ + Check the available size of the SD card for a specific camera. + + Parameters + ---------- + camId : Any, optional + The ID of the camera. + host : str, optional + The host address of the camera. + port : str, optional + The port number for the camera connection. + user : str, optional + The username for authentication. + passw : str, optional + The password for authentication. + vendor : str, optional + The vendor of the camera. + model : str, optional + The model of the camera. + ch : str, optional + The channel identifier. (Currently not working). + + Returns + ------- + dict[str, object] or str + A dictionary containing the available size information, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Wizard' info = self.gen_list[api_name] api_path = info['path'] @@ -446,12 +944,20 @@ def check_available_size_of_sdcard(self, # TODO not working def check_licence_quota(self) -> dict[str, object] | str: + """ + Check the license quota for Surveillance Station cameras. + + Returns + ------- + dict[str, object] or str + A dictionary containing license quota information, or a string with error details if the request fails. + """ api_name = 'SYNO.SurveillanceStation.Camera.Wizard' info = self.gen_list[api_name] api_path = info['path'] req_param = {'version': info['maxVersion'], 'method': 'CheckQuota'} - return self.request_data(api_name, api_path, req_param) + return self.request_data(api_name, api_path, req_param) def format_specific_sd_card(self, camId: Any = None, @@ -464,6 +970,35 @@ def format_specific_sd_card(self, ch: str = None, # TODO not working timeout: int = None) -> dict[str, object] | str: + """ + Format the SD card of a specific camera. + + Parameters + ---------- + camId : Any, optional + The ID of the camera whose SD card is to be formatted. + host : str, optional + The host address of the camera. + port : str, optional + The port number for the camera connection. + user : str, optional + The username for authentication. + passw : str, optional + The password for authentication. + vendor : str, optional + The vendor of the camera. + model : str, optional + The model of the camera. + ch : str, optional + The channel identifier. + timeout : int, optional + Timeout value for the formatting operation. (Currently not working). + + Returns + ------- + dict[str, object] or str + A dictionary containing the result of the format operation, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Wizard' info = self.gen_list[api_name] api_path = info['path'] @@ -496,6 +1031,47 @@ def quick_create_single_camera(self, camUserName: str = None, # TODO to check camPassWord: str = None) -> dict[str, object] | str: + """ + Quickly create a single camera in Surveillance Station. + + Parameters + ---------- + camServerId : Any, optional + The ID of the camera server. + actFromHost : bool, optional + Whether the action is performed from the host. + camStreamingType : str, optional + The streaming type of the camera. + camName : str, optional + The name of the camera. + camIP : str, optional + The IP address of the camera. + camPort : str, optional + The port number of the camera. + camVendor : str, optional + The vendor of the camera. + camModel : str, optional + The model of the camera. + camMountType : int, optional + The mount type of the camera. + camChannel : str, optional + The channel of the camera. + camVideoType : str, optional + The video type of the camera. + camAudioType : str, optional + The audio type of the camera. + camSourcePath : str, optional + The source path for the camera stream. + camUserName : str, optional + The username for camera authentication. + camPassWord : str, optional + The password for camera authentication. (To be checked). + + Returns + ------- + dict[str, object] or str + Result of the quick create operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Wizard' info = self.gen_list[api_name] api_path = info['path'] @@ -514,6 +1090,25 @@ def move_camera_lens(self, speed: int = None, # TODO not working moveType: str = None) -> dict[str, object] | str: + """ + Move the camera lens in a specified direction with an optional speed and move type. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control. + direction : str, optional + The direction to move the lens (e.g., 'up', 'down', 'left', 'right'). + speed : int, optional + The speed at which to move the lens. + moveType : str, optional + The type of movement (reserved for future use, currently not working). + + Returns + ------- + dict[str, object] or str + Result of the move operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -531,6 +1126,23 @@ def camera_lens_zoom(self, control: Any = None, # TODO not working moveType: str = None) -> dict[str, object] | str: + """ + Control the zoom function of a camera lens. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control. + control : Any, optional + The zoom control command or value. + moveType : str, optional + The type of movement (reserved for future use, currently not working). + + Returns + ------- + dict[str, object] or str + Result of the zoom operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -548,6 +1160,23 @@ def list_preset_ptz_camera(self, offset: int = None, # TODO not working limit: int = None) -> dict[str, object] | str: + """ + List preset positions for a PTZ (Pan-Tilt-Zoom) camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the PTZ camera to list presets for. + offset : int, optional + The starting index for the preset list. + limit : int, optional + The maximum number of presets to return. (Currently not working). + + Returns + ------- + dict[str, object] or str + Dictionary containing the list of PTZ presets, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -568,6 +1197,29 @@ def move_camera_lens_to_preset_position(self, type: Any = None, # TODO not working isPatrol: bool = None) -> dict[str, object] | str: + """ + Move the camera lens to a specified preset position. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control. + presetId : Any, optional + The ID of the preset position to move to. + position : Any, optional + The position value for the preset. + speed : Any, optional + The speed at which to move the lens. + type : Any, optional + The type of movement or preset. + isPatrol : bool, optional + Whether the movement is part of a patrol operation. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the move operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -585,6 +1237,23 @@ def list_patrol_cameras(self, offset: int = None, # TODO not working limit: int = None) -> dict[str, object] | str: + """ + List patrols for a PTZ (Pan-Tilt-Zoom) camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the PTZ camera to list patrols for. + offset : int, optional + The starting index for the patrol list. + limit : int, optional + The maximum number of patrols to return. (Currently not working). + + Returns + ------- + dict[str, object] or str + Dictionary containing the list of PTZ patrols, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -601,6 +1270,21 @@ def force_cam_to_execute_patrol(self, cameraId: Any = None, # TODO not working patrolId: Any = None) -> dict[str, object] | str: + """ + Force a camera to execute a specified patrol. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to execute the patrol. + patrolId : Any, optional + The ID of the patrol to execute. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the patrol execution as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -618,6 +1302,23 @@ def focus_camera(self, control: Any = None, # TODO not working moveType: Any = None) -> dict[str, object] | str: + """ + Control the focus function of a camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control. + control : Any, optional + The focus control command or value. + moveType : Any, optional + The type of movement (reserved for future use, currently not working). + + Returns + ------- + dict[str, object] or str + Result of the focus operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -635,6 +1336,23 @@ def control_camera_iris_in_out(self, control: Any = None, # TODO not working moveType: Any = None) -> dict[str, object] | str: + """ + Control the iris (in/out) function of a camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control. + control : Any, optional + The iris control command or value. + moveType : Any, optional + The type of movement (reserved for future use, currently not working). + + Returns + ------- + dict[str, object] or str + Result of the iris control operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -649,6 +1367,19 @@ def control_camera_iris_in_out(self, # TODO not working def auto_focus(self, cameraId: Any = None) -> dict[str, object] | str: + """ + Perform an auto-focus operation on a specified camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to auto-focus. + + Returns + ------- + dict[str, object] or str + Result of the auto-focus operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -665,6 +1396,21 @@ def move_cam_lens_to_absolute_position(self, posX: int = None, # TODO not working posY: int = None) -> dict[str, object] | str: + """ + Move the camera lens to an absolute position. + + Parameters + ---------- + posX : int, optional + The X coordinate for the absolute position. + posY : int, optional + The Y coordinate for the absolute position. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the move operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -680,6 +1426,19 @@ def move_cam_lens_to_absolute_position(self, def move_cam_to_home_position(self, # TODO not working cameraId: Any = None) -> dict[str, object] | str: + """ + Move the camera to its home position. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to move to the home position. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the move operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -696,6 +1455,21 @@ def auto_pan_camera(self, cameraId: Any = None, # TODO not working moveType: str = None) -> dict[str, object] | str: + """ + Automatically pan the camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to auto-pan. + moveType : str, optional + The type of movement (reserved for future use, currently not working). + + Returns + ------- + dict[str, object] or str + Result of the auto-pan operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -712,6 +1486,21 @@ def start_stop_object_tracking(self, cameraId: Any = None, # TODO not working moveType: str = None) -> dict[str, object] | str: + """ + Start or stop object tracking for a specified camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control object tracking. + moveType : str, optional + The type of movement (reserved for future use, currently not working). + + Returns + ------- + dict[str, object] or str + Result of the object tracking operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ' info = self.gen_list[api_name] api_path = info['path'] @@ -728,6 +1517,21 @@ def start_stop_external_recording(self, cameraId: Any = None, # TODO not working action: str = None) -> dict[str, object] | str: + """ + Start or stop external recording for a specified camera. + + Parameters + ---------- + cameraId : Any, optional + The ID of the camera to control external recording. + action : str, optional + The action to perform (e.g., 'start' or 'stop'). (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the external recording operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.ExternalRecording' info = self.gen_list[api_name] api_path = info['path'] @@ -748,6 +1552,31 @@ def query_event_list_by_filter(self, toTime: int = None, dsld: int = None, mountId: int = None) -> dict[str, object] | str: + """ + Query the event list by applying various filters. + + Parameters + ---------- + offset : int, optional + The starting index for the event list. + limit : int, optional + The maximum number of events to return. + cameraIds : str, optional + Comma-separated list of camera IDs to filter events. + fromTime : int, optional + Start time (timestamp) for filtering events. + toTime : int, optional + End time (timestamp) for filtering events. + dsld : int, optional + Device slot ID to filter events. + mountId : int, optional + Mount ID to filter events. + + Returns + ------- + dict[str, object] or str + Dictionary containing the filtered event list, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -763,6 +1592,21 @@ def query_event_list_by_filter(self, def delete_recordings(self, idList: int = None, dsld: int = None) -> dict[str, object] | str: + """ + Delete specific recordings from Surveillance Station. + + Parameters + ---------- + idList : int, optional + The ID or comma-separated list of IDs of the recordings to delete. + dsld : int, optional + Device slot ID associated with the recordings. + + Returns + ------- + dict[str, object] or str + Result of the delete operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -788,6 +1632,39 @@ def delete_events_by_filter(self, from_end: int = None, # TODO not working from_start: int = None) -> dict[str, object] | str: + """ + Delete events from Surveillance Station by applying various filters. + + Parameters + ---------- + reason : str, optional + The reason for deleting the events. + cameraIds : str, optional + Comma-separated list of camera IDs to filter events. + fromTime : Any, optional + Start time (timestamp) for filtering events. + toTime : Any, optional + End time (timestamp) for filtering events. + locked : int, optional + Whether to include locked events. + evtSrcType : int, optional + Event source type. + evtSrcId : int, optional + Event source ID. + blIncludeSnapshot : bool, optional + Whether to include snapshots in the deletion. + includeAllCam : bool, optional + Whether to include all cameras. + from_end : int, optional + End index for the filter range. + from_start : int, optional + Start index for the filter range. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the delete operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -802,6 +1679,14 @@ def delete_events_by_filter(self, # TODO not working def delete_all_recordings(self) -> dict[str, object] | str: + """ + Delete all recordings from Surveillance Station. + + Returns + ------- + dict[str, object] or str + Result of the delete operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -817,6 +1702,19 @@ def delete_all_recordings(self) -> dict[str, object] | str: def apply_settings_advance_tab(self, # TODO not working rotateUnrecogCam: bool = None) -> dict[str, object] | str: + """ + Apply advanced settings in the Surveillance Station recording tab. + + Parameters + ---------- + rotateUnrecogCam : bool, optional + Whether to rotate unrecognized cameras. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the apply operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -842,6 +1740,39 @@ def count_by_number_of_event(self, blIncludeSnapshot: bool = None, # TODO not working includeAllCam: bool = None) -> dict[str, object] | str: + """ + Count the number of events by category, with optional filters. + + Parameters + ---------- + offset : bool, optional + Whether to offset the results. + limit : int, optional + The maximum number of results to return. + reason : str, optional + The reason for filtering events. + cameraIds : str, optional + Comma-separated list of camera IDs to filter events. + fromTime : int, optional + Start time (timestamp) for filtering events. + toTime : int, optional + End time (timestamp) for filtering events. + locked : int, optional + Whether to include locked events. + evtSrcType : int, optional + Event source type. + evtSrcId : int, optional + Event source ID. + blIncludeSnapshot : bool, optional + Whether to include snapshots in the count. + includeAllCam : bool, optional + Whether to include all cameras. (Currently not working). + + Returns + ------- + dict[str, object] or str + Dictionary containing the event count by category, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -857,6 +1788,14 @@ def count_by_number_of_event(self, # TODO not working def keep_event_play_alive(self) -> dict[str, object] | str: + """ + Keep the event play session alive. + + Returns + ------- + dict[str, object] or str + Result of the keepalive operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -872,6 +1811,19 @@ def keep_event_play_alive(self) -> dict[str, object] | str: def stop_recording_event(self, # TODO not working idList: Any = None) -> dict[str, object] | str: + """ + Stop a recording event for the specified event IDs. + + Parameters + ---------- + idList : Any, optional + The ID or list of IDs of the events to stop recording. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the stop operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -886,6 +1838,14 @@ def stop_recording_event(self, # TODO not working def load_settings_in_advanced_tab(self) -> dict[str, object] | str: + """ + Load settings from the advanced tab in Surveillance Station. + + Returns + ------- + dict[str, object] or str + Dictionary containing the advanced settings, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -905,8 +1865,45 @@ def lock_selected_event(self, toTime: int = None, locked: int = None, evtSrcType: int = None, + evtSrcId: int = None, + blIncludeSnapshot: bool = None, + includeAllCam: bool = None, + from_end: int = None, # TODO not working - evtSrcId: int = None) -> dict[str, object] | str: + from_start: int = None) -> dict[str, object] | str: + """ + Lock selected events by applying various filters. + + Parameters + ---------- + reason : str, optional + The reason for locking the events. + cameraIds : str, optional + Comma-separated list of camera IDs to filter events. + fromTime : int, optional + Start time (timestamp) for filtering events. + toTime : int, optional + End time (timestamp) for filtering events. + locked : int, optional + Whether to lock the events. + evtSrcType : int, optional + Event source type. + evtSrcId : int, optional + Event source ID. + blIncludeSnapshot : bool, optional + Whether to include snapshots in the lock operation. + includeAllCam : bool, optional + Whether to include all cameras. + from_end : int, optional + End index for the filter range. + from_start : int, optional + Start index for the filter range. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the lock operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -923,6 +1920,21 @@ def unlock_selected_event(self, idList: str = None, # TODO not working dsld: int = None) -> dict[str, object] | str: + """ + Unlock selected events by their IDs. + + Parameters + ---------- + idList : str, optional + Comma-separated list of event IDs to unlock. + dsld : int, optional + Device slot ID associated with the events. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the unlock operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -944,6 +1956,31 @@ def unlock_selected_filter_event(self, evtSrcType: int = None, # TODO not working evtSrcId: int = None) -> dict[str, object] | str: + """ + Unlock events by applying various filters. + + Parameters + ---------- + reason : str, optional + The reason for unlocking the events. + cameraIds : str, optional + Comma-separated list of camera IDs to filter events. + fromTime : int, optional + Start time (timestamp) for filtering events. + toTime : int, optional + End time (timestamp) for filtering events. + locked : int, optional + Whether to unlock only locked events. + evtSrcType : int, optional + Event source type. + evtSrcId : int, optional + Event source ID. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the unlock operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -959,6 +1996,21 @@ def unlock_selected_filter_event(self, def lock_selected_recordings(self, idList: str = None, dsld: int = None) -> dict[str, object] | str: + """ + Lock selected recordings by their IDs. + + Parameters + ---------- + idList : str, optional + Comma-separated list of recording IDs to lock. + dsld : int, optional + Device slot ID associated with the recordings. + + Returns + ------- + dict[str, object] or str + Result of the lock operation as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -976,6 +2028,25 @@ def download_recordings(self, mountId: int = None, offsetTimeMs: int = None, playTimeMs: int = None) -> dict[str, object] | str: + """ + Download recordings by specifying recording ID and optional parameters. + + Parameters + ---------- + id : int, optional + The ID of the recording to download. + mountId : int, optional + The mount ID associated with the recording. + offsetTimeMs : int, optional + Offset time in milliseconds for the download. + playTimeMs : int, optional + Playback time in milliseconds for the download. + + Returns + ------- + dict[str, object] or str + The downloaded recording as a binary response, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -994,6 +2065,25 @@ def check_if_recording_playable(self, mountId: int = None, # TODO not working dsld: int = None) -> dict[str, object] | str: + """ + Check if a recording is playable by event ID and optional parameters. + + Parameters + ---------- + eventId : int, optional + The event ID of the recording to check. + chkDetail : bool, optional + Whether to check detailed information. + mountId : int, optional + The mount ID associated with the recording. + dsld : int, optional + Device slot ID. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the check as a dictionary, or a string with error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -1014,6 +2104,27 @@ def play_specific_recording(self, dsld: int = None, # TODO not working videoCodec: int = None) -> dict[str, object] | str: + """ + Stream a specific recording from Surveillance Station. + + Parameters + ---------- + recordingId : int, optional + The ID of the recording to play. + alertRecording : bool, optional + Whether the recording is an alert recording. + mountId : int, optional + The mount ID associated with the recording. + dsld : int, optional + Device slot ID. + videoCodec : int, optional + Video codec to use for streaming. (Currently not working). + + Returns + ------- + dict[str, object] or str + Streaming information or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -1032,17 +2143,33 @@ def download_merged_recording_files(self, toTime: int = None, # TODO not working fileName: str = None) -> dict[str, object] | str: - """Download the merged files of UTC time range recordings of target camera. - If there are different resolution or codec within UTC time range, the recordings will merge as much as possible - and downlod file will be a zip file. - - This method will start a task which have keep-alive mechanism. - Use GetRangeExportProgress method to get newest progress and keep-alive. - After receiving progress 100, use OnRangeExportDone method to download exported recording within 1 - minutes. - If you want to cancel range export task, just do not send GetRangeExportProgress method or - OnRangeExportDone method. System will cleanup processed files itself.""" - + """ + Download merged files of recordings within a UTC time range for a target camera. + + If there are different resolutions or codecs within the time range, recordings will be merged as much as possible, + and the download file will be a zip file. + + This method starts a task with a keep-alive mechanism. + Use GetRangeExportProgress to get the latest progress and keep-alive. + After receiving progress 100, use OnRangeExportDone to download the exported recording within 1 minute. + To cancel the export task, do not send GetRangeExportProgress or OnRangeExportDone; the system will clean up processed files. + + Parameters + ---------- + camId : int, optional + The camera ID to export recordings from. + fromTime : int, optional + Start UTC timestamp for the export range. + toTime : int, optional + End UTC timestamp for the export range. + fileName : str, optional + Name of the output file. (Currently not working). + + Returns + ------- + dict[str, object] or str + Task information for the export or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -1057,6 +2184,19 @@ def download_merged_recording_files(self, # TODO not working def get_newest_progress_keep_alive(self, dlid: int = None) -> dict[str, object] | str: + """ + Get the latest progress of a range export task and keep the task alive. + + Parameters + ---------- + dlid : int, optional + The download task ID. + + Returns + ------- + dict[str, object] or str + Progress information or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -1074,21 +2214,36 @@ def download_recording_from_target(self, dlid: int = None, # TODO not working fileName: str = None) -> dict[str, object] | str: - """Response - MP4 or zip file data. - The response type can be found in fileExt of GetRangeExportProgress method response when progress 100. - - Note - GetRangeExportProgress method must be sent within 1 minute after corresponding RangeExport method task - is completed, otherwise the exported recordings will be cleared. - - 2.3.11.20 API Error Code - Code Description - 400 Execution failed. - 401 Parameter invalid. - 405 CMS server connection failed. - 414 Some events not exist. - 439 Too many items selected.""" + """ + Download the exported recording file from a completed range export task. + + Parameters + ---------- + dlid : int, optional + The download task ID. + fileName : str, optional + Name of the file to download. (Currently not working). + + Returns + ------- + dict[str, object] or str + Downloaded file data or error details. + + Notes + ----- + GetRangeExportProgress must be called within 1 minute after the corresponding RangeExport task is completed, + otherwise the exported recordings will be cleared. + + Response: Returns MP4 or zip file data. The response type can be found in the fileExt field of the GetRangeExportProgress + response when progress is 100. + + API Error Codes: + 400 : Execution failed. + 401 : Parameter invalid. + 405 : CMS server connection failed. + 414 : Some events do not exist. + 439 : Too many items selected. + """ api_name = 'SYNO.SurveillanceStation.Recording' info = self.gen_list[api_name] @@ -1106,6 +2261,21 @@ def download_recording_from_target(self, def handle_load_event_export(self, start: int = None, limit: bool = None) -> dict[str, object] | str: + """ + Load exported event recordings with optional pagination. + + Parameters + ---------- + start : int, optional + The starting index for loading events. + limit : bool, optional + The maximum number of events to load. + + Returns + ------- + dict[str, object] or str + Exported event information or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Export' info = self.gen_list[api_name] api_path = info['path'] @@ -1122,6 +2292,23 @@ def check_name_export_event(self, dsId: int = None, name: int = None, share: str = None) -> dict[str, object] | str: + """ + Check if an export event name is valid or already exists. + + Parameters + ---------- + dsId : int, optional + The data source ID. + name : int, optional + The name to check for the export event. + share : str, optional + The share name associated with the export event. + + Returns + ------- + dict[str, object] or str + Result of the name check or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Export' info = self.gen_list[api_name] api_path = info['path'] @@ -1136,6 +2323,19 @@ def check_name_export_event(self, def get_camera_information_list(self, dslld: int = None) -> dict[str, object] | str: + """ + Retrieve the list of camera information for event export. + + Parameters + ---------- + dslld : int, optional + The ID of the data source (recording server) to query cameras from. + + Returns + ------- + dict[str, object] or str + Camera information list or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Export' info = self.gen_list[api_name] api_path = info['path'] @@ -1153,6 +2353,25 @@ def check_destination_folder_availability(self, startTime: int = None, stopTime: int = None, camIdList: str = None) -> dict[str, object] | str: + """ + Check if the destination folder has enough available space for export. + + Parameters + ---------- + freeSize : int, optional + Required free size in bytes. + startTime : int, optional + Start time of the export range (UTC timestamp). + stopTime : int, optional + End time of the export range (UTC timestamp). + camIdList : str, optional + Comma-separated list of camera IDs to check. + + Returns + ------- + dict[str, object] or str + Availability information or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Export' info = self.gen_list[api_name] api_path = info['path'] @@ -1176,6 +2395,35 @@ def handle_save_event_export(self, stop_time: int = None, isoverwrite: int = None, camlistid: str = None) -> dict[str, object] | str: + """ + Save an event export task with the specified parameters. + + Parameters + ---------- + name : str, optional + Name of the export task. + srcDsId : int, optional + Source data source ID. + dstDsId : int, optional + Destination data source ID. + dstdir : str, optional + Destination directory for export. + freesize : int, optional + Required free size in bytes. + start_time : int, optional + Start time of the export range (UTC timestamp). + stop_time : int, optional + End time of the export range (UTC timestamp). + isoverwrite : int, optional + Whether to overwrite existing files (1 for true, 0 for false). + camlistid : str, optional + Comma-separated list of camera IDs to export. + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Export' info = self.gen_list[api_name] api_path = info['path'] @@ -1192,6 +2440,23 @@ def get_event_export_info_from_recording_server(self, start_time: int = None, stop_time: int = None, camlistid: str = None) -> dict[str, object] | str: + """ + Retrieve event export information from the recording server. + + Parameters + ---------- + start_time : int, optional + Start time of the export range (UTC timestamp). + stop_time : int, optional + End time of the export range (UTC timestamp). + camlistid : str, optional + Comma-separated list of camera IDs. + + Returns + ------- + dict[str, object] or str + Export information or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Export' info = self.gen_list[api_name] api_path = info['path'] @@ -1205,6 +2470,14 @@ def get_event_export_info_from_recording_server(self, return self.request_data(api_name, api_path, req_param) def load_event_mount(self) -> dict[str, object] | str: + """ + Load event mount information for export. + + Returns + ------- + dict[str, object] or str + Mount information or error details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Mount' info = self.gen_list[api_name] api_path = info['path'] @@ -1221,12 +2494,25 @@ def redirect_webapi_to_target_ds(self, dsId: int = None, # TODO not working webAPI: Any = None) -> dict[str, object] | str: - """webAPI Array of `webAPI_info` - - Example: - `webAPI={"api": "SYNO.SurveillanceStation.AddOns", "version": 1, "method": - "List"}` """ - + """ + Redirect a WebAPI request to a target DiskStation. + + Parameters + ---------- + dsId : int, optional + Target DiskStation ID. + webAPI : Any, optional + WebAPI information to redirect (array of webAPI_info). + + Returns + ------- + dict[str, object] or str + Result of the redirect operation or error details. + + Examples + -------- + webAPI={"api": "SYNO.SurveillanceStation.AddOns", "version": 1, "method": "List"} + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1243,6 +2529,21 @@ def modify_share_privilege(self, privSet: int = None, # TODO not working shareName: str = None) -> dict[str, object] | str: + """ + Modify the share privilege settings in Surveillance Station CMS. + + Parameters + ---------- + privSet : int, optional + Privilege set value. + shareName : str, optional + Name of the share to modify. + + Returns + ------- + dict[str, object] or str + Result of the privilege modification or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1264,6 +2565,31 @@ def apply_option_settings(self, nvr_enable: bool = None, # TODO not working nvr_lang: str = None) -> dict[str, object] | str: + """ + Apply option settings for Surveillance Station CMS. + + Parameters + ---------- + central_auto_video_relay : bool, optional + Enable or disable central auto video relay. + central_enable : bool, optional + Enable or disable central management. + central_mode : str, optional + Set the central management mode. + central_rec_mask_mode : bool, optional + Enable or disable central recording mask mode. + central_rec_sync_time : bool, optional + Enable or disable central recording time synchronization. + nvr_enable : bool, optional + Enable or disable NVR. + nvr_lang : str, optional + Set the NVR language. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the apply operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1279,6 +2605,19 @@ def apply_option_settings(self, def get_cms_info(self, # TODO not working isPolling: bool = None) -> dict[str, object] | str: + """ + Retrieve CMS (Central Management System) information. + + Parameters + ---------- + isPolling : bool, optional + Whether to poll for CMS information. (Currently not working). + + Returns + ------- + dict[str, object] or str + CMS information or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1296,6 +2635,23 @@ def get_log_recording_data_from_target_ds(self, syncTargetId: int = None, # TODO not working limit: int = None) -> dict[str, object] | str: + """ + Retrieve log recording data from a target DiskStation. + + Parameters + ---------- + syncType : int, optional + Type of synchronization. + syncTargetId : int, optional + ID of the target DiskStation for synchronization. + limit : int, optional + Limit the number of records returned. (Currently not working). + + Returns + ------- + dict[str, object] or str + Log recording data or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1309,6 +2665,14 @@ def get_log_recording_data_from_target_ds(self, return self.request_data(api_name, api_path, req_param) def get_samba_service(self) -> dict[str, object] | str: # TODO not working + """ + Check if the Samba service is enabled on the CMS. + + Returns + ------- + dict[str, object] or str + Samba service status or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1319,6 +2683,14 @@ def get_samba_service(self) -> dict[str, object] | str: # TODO not working # TODO not working def check_if_samba_on_and_rec_enabled(self) -> dict[str, object] | str: + """ + Check if Samba is enabled and recording is enabled on the CMS. + + Returns + ------- + dict[str, object] or str + Status of Samba and recording or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1329,6 +2701,19 @@ def check_if_samba_on_and_rec_enabled(self) -> dict[str, object] | str: def get_encoded_single_image_of_camera(self, camId: int = None) -> dict[str, object] | str: + """ + Retrieve an encoded single image (snapshot) from a specified camera. + + Parameters + ---------- + camId : int, optional + ID of the camera to get the snapshot from. + + Returns + ------- + dict[str, object] or str + Encoded image data or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1344,6 +2729,19 @@ def get_encoded_single_image_of_camera(self, def get_cms_status(self, # TODO not working camId: int = None) -> dict[str, object] | str: + """ + Retrieve the status of the CMS. + + Parameters + ---------- + camId : int, optional + ID of the camera to check status for. (Currently not working). + + Returns + ------- + dict[str, object] or str + CMS status or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1358,6 +2756,14 @@ def get_cms_status(self, # TODO not working def enable_smb_service(self) -> dict[str, object] | str: + """ + Enable the Samba service on the CMS. + + Returns + ------- + dict[str, object] or str + Result of the enable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1367,6 +2773,14 @@ def enable_smb_service(self) -> dict[str, object] | str: # TODO not working def notify_slave_ds_to_disconnect(self) -> dict[str, object] | str: + """ + Notify a slave DiskStation to disconnect from the CMS. + + Returns + ------- + dict[str, object] or str + Result of the notification or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1377,6 +2791,19 @@ def notify_slave_ds_to_disconnect(self) -> dict[str, object] | str: def lock_recording_server_prevent_setting_change(self, # TODO not working locked: bool = None) -> dict[str, object] | str: + """ + Lock the recording server to prevent setting changes. + + Parameters + ---------- + locked : bool, optional + Whether to lock the server. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the lock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS' info = self.gen_list[api_name] api_path = info['path'] @@ -1394,6 +2821,25 @@ def enable_ds_into_recording_server(self, adminPasswd: str = None, central_rec_mask_mode: str = None, central_rec_sync_time: str = None) -> dict[str, object] | str: + """ + Enable a DiskStation as a recording server in the CMS. + + Parameters + ---------- + adminUsername : str, optional + Administrator username. + adminPasswd : str, optional + Administrator password. + central_rec_mask_mode : str, optional + Central recording mask mode. + central_rec_sync_time : str, optional + Central recording synchronization time. + + Returns + ------- + dict[str, object] or str + Result of the enable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1411,6 +2857,25 @@ def unpair_recording_servers(self, key: str = None, mac: str = None, cmsMode: int = None) -> dict[str, object] | str: + """ + Unpair recording servers from the CMS. + + Parameters + ---------- + adminUsername : str, optional + Administrator username. + key : str, optional + Key for unpairing. + mac : str, optional + MAC address of the server. + cmsMode : int, optional + CMS mode. + + Returns + ------- + dict[str, object] or str + Result of the unpair operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1424,6 +2889,14 @@ def unpair_recording_servers(self, return self.request_data(api_name, api_path, req_param) def get_free_memory_size(self) -> dict[str, object] | str: + """ + Retrieve the free memory size from the target DiskStation. + + Returns + ------- + dict[str, object] or str + Free memory size information or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1438,6 +2911,27 @@ def handle_slave_ds(self, mac: str = None, # TODO to check masterAuthKey: str = None) -> dict[str, object] | str: + """ + Handle slave DiskStation operations such as locking or authentication. + + Parameters + ---------- + lock : bool, optional + Whether to lock the slave DiskStation. + adminUsername : str, optional + Administrator username. + key : str, optional + Authentication key. + mac : str, optional + MAC address of the slave DiskStation. + masterAuthKey : str, optional + Master authentication key. (To check). + + Returns + ------- + dict[str, object] or str + Result of the operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1452,6 +2946,19 @@ def handle_slave_ds(self, def get_target_ds_info(self, slaveDslp: str = None) -> dict[str, object] | str: + """ + Retrieve information about the target slave DiskStation. + + Parameters + ---------- + slaveDslp : str, optional + Slave DiskStation IP or identifier. + + Returns + ------- + dict[str, object] or str + Target DiskStation information or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1468,6 +2975,23 @@ def logout_slave_ds(self, adminUsername: str = None, key: str = None, mac: str = None) -> dict[str, object] | str: + """ + Log out a slave DiskStation from the CMS. + + Parameters + ---------- + adminUsername : str, optional + Administrator username. + key : str, optional + Authentication key. + mac : str, optional + MAC address of the slave DiskStation. + + Returns + ------- + dict[str, object] or str + Result of the logout operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1491,6 +3015,35 @@ def pair_slave_ds(self, cms_masked: bool = None, # TODO not working cms_sync_time: bool = None) -> dict[str, object] | str: + """ + Pair a slave DiskStation with the CMS. + + Parameters + ---------- + dsname : str, optional + Name of the slave DiskStation. + slaveDslp : str, optional + Slave DiskStation IP or identifier. + port : int, optional + Port number for connection. + masterAuthKey : str, optional + Master authentication key. + model : str, optional + Model of the slave DiskStation. + mac : str, optional + MAC address of the slave DiskStation. + cms_locked : bool, optional + Whether the CMS is locked. + cms_masked : bool, optional + Whether the CMS is masked. + cms_sync_time : bool, optional + Synchronize time with CMS. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the pairing operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1518,11 +3071,51 @@ def login_slave_ds(self, cms_masked: bool = None, # TODO not working cms_sync_time: bool = None) -> dict[str, object] | str: - """2.3.15.9 API Error Code + """ + Log in a slave DiskStation to the CMS. + + Parameters + ---------- + adminUsername : str, optional + Administrator username. + key : str, optional + Authentication key. + mac : str, optional + MAC address of the slave DiskStation. + masterAuthKey : str, optional + Master authentication key. + hostName : str, optional + Hostname of the slave DiskStation. + hostPort : int, optional + Port number for connection. + ignoreAuthError : str, optional + Ignore authentication errors. + hostDisconnect : bool, optional + Whether to disconnect the host. + blUpdateVolSpace : bool, optional + Update volume space information. + enable_rec : bool, optional + Enable recording. + cms_locked : bool, optional + Whether the CMS is locked. + cms_masked : bool, optional + Whether the CMS is masked. + cms_sync_time : bool, optional + Synchronize time with CMS. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the login operation or error details. + + Notes + ----- + 2.3.15.9 API Error Code Code Description 400 Execution failed. 401 Invalid parameter. - 415 message connect failed. """ + 415 message connect failed. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] @@ -1552,6 +3145,45 @@ def save_slave_ds(self, cms_masked: bool = None, # TODO not working cms_sync_time: bool = None) -> dict[str, object] | str: + """ + Save or update a slave DiskStation's configuration in the CMS. + + Parameters + ---------- + slavedsName : str, optional + Name of the slave DiskStation. + slavedsModel : str, optional + Model of the slave DiskStation. + slavedsPort : int, optional + Port number used by the slave DiskStation. + slavedsVersion : str, optional + Version of the slave DiskStation. + slavedsMaxCamNum : int, optional + Maximum number of cameras supported by the slave DiskStation. + slavedsId : str, optional + Identifier for the slave DiskStation. + slavedsIP : str, optional + IP address of the slave DiskStation. + slavedsEnable : int, optional + Enable status of the slave DiskStation. + slavedsCamCnt : bool, optional + Number of cameras currently connected to the slave DiskStation. + adminUsername : str, optional + Administrator username for authentication. + adminPasswd : str, optional + Administrator password for authentication. + cms_locked : bool, optional + Whether the CMS is locked. + cms_masked : bool, optional + Whether the CMS is masked. + cms_sync_time : bool, optional + Synchronize time with CMS. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.GetDsStatus' info = self.gen_list[api_name] api_path = info['path'] @@ -1570,6 +3202,27 @@ def load_slave_ds_list(self, blRuntimeInfo: bool = None, dslds: str = None, sortInfo: int = None) -> dict[str, object] | str: + """ + Load the list of slave DiskStations from the CMS. + + Parameters + ---------- + blNeedStatus : bool, optional + Whether to include status information. + blGetSortInfo : bool, optional + Whether to include sorting information. + blRuntimeInfo : bool, optional + Whether to include runtime information. + dslds : str, optional + Comma-separated list of DiskStation IDs to load. + sortInfo : int, optional + Sorting information. + + Returns + ------- + dict[str, object] or str + List of slave DiskStations or error details. + """ api_name = 'SYNO.SurveillanceStation.CMS.SlavedsList' info = self.gen_list[api_name] api_path = info['path'] @@ -1597,6 +3250,45 @@ def count_number_of_logs(self, dsId: str = None, srcType: int = None, timezoneOffset: int = None) -> dict[str, object] | str: + """ + Count the number of logs in Surveillance Station based on various filters. + + Parameters + ---------- + slavedsName : str, optional + Name of the slave DiskStation. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of logs to count. + level : str, optional + Log level filter. + filterCamera : str, optional + Filter by camera. + cameraIds : str, optional + Comma-separated list of camera IDs. + dsfrom : int, optional + Start time (timestamp). + to : int, optional + End time (timestamp). + keyword : str, optional + Keyword to search in logs. + keywordDsId : str, optional + DiskStation ID for keyword search. + time2String : str, optional + Time string for filtering. + dsId : str, optional + DiskStation ID. + srcType : int, optional + Source type filter. + timezoneOffset : int, optional + Timezone offset. + + Returns + ------- + dict[str, object] or str + Count of logs or error details. + """ api_name = 'SYNO.SurveillanceStation.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -1606,10 +3298,7 @@ def count_number_of_logs(self, for key, val in locals().items(): if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: if val is not None: - if key == 'dsfrom': - req_param[str('from')] = val - else: - req_param[str(key)] = val + req_param[str(key)] = val return self.request_data(api_name, api_path, req_param) @@ -1625,6 +3314,39 @@ def clear_selected_logs(self, keywordDsId: str = None, srcType: int = None, timezoneOffset: int = None) -> dict[str, object] | str: + """ + Clear selected logs from Surveillance Station based on various filters. + + Parameters + ---------- + blClearAll : bool, optional + Whether to clear all logs. + level : int, optional + Log level filter. + dsId : int, optional + DiskStation ID. + filterCamera : str, optional + Filter by camera. + cameraIds : str, optional + Comma-separated list of camera IDs. + dsfrom : int, optional + Start time (timestamp). + to : int, optional + End time (timestamp). + keyword : str, optional + Keyword to search in logs. + keywordDsId : str, optional + DiskStation ID for keyword search. + srcType : int, optional + Source type filter. + timezoneOffset : int, optional + Timezone offset. + + Returns + ------- + dict[str, object] or str + Result of the clear operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -1656,6 +3378,47 @@ def get_information_log(self, all: bool = None, blIncludeRecCnt: str = None, blIncludeAuInfo: str = None) -> dict[str, object] | str: + """ + Retrieve information logs from Surveillance Station based on various filters. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of logs to retrieve. + level : str, optional + Log level filter. + filterCamera : str, optional + Filter by camera. + cameraIds : str, optional + Comma-separated list of camera IDs. + dsfrom : int, optional + Start time (timestamp). + to : int, optional + End time (timestamp). + keyword : str, optional + Keyword to search in logs. + keywordDsId : str, optional + DiskStation ID for keyword search. + time2String : str, optional + Time string for filtering. + dsId : int, optional + DiskStation ID. + srcType : int, optional + Source type filter. + all : bool, optional + Whether to retrieve all logs. + blIncludeRecCnt : str, optional + Include recording count information. + blIncludeAuInfo : str, optional + Include additional information. + + Returns + ------- + dict[str, object] or str + List of information logs or error details. + """ api_name = 'SYNO.SurveillanceStation.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -1672,6 +3435,14 @@ def get_information_log(self, return self.request_data(api_name, api_path, req_param) def get_advanced_settings_logs(self) -> dict[str, object] | str: + """ + Retrieve advanced log settings from Surveillance Station. + + Returns + ------- + dict[str, object] or str + Advanced log settings or error details. + """ api_name = 'SYNO.SurveillanceStation.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -1681,6 +3452,21 @@ def get_advanced_settings_logs(self) -> dict[str, object] | str: def set_advanced_setting_logs(self, data: Any = None) -> dict[str, object] | str: + """ + Set advanced log settings in Surveillance Station. + + Parameters + ---------- + data : Any, optional + List of log type settings to apply. + Example: + data=[{"SSLogType":321912835,"enable":1},{"SSLogType":321912836,"enable":0}] + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -1696,6 +3482,19 @@ def set_advanced_setting_logs(self, def load_license_data(self, # TODO not working num_only: int = None) -> dict[str, object] | str: + """ + Load license data from Surveillance Station. + + Parameters + ---------- + num_only : int, optional + If set, only the number of licenses will be returned. + + Returns + ------- + dict[str, object] or str + License data or error details. + """ api_name = 'SYNO.SurveillanceStation.License' info = self.gen_list[api_name] api_path = info['path'] @@ -1708,6 +3507,23 @@ def check_license_quota(self, camList: Any = None, # TODO not working camServerId: int = None) -> dict[str, object] | str: + """ + Check the license quota for cameras in Surveillance Station. + + Parameters + ---------- + camList : Any, optional + List of camera information dictionaries. + Example: + camList = [{"ip": "10.13.22.141", "model": "DCS-3110", "vendor": "DLink", "port": 80}] + camServerId : int, optional + Camera server ID. + + Returns + ------- + dict[str, object] or str + License quota information or error details. + """ api_name = 'SYNO.SurveillanceStation.License' info = self.gen_list[api_name] api_path = info['path'] @@ -1728,6 +3544,23 @@ def get_http_video_stream(self, writeHeader: bool = None, analyevent: bool = None, mountId: int = None) -> dict[str, object] | str: + """ + Retrieve an HTTP video event stream from Surveillance Station. + + Parameters + ---------- + writeHeader : bool, optional + Whether to include headers in the stream. + analyevent : bool, optional + Whether to analyze events in the stream. + mountId : int, optional + Mount ID for the stream. + + Returns + ------- + dict[str, object] or str + Video stream data or error details. + """ api_name = 'SYNO.SurveillanceStation.Stream' info = self.gen_list[api_name] api_path = info['path'] @@ -1767,6 +3600,67 @@ def save_action_rule(self, userName: str = None, # TODO not working password: str = None) -> dict[str, object] | str: + """ + Save or update an action rule in Surveillance Station. + + Parameters + ---------- + id : int, optional + Action rule ID. + name : str, optional + Name of the action rule. + ruleType : int, optional + Type of the rule. + actType : int, optional + Action type. + evtSrc : int, optional + Event source. + evtDsId : int, optional + Event DiskStation ID. + evtDevId : int, optional + Event device ID. + evtId : int, optional + Event ID. + evtItem : int, optional + Event item. + evtMinIntvl : int, optional + Minimum interval between events. + Actions : Any, optional + List of actions to perform. + actSchedule : str, optional + Action schedule. + Id : int, optional + Alternative action rule ID. + actSrc : int, optional + Action source. + actDsId : int, optional + Action DiskStation ID. + actDevId : int, optional + Action device ID. + actId : int, optional + Action ID. + actTimes : int, optional + Number of times to perform the action. + actTimeUnit : int, optional + Time unit for the action. + actTimeDur : int, optional + Duration for the action. + actItemId : int, optional + Action item ID. + actRetPos : int, optional + Action return position. + extUrl : str, optional + External URL for the action. + userName : str, optional + Username for authentication. + password : str, optional + Password for authentication. (Currently not working). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1781,6 +3675,14 @@ def save_action_rule(self, # TODO not working def download_action_rule(self) -> dict[str, object] | str: + """ + Download the history of action rules from Surveillance Station. + + Returns + ------- + dict[str, object] or str + Downloaded action rule history or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1791,6 +3693,14 @@ def download_action_rule(self) -> dict[str, object] | str: # TODO not working def send_data_2_player(self) -> dict[str, object] | str: + """ + Send data to the Surveillance Station player. + + Returns + ------- + dict[str, object] or str + Result of the send operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1801,6 +3711,19 @@ def send_data_2_player(self) -> dict[str, object] | str: # TODO not working def delete_all_histories_of_action_rule(self, idList: str = None) -> dict[str, object] | str: + """ + Delete all histories of specified action rules. + + Parameters + ---------- + idList : str, optional + Comma-separated list of action rule IDs to delete histories for. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1810,6 +3733,21 @@ def delete_all_histories_of_action_rule(self, idList: str = None) -> dict[str, o return self.request_data(api_name, api_path, req_param) def list_action_rules(self, start: str = None, limit: int = None) -> dict[str, object] | str: + """ + List action rules in Surveillance Station. + + Parameters + ---------- + start : str, optional + Start index for pagination. + limit : int, optional + Maximum number of action rules to return. + + Returns + ------- + dict[str, object] or str + List of action rules or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1820,6 +3758,19 @@ def list_action_rules(self, start: str = None, limit: int = None) -> dict[str, o # TODO not working def disable_action_rules(self, idList: str = None) -> dict[str, object] | str: + """ + Disable specified action rules in Surveillance Station. + + Parameters + ---------- + idList : str, optional + Comma-separated list of action rule IDs to disable. + + Returns + ------- + dict[str, object] or str + Result of the disable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1830,6 +3781,19 @@ def disable_action_rules(self, idList: str = None) -> dict[str, object] | str: # TODO not working def enable_action_rules(self, idList: str = None) -> dict[str, object] | str: + """ + Enable specified action rules in Surveillance Station. + + Parameters + ---------- + idList : str, optional + Comma-separated list of action rule IDs to enable. + + Returns + ------- + dict[str, object] or str + Result of the enable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1840,6 +3804,21 @@ def enable_action_rules(self, idList: str = None) -> dict[str, object] | str: # TODO not working def list_history_action_rules(self, start: int = None, limit: int = None) -> dict[str, object] | str: + """ + List the history of action rules in Surveillance Station. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of history records to return. + + Returns + ------- + dict[str, object] or str + List of action rule histories or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1850,6 +3829,19 @@ def list_history_action_rules(self, start: int = None, limit: int = None) -> dic # TODO not working def delete_action_rule(self, idList: str = None) -> dict[str, object] | str: + """ + Delete specified action rules from Surveillance Station. + + Parameters + ---------- + idList : str, optional + Comma-separated list of action rule IDs to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ActionRule' info = self.gen_list[api_name] api_path = info['path'] @@ -1863,6 +3855,25 @@ def get_list_of_emaps(self, limit: str = None, emapIds: int = None, includeItems: int = None) -> dict[str, object] | str: + """ + Retrieve a list of eMaps from Surveillance Station. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : str, optional + Maximum number of eMaps to return. + emapIds : int, optional + Specific eMap IDs to retrieve. + includeItems : int, optional + Whether to include items in the eMap. + + Returns + ------- + dict[str, object] or str + List of eMaps or error details. + """ api_name = 'SYNO.SurveillanceStation.Emap' info = self.gen_list[api_name] api_path = info['path'] @@ -1879,6 +3890,21 @@ def get_specific_emaps_setting(self, emapIds: int = None, # TODO to check includeImage: int = None) -> dict[str, object] | str: + """ + Retrieve specific eMap settings from Surveillance Station. + + Parameters + ---------- + emapIds : int, optional + The ID(s) of the eMap(s) to retrieve settings for. + includeImage : int, optional + Whether to include the eMap image in the response. + + Returns + ------- + dict[str, object] or str + The eMap settings or error details. + """ api_name = 'SYNO.SurveillanceStation.Emap' info = self.gen_list[api_name] api_path = info['path'] @@ -1894,6 +3920,19 @@ def get_specific_emaps_setting(self, def get_emap_image(self, # TODO to check filename: str = None) -> dict[str, object] | str: + """ + Retrieve an eMap image from Surveillance Station. + + Parameters + ---------- + filename : str, optional + The filename of the eMap image to retrieve. + + Returns + ------- + dict[str, object] or str + The eMap image data or error details. + """ api_name = 'SYNO.SurveillanceStation.Emap.Image' info = self.gen_list[api_name] api_path = info['path'] @@ -1908,6 +3947,14 @@ def get_emap_image(self, # TODO to check def get_autorized_ds_token(self) -> dict[str, object] | str: + """ + Retrieve an authorized DiskStation token for notifications. + + Returns + ------- + dict[str, object] or str + The authorized token or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -1921,6 +3968,23 @@ def set_message_event(self, subject: str = None, # TODO not working content: str = None) -> dict[str, object] | str: + """ + Set a customized message event in Surveillance Station. + + Parameters + ---------- + eventTypes : str, optional + The type(s) of event(s) to set the message for. + subject : str, optional + The subject of the message. + content : str, optional + The content of the message. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -1937,6 +4001,19 @@ def set_message_event(self, def get_message_event(self, # TODO not working eventTypes: int = None) -> dict[str, object] | str: + """ + Retrieve a customized message event from Surveillance Station. + + Parameters + ---------- + eventTypes : int, optional + The type(s) of event(s) to retrieve the message for. + + Returns + ------- + dict[str, object] or str + The message event data or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -1953,6 +4030,19 @@ def get_message_event(self, def set_notification_sender_name(self, # TODO not working ss_pkg_name: str = None) -> dict[str, object] | str: + """ + Set the sender name for Surveillance Station notifications. + + Parameters + ---------- + ss_pkg_name : str, optional + The sender name to set. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -1967,6 +4057,14 @@ def set_notification_sender_name(self, # TODO not working def get_notification_sender_name(self) -> dict[str, object] | str: + """ + Retrieve the sender name for Surveillance Station notifications. + + Returns + ------- + dict[str, object] or str + The sender name or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -1978,6 +4076,21 @@ def set_advanced_notification_setting(self, blSyncDSMNotify: bool = None, # TODO to check blCompactMsg: bool = None) -> dict[str, object] | str: + """ + Set advanced notification settings in Surveillance Station. + + Parameters + ---------- + blSyncDSMNotify : bool, optional + Whether to synchronize DSM notifications. + blCompactMsg : bool, optional + Whether to enable compact message format. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -1992,6 +4105,14 @@ def set_advanced_notification_setting(self, # TODO not working def get_advanced_notification_setting(self) -> dict[str, object] | str: + """ + Retrieve advanced notification settings from Surveillance Station. + + Returns + ------- + dict[str, object] or str + The advanced notification settings or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification' info = self.gen_list[api_name] api_path = info['path'] @@ -2016,6 +4137,47 @@ def send_test_mesg_to_primary_secondary_phone(self, hasSysSms: bool = None, # TODO to check apiId: str = None) -> dict[str, object] | str: + """ + Send a test message to the primary and secondary phone numbers via SMS. + + Parameters + ---------- + smsEnable : bool, optional + Whether SMS notifications are enabled. + smsMethod : int, optional + The SMS sending method. + smsProvider : str, optional + The SMS provider name. + userName : str, optional + Username for SMS provider authentication. + password : str, optional + Password for SMS provider authentication. + confirmPassword : str, optional + Confirmation of the password. + primaryPhoneCode : str, optional + Country code for the primary phone. + primaryPhonePrefix : str, optional + Prefix for the primary phone. + secondaryPhoneCode : str, optional + Country code for the secondary phone. + secondaryPhonePrefix : str, optional + Prefix for the secondary phone. + secondaryPhoneNumber : str, optional + The secondary phone number. + setMinMessageInterval : bool, optional + Whether to set a minimum message interval. + minMessageInterval : int, optional + The minimum interval between messages. + hasSysSms : bool, optional + Whether system SMS is enabled. + apiId : str, optional + The API ID for the SMS provider. + + Returns + ------- + dict[str, object] or str + Result of the test message operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS' info = self.gen_list[api_name] api_path = info['path'] @@ -2030,6 +4192,14 @@ def send_test_mesg_to_primary_secondary_phone(self, return self.request_data(api_name, api_path, req_param) def get_setting_notification_sms(self) -> dict[str, object] | str: + """ + Retrieve the SMS notification settings from Surveillance Station. + + Returns + ------- + dict[str, object] or str + The SMS notification settings or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS' info = self.gen_list[api_name] api_path = info['path'] @@ -2053,6 +4223,47 @@ def set_sms_service_setting(self, minMessageInterval: int = None, hasSysSms: bool = None, apiId: str = None) -> dict[str, object] | str: + """ + Set the SMS service settings for Surveillance Station notifications. + + Parameters + ---------- + smsEnable : bool, optional + Whether SMS notifications are enabled. + smsMethod : int, optional + The SMS sending method. + smsProvider : str, optional + The SMS provider name. + userName : str, optional + Username for SMS provider authentication. + password : str, optional + Password for SMS provider authentication. + confirmPassword : str, optional + Confirmation of the password. + primaryPhoneCode : str, optional + Country code for the primary phone. + primaryPhonePrefix : str, optional + Prefix for the primary phone. + secondaryPhoneCode : str, optional + Country code for the secondary phone. + secondaryPhonePrefix : str, optional + Prefix for the secondary phone. + secondaryPhoneNumber : str, optional + The secondary phone number. + setMinMessageInterval : bool, optional + Whether to set a minimum message interval. + minMessageInterval : int, optional + The minimum interval between messages. + hasSysSms : bool, optional + Whether system SMS is enabled. + apiId : str, optional + The API ID for the SMS provider. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS' info = self.gen_list[api_name] api_path = info['path'] @@ -2075,6 +4286,33 @@ def send_test_sms(self, synoMailEnable: bool = None, # TODO to check mail_recipient: str = None) -> dict[str, object] | str: + """ + Send a test SMS notification from Surveillance Station. + + Parameters + ---------- + attachSnapshot : bool, optional + Whether to attach a snapshot to the SMS. + enableInterval : bool, optional + Whether to enable message interval. + mobileEnable : bool, optional + Whether to enable mobile notifications. + msgInterval : str, optional + The interval between messages. + primaryEmail : str, optional + The primary email address for notifications. + secondaryEmail : str, optional + The secondary email address for notifications. + synoMailEnable : bool, optional + Whether to enable Synology Mail notifications. + mail_recipient : str, optional + The recipient of the test mail. + + Returns + ------- + dict[str, object] or str + Result of the test SMS operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS' info = self.gen_list[api_name] api_path = info['path'] @@ -2098,6 +4336,33 @@ def send_test_mail(self, synoMailEnable: bool = None, # TODO to check mail_recipient: str = None) -> dict[str, object] | str: + """ + Send a test verification mail for Surveillance Station notifications. + + Parameters + ---------- + attachSnapshot : bool, optional + Whether to attach a snapshot to the email. + enableInterval : bool, optional + Whether to enable message interval. + mobileEnable : bool, optional + Whether to enable mobile notifications. + msgInterval : str, optional + The interval between messages. + primaryEmail : str, optional + The primary email address for notifications. + secondaryEmail : str, optional + The secondary email address for notifications. + synoMailEnable : bool, optional + Whether to enable Synology Mail notifications. + mail_recipient : str, optional + The recipient of the test mail. + + Returns + ------- + dict[str, object] or str + Result of the test mail operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.PushService' info = self.gen_list[api_name] api_path = info['path'] @@ -2120,6 +4385,33 @@ def list_mobile_paired_devices(self, secondaryEmail: str = None, synoMailEnable: bool = None, mail_recipient: str = None) -> dict[str, object] | str: + """ + List mobile devices paired with Surveillance Station for push notifications. + + Parameters + ---------- + attachSnapshot : bool, optional + Whether to attach a snapshot to the notification. + enableInterval : bool, optional + Whether to enable message interval. + mobileEnable : bool, optional + Whether to enable mobile notifications. + msgInterval : str, optional + The interval between messages. + primaryEmail : str, optional + The primary email address for notifications. + secondaryEmail : str, optional + The secondary email address for notifications. + synoMailEnable : bool, optional + Whether to enable Synology Mail notifications. + mail_recipient : str, optional + The recipient of the notification. + + Returns + ------- + dict[str, object] or str + List of paired mobile devices or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.PushService' info = self.gen_list[api_name] api_path = info['path'] @@ -2135,6 +4427,19 @@ def list_mobile_paired_devices(self, def unpair_device(self, targetIds: str = None) -> dict[str, object] | str: + """ + Unpair a mobile device from Surveillance Station notifications. + + Parameters + ---------- + targetIds : str, optional + The ID(s) of the device(s) to unpair. + + Returns + ------- + dict[str, object] or str + Result of the unpair operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.PushService' info = self.gen_list[api_name] api_path = info['path'] @@ -2150,6 +4455,19 @@ def unpair_device(self, def get_controller_access_schedule(self, # TODO to check targetIds: str = None) -> dict[str, object] | str: + """ + Retrieve the access control controller schedule from Surveillance Station. + + Parameters + ---------- + targetIds : str, optional + The ID(s) of the controllers to retrieve the schedule for. + + Returns + ------- + dict[str, object] or str + The controller access schedule or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2167,6 +4485,21 @@ def get_camera_alarm_schedule(self, cameraId: int = None, # TODO to check alarmdx: int = None) -> dict[str, object] | str: + """ + Retrieve the alarm schedule for a specific camera. + + Parameters + ---------- + cameraId : int, optional + The ID of the camera. + alarmdx : int, optional + Additional alarm parameter (to check). + + Returns + ------- + dict[str, object] or str + The camera alarm schedule or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2183,6 +4516,19 @@ def get_camera_alarm_schedule(self, def get_sys_dependent_schedule(self, # TODO to check eventGroupTypes: int = None) -> dict[str, object] | str: + """ + Retrieve the system dependent schedule for Surveillance Station events. + + Parameters + ---------- + eventGroupTypes : int, optional + The type(s) of event groups to retrieve the schedule for. + + Returns + ------- + dict[str, object] or str + The system dependent schedule or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2203,6 +4549,27 @@ def set_batch_schedule(self, cameraGroupIds: str = None, # TODO to check filter: int = None) -> dict[str, object] | str: + """ + Set batch schedules for events, cameras, or camera groups. + + Parameters + ---------- + eventTypes : str, optional + The type(s) of events to schedule. + schedule : Any, optional + The schedule data to apply. + cameraIds : str, optional + The IDs of cameras to apply the schedule to. + cameraGroupIds : str, optional + The IDs of camera groups to apply the schedule to. + filter : int, optional + Additional filter parameter (to check). + + Returns + ------- + dict[str, object] or str + Result of the batch schedule operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2219,6 +4586,19 @@ def set_batch_schedule(self, def get_access_ctrl_door_schedule(self, # TODO to check doorId: str = None) -> dict[str, object] | str: + """ + Retrieve the access control door schedule from Surveillance Station. + + Parameters + ---------- + doorId : str, optional + The ID of the door to retrieve the schedule for. + + Returns + ------- + dict[str, object] or str + The door schedule or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2235,6 +4615,19 @@ def get_access_ctrl_door_schedule(self, def get_camera_schedule(self, # TODO to check cameraId: str = None) -> dict[str, object] | str: + """ + Retrieve the schedule for a specific camera. + + Parameters + ---------- + cameraId : str, optional + The ID of the camera to retrieve the schedule for. + + Returns + ------- + dict[str, object] or str + The camera schedule or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2252,6 +4645,21 @@ def set_sys_dependent_schedule(self, eventType: int = None, # TODO to check schedule: Any = None) -> dict[str, object] | str: + """ + Set the system dependent schedule for Surveillance Station events. + + Parameters + ---------- + eventType : int, optional + The type of event to set the schedule for. + schedule : Any, optional + The schedule data to apply. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2270,6 +4678,23 @@ def set_controller_access_schedule(self, schedule: Any = None, # TODO to check doorId: int = None) -> dict[str, object] | str: + """ + Set the access control schedule for a controller or door. + + Parameters + ---------- + eventType : int, optional + The type of event to set the schedule for. + schedule : Any, optional + The schedule data to apply. + doorId : int, optional + The ID of the door to set the schedule for. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2288,6 +4713,23 @@ def set_camera_schedule(self, schedule: Any = None, # TODO to check cameraId: Any = None) -> dict[str, object] | str: + """ + Set the schedule for a specific camera in Surveillance Station. + + Parameters + ---------- + eventType : int, optional + The type of event to set the schedule for. + schedule : Any, optional + The schedule data to apply. + cameraId : Any, optional + The ID of the camera to set the schedule for. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Schedule' info = self.gen_list[api_name] api_path = info['path'] @@ -2302,6 +4744,14 @@ def set_camera_schedule(self, return self.request_data(api_name, api_path, req_param) def get_notification_email_string(self) -> dict[str, object] | str: + """ + Retrieve the notification email settings string from Surveillance Station. + + Returns + ------- + dict[str, object] or str + The notification email settings or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Email' info = self.gen_list[api_name] api_path = info['path'] @@ -2312,6 +4762,19 @@ def get_notification_email_string(self) -> dict[str, object] | str: def set_adv_tab_info_filter(self, # TODO to check X: int = None) -> dict[str, object] | str: + """ + Set the advanced tab information filter for notification emails. + + Parameters + ---------- + X : int, optional + The filter value to set (to check). + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.Email' info = self.gen_list[api_name] api_path = info['path'] @@ -2331,6 +4794,29 @@ def create_sms_service_provider(self, providerTemplate: str = None, providerSepChar: str = None, providerNeedSSL: bool = None) -> dict[str, object] | str: + """ + Create a new SMS service provider for Surveillance Station notifications. + + Parameters + ---------- + providerName : str, optional + The name of the SMS provider. + providerPort : int, optional + The port used by the provider. + providerUrl : str, optional + The URL of the provider. + providerTemplate : str, optional + The message template for the provider. + providerSepChar : str, optional + The separator character used by the provider. + providerNeedSSL : bool, optional + Whether SSL is required for the provider. + + Returns + ------- + dict[str, object] or str + Result of the create operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS.ServiceProvider' info = self.gen_list[api_name] api_path = info['path'] @@ -2344,6 +4830,14 @@ def create_sms_service_provider(self, return self.request_data(api_name, api_path, req_param) def list_sms_provider(self) -> dict[str, object] | str: + """ + List all SMS service providers configured in Surveillance Station. + + Returns + ------- + dict[str, object] or str + List of SMS providers or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS.ServiceProvider' info = self.gen_list[api_name] api_path = info['path'] @@ -2354,6 +4848,19 @@ def list_sms_provider(self) -> dict[str, object] | str: def delete_sms_service_provider(self, # TODO to check providerName: str = None) -> dict[str, object] | str: + """ + Delete an SMS service provider from Surveillance Station. + + Parameters + ---------- + providerName : str, optional + The name of the SMS provider to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Notification.SMS.ServiceProvider' info = self.gen_list[api_name] api_path = info['path'] @@ -2367,6 +4874,14 @@ def delete_sms_service_provider(self, return self.request_data(api_name, api_path, req_param) def get_addson_to_update(self) -> dict[str, object] | str: + """ + Retrieve information about add-ons that require updates in Surveillance Station. + + Returns + ------- + dict[str, object] or str + Add-on update information or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2378,6 +4893,21 @@ def enable_specific_addon(self, service: int = None, # TODO to check servicename: str = None) -> dict[str, object] | str: + """ + Enable a specific add-on in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to enable. + servicename : str, optional + The name of the add-on service to enable. + + Returns + ------- + dict[str, object] or str + Result of the enable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2393,6 +4923,19 @@ def enable_specific_addon(self, def get_specific_addon_update_info(self, # TODO to check service: int = None) -> dict[str, object] | str: + """ + Retrieve update information for a specific add-on in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to check for updates. + + Returns + ------- + dict[str, object] or str + Update information or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2409,6 +4952,19 @@ def get_specific_addon_update_info(self, def get_specific_addon_info(self, # TODO to check service: int = None) -> dict[str, object] | str: + """ + Retrieve information for a specific add-on in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to retrieve information for. + + Returns + ------- + dict[str, object] or str + Add-on information or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2422,6 +4978,14 @@ def get_specific_addon_info(self, return self.request_data(api_name, api_path, req_param) def get_total_addon_info(self) -> dict[str, object] | str: # TODO to check + """ + Retrieve information about all add-ons in Surveillance Station. + + Returns + ------- + dict[str, object] or str + List of all add-ons or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2433,6 +4997,21 @@ def update_addon_package(self, service: int = None, # TODO to check filePath: str = None) -> dict[str, object] | str: + """ + Update an add-on package in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to update. + filePath : str, optional + The file path to the add-on package (to check). + + Returns + ------- + dict[str, object] or str + Result of the update operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2448,6 +5027,19 @@ def update_addon_package(self, def check_addon_status(self, # TODO to check service: int = None) -> dict[str, object] | str: + """ + Check the enable status of a specific add-on in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to check (to check). + + Returns + ------- + dict[str, object] or str + Status information or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2465,6 +5057,21 @@ def disable_addon(self, service: int = None, # TODO to check serviceName: str = None) -> dict[str, object] | str: + """ + Disable a specific add-on in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to disable. + serviceName : str, optional + The name of the add-on service to disable (to check). + + Returns + ------- + dict[str, object] or str + Result of the disable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2481,6 +5088,21 @@ def set_addon_autoupdate(self, service: int = None, # TODO to check BlEnabled: Any = None) -> dict[str, object] | str: + """ + Set the auto-update setting for a specific add-on in Surveillance Station. + + Parameters + ---------- + service : int, optional + The ID of the add-on service to configure. + BlEnabled : Any, optional + Whether auto-update is enabled (to check). + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AddOns' info = self.gen_list[api_name] api_path = info['path'] @@ -2496,6 +5118,19 @@ def set_addon_autoupdate(self, def delete_specific_camera_recording_server(self, # TODO to check camIdList: str = None) -> dict[str, object] | str: + """ + Delete a specific camera recording server in Surveillance Station. + + Parameters + ---------- + camIdList : str, optional + List of camera IDs to delete from the recording server (to check). + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2511,6 +5146,19 @@ def delete_specific_camera_recording_server(self, def get_camera_event_analytic(self, # TODO to check camIdList: str = None) -> dict[str, object] | str: + """ + Retrieve camera event analytics from Surveillance Station. + + Parameters + ---------- + camIdList : str, optional + List of camera IDs to retrieve analytics for (to check). + + Returns + ------- + dict[str, object] or str + Analytics data or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2527,6 +5175,21 @@ def delete_selected_events(self, dsIdList: str = None, # TODO to check idList: str = None) -> dict[str, object] | str: + """ + Delete selected events from Surveillance Station. + + Parameters + ---------- + dsIdList : str, optional + List of DS IDs for which to delete events. + idList : str, optional + List of event IDs to delete (to check). + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2542,6 +5205,19 @@ def delete_selected_events(self, def delete_specific_camera_events(self, # TODO to check camIdList: str = None) -> dict[str, object] | str: + """ + Delete events for specific cameras in Surveillance Station. + + Parameters + ---------- + camIdList : str, optional + List of camera IDs for which to delete events (to check). + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2558,6 +5234,21 @@ def get_analytic_history(self, camIdList: str = None, # TODO to check typeListstring: str = None) -> dict[str, object] | str: + """ + Retrieve analytic history for cameras in Surveillance Station. + + Parameters + ---------- + camIdList : str, optional + List of camera IDs to retrieve history for. + typeListstring : str, optional + List of analytic types as a string (to check). + + Returns + ------- + dict[str, object] or str + Analytic history data or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2576,6 +5267,25 @@ def get_analytic_history_by_filter(self, lock: int = None, # TODO to check typeList: str = None) -> dict[str, object] | str: + """ + Retrieve analytic history for cameras by filter in Surveillance Station. + + Parameters + ---------- + camIdList : str, optional + List of camera IDs to filter. + dsId : int, optional + The DS ID to filter. + lock : int, optional + Lock status to filter. + typeList : str, optional + List of analytic types as a string (to check). + + Returns + ------- + dict[str, object] or str + Filtered analytic history data or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2592,6 +5302,21 @@ def unklock_selected_events(self, dsId: int = None, # TODO to check idList: str = None) -> dict[str, object] | str: + """ + Unlock selected events in Surveillance Station. + + Parameters + ---------- + dsId : int, optional + The DS ID for which to unlock events. + idList : str, optional + List of event IDs to unlock (to check). + + Returns + ------- + dict[str, object] or str + Result of the unlock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2607,6 +5332,19 @@ def unklock_selected_events(self, def set_camera_analytic_trigger(self, # TODO to check trigCamIdList: str = None) -> dict[str, object] | str: + """ + Trigger camera analytics for specified cameras in Surveillance Station. + + Parameters + ---------- + trigCamIdList : str, optional + List of camera IDs to trigger analytics for (to check). + + Returns + ------- + dict[str, object] or str + Result of the trigger operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2622,6 +5360,19 @@ def set_camera_analytic_trigger(self, def flush_event_header(self, # TODO to check eventId: str = None) -> dict[str, object] | str: + """ + Flush the header of a specific event in Surveillance Station. + + Parameters + ---------- + eventId : str, optional + The ID of the event to flush the header for (to check). + + Returns + ------- + dict[str, object] or str + Result of the flush operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2639,6 +5390,21 @@ def lock_selected_events(self, dsId: int = None, # TODO to check idList: str = None) -> dict[str, object] | str: + """ + Lock selected events in Surveillance Station. + + Parameters + ---------- + dsId : int, optional + The DS ID for which to lock events. + idList : str, optional + List of event IDs to lock (to check). + + Returns + ------- + dict[str, object] or str + Result of the lock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2655,6 +5421,21 @@ def get_analytic_event_from_rec_server(self, camIdList: str = None, # TODO to check idList: int = None) -> dict[str, object] | str: + """ + Retrieve analytic event counts from the recording server for specified cameras. + + Parameters + ---------- + camIdList : str, optional + Comma-separated list of camera IDs to query. + idList : int, optional + Additional ID list parameter (to check). + + Returns + ------- + dict[str, object] or str + Analytic event count data or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert' info = self.gen_list[api_name] api_path = info['path'] @@ -2681,6 +5462,39 @@ def save_analytic_settings(self, objSize: int = None, # TODO to check region: str = None) -> dict[str, object] | str: + """ + Save analytic settings for a specific camera. + + Parameters + ---------- + camId : int, optional + Camera ID to apply settings to. + type : int, optional + Type of analytic. + showFrame : bool, optional + Whether to display the frame. + showLine : bool, optional + Whether to display lines. + showVirtualFence : bool, optional + Whether to display virtual fences. + beep : bool, optional + Whether to enable beep on event. + sens : int, optional + Sensitivity setting. + dwellTime : int, optional + Dwell time setting. + direction : int, optional + Direction setting. + objSize : int, optional + Object size setting. + region : str, optional + Region definition (to check). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Alert.Setting' info = self.gen_list[api_name] api_path = info['path'] @@ -2696,6 +5510,19 @@ def save_analytic_settings(self, def check_if_snapshot_exist(self, # TODO to check id: int = None) -> dict[str, object] | str: + """ + Check if a snapshot exists for a given ID. + + Parameters + ---------- + id : int, optional + Snapshot ID to check (to check). + + Returns + ------- + dict[str, object] or str + Existence status or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2716,6 +5543,29 @@ def save_snapshot_modification(self, byteSize: int = None, # TODO to check imageData: str = None) -> dict[str, object] | str: + """ + Save modifications to a snapshot. + + Parameters + ---------- + id : int, optional + Snapshot ID to modify. + createCopy : bool, optional + Whether to create a copy of the snapshot. + width : int, optional + Width of the snapshot. + height : int, optional + Height of the snapshot. + byteSize : int, optional + Size of the snapshot in bytes. + imageData : str, optional + Image data (to check). + + Returns + ------- + dict[str, object] or str + Result of the modification or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2736,6 +5586,29 @@ def count_snapshot_by_category(self, byteSize: int = None, # TODO to check imageData: str = None) -> dict[str, object] | str: + """ + Count snapshots by category within a specified range. + + Parameters + ---------- + keyword : str, optional + Keyword to filter snapshots. + dsfrom : int, optional + Start timestamp. + to : int, optional + End timestamp. + timezoneOffset : int, optional + Timezone offset. + byteSize : int, optional + Size of the snapshot in bytes. + imageData : str, optional + Image data (to check). + + Returns + ------- + dict[str, object] or str + Count data or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2758,6 +5631,25 @@ def check_any_locked_snapshot(self, to: int = None, # TODO to check keyword: str = None) -> dict[str, object] | str: + """ + Check if any locked snapshots exist within a specified range. + + Parameters + ---------- + id : str, optional + Snapshot ID(s) to check. + dsfrom : int, optional + Start timestamp. + to : int, optional + End timestamp. + keyword : str, optional + Keyword to filter snapshots (to check). + + Returns + ------- + dict[str, object] or str + Lock status or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2779,6 +5671,23 @@ def unlock_snapshot_by_filter(self, to: int = None, # TODO to check keyword: str = None) -> dict[str, object] | str: + """ + Unlock snapshots by filter within a specified range. + + Parameters + ---------- + dsfrom : int, optional + Start timestamp. + to : int, optional + End timestamp. + keyword : str, optional + Keyword to filter snapshots (to check). + + Returns + ------- + dict[str, object] or str + Result of the unlock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2806,6 +5715,37 @@ def list_snapshot_information(self, blIncludeRecCnt: bool = None, # TODO to check camId: int = None) -> dict[str, object] | str: + """ + List snapshot information with optional filters. + + Parameters + ---------- + idList : str, optional + Comma-separated list of snapshot IDs. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + dsfrom : int, optional + Start timestamp. + to : int, optional + End timestamp. + keyword : str, optional + Keyword to filter snapshots. + imgSize : int, optional + Image size filter. + blIncludeAuInfo : bool, optional + Whether to include additional info. + blIncludeRecCnt : bool, optional + Whether to include recording count. + camId : int, optional + Camera ID filter (to check). + + Returns + ------- + dict[str, object] or str + List of snapshot information or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2824,6 +5764,19 @@ def list_snapshot_information(self, def unlock_snapshot(self, # TODO to check objList: Any = None) -> dict[str, object] | str: + """ + Unlock specific snapshots. + + Parameters + ---------- + objList : Any, optional + List of snapshot objects to unlock (to check). + + Returns + ------- + dict[str, object] or str + Result of the unlock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2841,6 +5794,23 @@ def take_snapshot(self, camId: int = None, # TODO to check blSave: bool = None) -> dict[str, object] | str: + """ + Take a snapshot for a specific camera and DS. + + Parameters + ---------- + dsId : int, optional + DS ID for the snapshot. + camId : int, optional + Camera ID for the snapshot. + blSave : bool, optional + Whether to save the snapshot (to check). + + Returns + ------- + dict[str, object] or str + Result of the snapshot operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2855,6 +5825,14 @@ def take_snapshot(self, # TODO to check def get_snapshot_setting_function(self) -> dict[str, object] | str: + """ + Retrieve the snapshot setting function. + + Returns + ------- + dict[str, object] or str + Snapshot setting information or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2868,6 +5846,25 @@ def delete_snapshot_by_filter(self, to: int = None, # TODO to check keyword: str = None) -> dict[str, object] | str: + """ + Delete snapshots by filter within a specified range. + + Parameters + ---------- + deleteAllCommand : bool, optional + Whether to delete all snapshots. + dsfrom : int, optional + Start timestamp. + to : int, optional + End timestamp. + keyword : str, optional + Keyword to filter snapshots (to check). + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2887,6 +5884,21 @@ def get_snapshot_image(self, id: int = None, # TODO to modify for download? imgSize: int = None) -> dict[str, object] | str: + """ + Retrieve a snapshot image by ID. + + Parameters + ---------- + id : int, optional + Snapshot ID to retrieve. + imgSize : int, optional + Image size (to modify for download?). + + Returns + ------- + dict[str, object] or str + Snapshot image data or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2901,6 +5913,19 @@ def get_snapshot_image(self, def lock_snapshot_image(self, objList: Any = None) -> dict[str, object] | str: + """ + Lock specific snapshot images. + + Parameters + ---------- + objList : Any, optional + List of snapshot objects to lock. + + Returns + ------- + dict[str, object] or str + Result of the lock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2913,9 +5938,23 @@ def lock_snapshot_image(self, return self.request_data(api_name, api_path, req_param) + # TODO: fix typo def downld_single_snapshot(self, # TODO not working id: int = None) -> dict[str, object] | str: + """ + Download a single snapshot by ID. + + Parameters + ---------- + id : int, optional + Snapshot ID to download (not working). + + Returns + ------- + dict[str, object] or str + Download result or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2935,6 +5974,29 @@ def save_new_snapshot_setting(self, limitSizeInGb: int = None, addTimestamp: bool = None, timestampPosition: int = None) -> dict[str, object] | str: + """ + Save new snapshot settings. + + Parameters + ---------- + dispSnapshot : bool, optional + Whether to display snapshots. + dispDuration : int, optional + Display duration for snapshots. + limitTotalSize : bool, optional + Whether to limit total snapshot size. + limitSizeInGb : int, optional + Limit size in GB. + addTimestamp : bool, optional + Whether to add a timestamp to snapshots. + timestampPosition : int, optional + Position of the timestamp. + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2955,6 +6017,29 @@ def save_snapshot(self, byteSize: int = None, # TODO to check imageData: str = None) -> dict[str, object] | str: + """ + Save a new snapshot. + + Parameters + ---------- + camName : str, optional + Name of the camera. + createdTm : int, optional + Creation timestamp. + width : int, optional + Width of the snapshot. + height : int, optional + Height of the snapshot. + byteSize : int, optional + Size of the snapshot in bytes. + imageData : str, optional + Image data (to check). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2969,6 +6054,19 @@ def save_snapshot(self, def check_snapshot_status(self, dispSnapshot: bool = None) -> dict[str, object] | str: + """ + Check the status of snapshot display. + + Parameters + ---------- + dispSnapshot : bool, optional + Whether to display snapshots. + + Returns + ------- + dict[str, object] or str + Status information or error details. + """ api_name = 'SYNO.SurveillanceStation.SnapShot' info = self.gen_list[api_name] api_path = info['path'] @@ -2985,6 +6083,19 @@ def check_snapshot_status(self, def enable_visualstation(self, # TODO to check vslist: str = None) -> dict[str, object] | str: + """ + Enable VisualStation devices. + + Parameters + ---------- + vslist : str, optional + Comma-separated list of VisualStation IDs to enable (to check). + + Returns + ------- + dict[str, object] or str + Result of the enable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3005,6 +6116,29 @@ def update_vs_network_config(self, blDhcp: bool = None, # TODO to check name: str = None) -> dict[str, object] | str: + """ + Update the network configuration for a VisualStation device. + + Parameters + ---------- + vsMAc : str, optional + MAC address of the VisualStation. + ip : str, optional + IP address to assign. + mask : str, optional + Subnet mask. + gateway : str, optional + Gateway address. + blDhcp : bool, optional + Whether to use DHCP. + name : str, optional + Name of the VisualStation (to check). + + Returns + ------- + dict[str, object] or str + Result of the update operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3020,6 +6154,19 @@ def update_vs_network_config(self, def lock_visualstation_by_id(self, # TODO to check vslist: str = None) -> dict[str, object] | str: + """ + Lock VisualStation devices by ID. + + Parameters + ---------- + vslist : str, optional + Comma-separated list of VisualStation IDs to lock (to check). + + Returns + ------- + dict[str, object] or str + Result of the lock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3034,6 +6181,14 @@ def lock_visualstation_by_id(self, # TODO to check def enumerate_vs_owner_info(self) -> dict[str, object] | str: + """ + Enumerate VisualStation owner information. + + Returns + ------- + dict[str, object] or str + Owner information or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3044,6 +6199,19 @@ def enumerate_vs_owner_info(self) -> dict[str, object] | str: def unlock_visualstation_by_id(self, # TODO to check vslist: str = None) -> dict[str, object] | str: + """ + Unlock VisualStation devices by ID. + + Parameters + ---------- + vslist : str, optional + Comma-separated list of VisualStation IDs to unlock (to check). + + Returns + ------- + dict[str, object] or str + Result of the unlock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3059,6 +6227,19 @@ def unlock_visualstation_by_id(self, def disable_visualstation_by_id(self, # TODO to check vslist: str = None) -> dict[str, object] | str: + """ + Disable VisualStation devices by ID. + + Parameters + ---------- + vslist : str, optional + Comma-separated list of VisualStation IDs to disable (to check). + + Returns + ------- + dict[str, object] or str + Result of the disable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3074,6 +6255,19 @@ def disable_visualstation_by_id(self, def delete_specific_visualstation(self, # TODO to check vslist: str = None) -> dict[str, object] | str: + """ + Delete specific VisualStation devices by ID. + + Parameters + ---------- + vslist : str, optional + Comma-separated list of VisualStation IDs to delete (to check). + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation' info = self.gen_list[api_name] api_path = info['path'] @@ -3089,6 +6283,19 @@ def delete_specific_visualstation(self, def enumerate_layout_visualstation(self, # TODO to check vsId: int = None) -> dict[str, object] | str: + """ + Enumerate VisualStation layouts. + + Parameters + ---------- + vsId : int, optional + VisualStation ID to filter layouts (to check). + + Returns + ------- + dict[str, object] or str + Layout information or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Layout' info = self.gen_list[api_name] api_path = info['path'] @@ -3112,6 +6319,35 @@ def save_layout_information(self, channelList: Any = None, # TODO to check customPosList: str = None) -> dict[str, object] | str: + """ + Save layout information for a VisualStation. + + Parameters + ---------- + id : int, optional + Layout ID. + vsId : int, optional + VisualStation ID. + name : str, optional + Name of the layout. + canGrpId : int, optional + Camera group ID. + isDefault : int, optional + Whether this is the default layout. + isFixAspectRatio : int, optional + Whether to fix the aspect ratio. + layoutType : int, optional + Type of the layout. + channelList : Any, optional + List of channels in the layout. + customPosList : str, optional + Custom position list (to check). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Layout' info = self.gen_list[api_name] api_path = info['path'] @@ -3128,6 +6364,21 @@ def delete_layout_visualstation(self, id: int = None, # TODO to check vsId: int = None) -> dict[str, object] | str: + """ + Delete a VisualStation layout. + + Parameters + ---------- + id : int, optional + Layout ID to delete. + vsId : int, optional + VisualStation ID (to check). + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Layout' info = self.gen_list[api_name] api_path = info['path'] @@ -3142,6 +6393,14 @@ def delete_layout_visualstation(self, # TODO to check def clear_visualstation_search_result(self) -> dict[str, object] | str: + """ + Clear VisualStation search results. + + Returns + ------- + dict[str, object] or str + Result of the clear operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -3152,6 +6411,19 @@ def clear_visualstation_search_result(self) -> dict[str, object] | str: def get_visualstation_ip_info(self, # TODO to check ip: int = None) -> dict[str, object] | str: + """ + Retrieve VisualStation IP information. + + Parameters + ---------- + ip : int, optional + IP address to search for (to check). + + Returns + ------- + dict[str, object] or str + IP information or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -3166,6 +6438,14 @@ def get_visualstation_ip_info(self, # TODO to check def stop_previous_visualstation_search(self) -> dict[str, object] | str: + """ + Stop the previous VisualStation search operation. + + Returns + ------- + dict[str, object] or str + Result of the stop operation or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -3176,6 +6456,19 @@ def stop_previous_visualstation_search(self) -> dict[str, object] | str: def get_visualstation_list(self, # TODO to check offset: int = None) -> dict[str, object] | str: + """ + Retrieve the list of VisualStation devices. + + Parameters + ---------- + offset : int, optional + Offset for pagination (to check). + + Returns + ------- + dict[str, object] or str + List of VisualStation devices or error details. + """ api_name = 'SYNO.SurveillanceStation.VisualStation.Layout' info = self.gen_list[api_name] api_path = info['path'] @@ -3189,6 +6482,14 @@ def get_visualstation_list(self, return self.request_data(api_name, api_path, req_param) def get_number_of_controller(self) -> dict[str, object] | str: + """ + Get the number of controllers in the system. + + Returns + ------- + dict[str, object] or str + Number of controllers or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3197,6 +6498,19 @@ def get_number_of_controller(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_cardholder_count(self, filterKeyword: str = None) -> dict[str, object] | str: + """ + Get the count of cardholders, optionally filtered by keyword. + + Parameters + ---------- + filterKeyword : str, optional + Keyword to filter cardholders. + + Returns + ------- + dict[str, object] or str + Cardholder count or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3211,6 +6525,14 @@ def get_cardholder_count(self, filterKeyword: str = None) -> dict[str, object] | return self.request_data(api_name, api_path, req_param) def enum_all_controllers_logger(self) -> dict[str, object] | str: + """ + Enumerate all controller logger configurations. + + Returns + ------- + dict[str, object] or str + Logger configuration information or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3222,6 +6544,21 @@ def get_cardholder_photo(self, photo_name: str = None, # TODO to check isRedirectCgi: bool = None) -> dict[str, object] | str: + """ + Retrieve a cardholder's photo. + + Parameters + ---------- + photo_name : str, optional + Name of the photo file. + isRedirectCgi : bool, optional + Whether to redirect to CGI for the photo (to check). + + Returns + ------- + dict[str, object] or str + Photo data or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3249,6 +6586,43 @@ def get_log_count(self, doorIds: str = None, eventTypes: str = None, update: int = None) -> dict[str, object] | str: + """ + Get the count of logs with optional filters. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + filterType : int, optional + Type of filter to apply. + filterEventSource : Any, optional + Event source filter. + filterSource : int, optional + Source filter. + filterEventSourceItem : int, optional + Event source item filter. + filterTimeFrom : int, optional + Start time for filtering. + filterTimeTo : int, optional + End time for filtering. + filterKeyword : str, optional + Keyword to filter logs. + timezoneOffset : int, optional + Timezone offset. + doorIds : str, optional + Door IDs filter. + eventTypes : str, optional + Event types filter. + update : int, optional + Update flag. + + Returns + ------- + dict[str, object] or str + Log count or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3268,6 +6642,27 @@ def get_cardholder_info(self, filterKeyword: str = None, filterStatus: int = None, filterCtrlerId: int = None) -> dict[str, object] | str: + """ + Retrieve cardholder information with optional filters. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + filterKeyword : str, optional + Keyword to filter cardholders. + filterStatus : int, optional + Status filter. + filterCtrlerId : int, optional + Controller ID filter. + + Returns + ------- + dict[str, object] or str + Cardholder information or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3284,6 +6679,21 @@ def retrieve_last_access_credential(self, ctrlerId: int = None, # TODO to check idPtId: int = None) -> dict[str, object] | str: + """ + Retrieve the last access credential for a controller. + + Parameters + ---------- + ctrlerId : int, optional + Controller ID. + idPtId : int, optional + ID/point ID (to check). + + Returns + ------- + dict[str, object] or str + Last access credential information or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3300,6 +6710,21 @@ def retrieve_last_access_credential(self, def enable_disable_controller(self, blEnable: bool = None, arrayJson: str = None) -> dict[str, object] | str: + """ + Enable or disable controllers. + + Parameters + ---------- + blEnable : bool, optional + Whether to enable (True) or disable (False) controllers. + arrayJson : str, optional + JSON array of controller IDs. + + Returns + ------- + dict[str, object] or str + Result of the operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3323,6 +6748,37 @@ def acknowledge_all_alarm_level_log(self, doorIds: str = None, eventTypes: str = None, update: int = None) -> dict[str, object] | str: + """ + Acknowledge all alarm level logs with optional filters. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + filterEventSource : Any, optional + Event source filter. + filterSource : int, optional + Source filter. + filterEventSourceItem : str, optional + Event source item filter. + filterTimeFrom : int, optional + Start time for filtering. + filterKeyword : str, optional + Keyword to filter logs. + doorIds : str, optional + Door IDs filter. + eventTypes : str, optional + Event types filter. + update : int, optional + Update flag. + + Returns + ------- + dict[str, object] or str + Result of the acknowledge operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3338,6 +6794,28 @@ def acknowledge_all_alarm_level_log(self, def modify_controller_logger_config(self, # TODO to check data: Any = None) -> dict[str, object] | str: + """ + Modify the logger configuration for a controller. + + Parameters + ---------- + data : Any, optional + Logger configuration data (see example in docstring). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + + Notes + ----- + Example data: + data = { + "log_evt": "11111111111111111111111111111111111111", + "id": 97, + "log_alarm": "00111111111111111111111111111111111111" + } + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3357,6 +6835,23 @@ def modify_controller_logger_config(self, def save_controller_settings(self, arrayJson: str = None) -> dict[str, object] | str: + """ + Save controller settings for Surveillance Station. + + Parameters + ---------- + arrayJson : str, optional + JSON string representing controller settings. Example: + [{"enable": true, "id": 97, "name": "ctrler1", "host": "10.13.12.173", "port": 80, + "model": "A1001", "username": "root", "password": "Q__Q-__-", "time_server": + "SurveillanceStation", "time_zone": "Fiji", "door": [{"id": 231, "name": "FrontDoor", + "enable_cam": true, "cam_ds_id": 0, "cam_id": 13}]}] + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3390,6 +6885,41 @@ def download_filtered_logs(self, eventTypes: str = None, # TODO to modify for download? update: int = None) -> dict[str, object] | str: + """ + Download filtered logs from Surveillance Station. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + filterType : int, optional + Type of filter to apply. + filterEventSource : int, optional + Event source filter. + filterSource : int, optional + Source filter. + filterEventSourceItem : str, optional + Event source item filter. + filterTimeFrom : int, optional + Start time for filtering. + filterTimeTo : int, optional + End time for filtering. + filterKeyword : str, optional + Keyword to filter logs. + doorIds : str, optional + Door IDs filter. + eventTypes : str, optional + Event types filter. + update : int, optional + Update flag. + + Returns + ------- + dict[str, object] or str + Downloaded log data or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3409,6 +6939,27 @@ def get_door_name_from_controller(self, userName: str = None, # TODO to check password: int = None) -> dict[str, object] | str: + """ + Retrieve door names from a specific controller. + + Parameters + ---------- + ctrlerId : int, optional + Controller ID. + ip : str, optional + Controller IP address. + port : int, optional + Controller port. + userName : str, optional + Username for authentication. + password : int, optional + Password for authentication (to check). + + Returns + ------- + dict[str, object] or str + Door names or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3428,6 +6979,27 @@ def test_connection_and_authentication(self, userName: str = None, # TODO to check password: int = None) -> dict[str, object] | str: + """ + Test connection and authentication to a controller. + + Parameters + ---------- + ctrlerId : int, optional + Controller ID. + ip : str, optional + Controller IP address. + port : int, optional + Controller port. + userName : str, optional + Username for authentication. + password : int, optional + Password for authentication (to check). + + Returns + ------- + dict[str, object] or str + Result of the test or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3447,6 +7019,27 @@ def enumerate_controller_list_info(self, blIncludeRecCnt: bool = None, # TODO to check blIncludeAuInfo: bool = None) -> dict[str, object] | str: + """ + Enumerate controller list information. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + update : int, optional + Update flag. + blIncludeRecCnt : bool, optional + Whether to include record count. + blIncludeAuInfo : bool, optional + Whether to include additional info (to check). + + Returns + ------- + dict[str, object] or str + Controller list information or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3461,6 +7054,19 @@ def enumerate_controller_list_info(self, def save_cardholder_setting(self, arrayJson: str = None) -> dict[str, object] | str: + """ + Save cardholder settings. + + Parameters + ---------- + arrayJson : str, optional + JSON string representing cardholder settings. + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3475,6 +7081,19 @@ def save_cardholder_setting(self, def enumerate_door_info(self, DoorIds: str = None) -> dict[str, object] | str: + """ + Enumerate door information. + + Parameters + ---------- + DoorIds : str, optional + Comma-separated list of door IDs. + + Returns + ------- + dict[str, object] or str + Door information or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3498,6 +7117,37 @@ def clear_logs_surveillance_station(self, doorIds: str = None, eventTypes: str = None, update: int = None) -> dict[str, object] | str: + """ + Clear logs in Surveillance Station with optional filters. + + Parameters + ---------- + filterType : int, optional + Type of filter to apply. + filterEventSource : Any, optional + Event source filter. + filterSource : int, optional + Source filter. + filterEventSourceItem : str, optional + Event source item filter. + filterTimeFrom : int, optional + Start time for filtering. + filterTimeTo : int, optional + End time for filtering. + filterKeyword : str, optional + Keyword to filter logs. + doorIds : str, optional + Door IDs filter. + eventTypes : str, optional + Event types filter. + update : int, optional + Update flag. + + Returns + ------- + dict[str, object] or str + Result of the clear operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3511,6 +7161,14 @@ def clear_logs_surveillance_station(self, return self.request_data(api_name, api_path, req_param) def list_all_user_privilege(self) -> dict[str, object] | str: + """ + List all user privileges in Surveillance Station. + + Returns + ------- + dict[str, object] or str + List of user privileges or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3527,6 +7185,21 @@ def manual_lock_operation(self, doorId: int = None, # TODO to check operation: int = None) -> dict[str, object] | str: + """ + Perform a manual lock or unlock operation on a door. + + Parameters + ---------- + doorId : int, optional + Door ID to operate on. + operation : int, optional + Operation code (to check). + + Returns + ------- + dict[str, object] or str + Result of the operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3541,6 +7214,19 @@ def manual_lock_operation(self, def save_user_door_priv_setting(self, arrayJson: str = None) -> dict[str, object] | str: + """ + Save user door privilege settings. + + Parameters + ---------- + arrayJson : str, optional + JSON string representing user door privilege settings. + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3569,6 +7255,47 @@ def list_all_logs(self, update: int = None, blIncludeRecCnt: bool = None, blIncludeAuInfo: bool = None) -> dict[str, object] | str: + """ + List all logs in Surveillance Station with optional filters. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + filterType : int, optional + Type of filter to apply. + filterEventSource : Any, optional + Event source filter. + filterSource : int, optional + Source filter. + filterEventSourceItem : str, optional + Event source item filter. + filterTimeFrom : int, optional + Start time for filtering. + filterTimeTo : int, optional + End time for filtering. + filterKeyword : str, optional + Keyword to filter logs. + timezoneOffset : int, optional + Timezone offset. + doorIds : str, optional + Door IDs filter. + eventTypes : str, optional + Event types filter. + update : int, optional + Update flag. + blIncludeRecCnt : bool, optional + Whether to include record count. + blIncludeAuInfo : bool, optional + Whether to include additional info. + + Returns + ------- + dict[str, object] or str + List of logs or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3582,6 +7309,19 @@ def list_all_logs(self, return self.request_data(api_name, api_path, req_param) def delete_selected_controller(self, ids: str = None) -> dict[str, object] | str: + """ + Delete selected controllers from Surveillance Station. + + Parameters + ---------- + ids : str, optional + Comma-separated string of controller IDs to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3596,6 +7336,19 @@ def delete_selected_controller(self, ids: str = None) -> dict[str, object] | str # TODO to check def retrieve_data_from_controller(self, ctrlerId: str = None) -> dict[str, object] | str: + """ + Retrieve data from a specific controller. + + Parameters + ---------- + ctrlerId : str, optional + ID of the controller to retrieve data from. + + Returns + ------- + dict[str, object] or str + Retrieved data or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3609,6 +7362,19 @@ def retrieve_data_from_controller(self, ctrlerId: str = None) -> dict[str, objec return self.request_data(api_name, api_path, req_param) def block_cardholder(self, arrayJson: str = None) -> dict[str, object] | str: + """ + Block cardholders in Surveillance Station. + + Parameters + ---------- + arrayJson : str, optional + JSON string representing cardholder(s) to block. + + Returns + ------- + dict[str, object] or str + Result of the block operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3623,6 +7389,14 @@ def block_cardholder(self, arrayJson: str = None) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_controller_count(self) -> dict[str, object] | str: + """ + Get the count of controllers by category. + + Returns + ------- + dict[str, object] or str + Controller count or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler' info = self.gen_list[api_name] api_path = info['path'] @@ -3632,6 +7406,14 @@ def get_controller_count(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def start_controller_search(self) -> dict[str, object] | str: + """ + Start searching for controllers. + + Returns + ------- + dict[str, object] or str + Result of the search operation or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -3639,13 +7421,28 @@ def start_controller_search(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) - def get_controller_search_result(self, - pid: int = None, - offset: int = None) -> dict[str, object] | str: + def get_controller_search_info(self, + pid: int = None, + offset: int = None) -> dict[str, object] | str: + """ + Get information about the current controller search. + + Parameters + ---------- + pid : int, optional + Process ID of the search. + offset : int, optional + Offset for paginated results. + + Returns + ------- + dict[str, object] or str + Search information or error details. + """ api_name = 'SYNO.SurveillanceStation.AxisAcsCtrler.Search' info = self.gen_list[api_name] api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'InfoGet'} + req_param = {'version': info['maxVersion'], 'method': 'GetInfo'} for key, val in locals().items(): if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: @@ -3657,6 +7454,19 @@ def get_controller_search_result(self, def enumerate_digital_output(self, # TODO to check camId: int = None) -> dict[str, object] | str: + """ + Enumerate digital output devices. + + Parameters + ---------- + camId : int, optional + Camera ID to filter digital outputs. + + Returns + ------- + dict[str, object] or str + List of digital outputs or error details. + """ api_name = 'SYNO.SurveillanceStation.DigitalOutput' info = self.gen_list[api_name] api_path = info['path'] @@ -3676,6 +7486,27 @@ def save_digital_output_parameters(self, normal_state: int = None, # TODO to check trigger_state: bool = None) -> dict[str, object] | str: + """ + Save parameters for a digital output device. + + Parameters + ---------- + camId : int, optional + Camera ID. + idx : int, optional + Index of the digital output. + keep_setting : bool, optional + Whether to keep the current setting. + normal_state : int, optional + Normal state value. + trigger_state : bool, optional + Trigger state value. + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.DigitalOutput' info = self.gen_list[api_name] api_path = info['path'] @@ -3697,6 +7528,31 @@ def long_polling_digital_output_status(self, trigger: bool = None, # TODO to check timeOut: int = None) -> dict[str, object] | str: + """ + Perform long polling to get the status of a digital output. + + Parameters + ---------- + camId : int, optional + Camera ID. + idx : int, optional + Index of the digital output. + keep : bool, optional + Whether to keep polling. + setNormalCap : bool, optional + Set normal capability. + normal : int, optional + Normal state value. + trigger : bool, optional + Trigger state value. + timeOut : int, optional + Timeout for polling. + + Returns + ------- + dict[str, object] or str + Status information or error details. + """ api_name = 'SYNO.SurveillanceStation.DigitalOutput' info = self.gen_list[api_name] api_path = info['path'] @@ -3713,6 +7569,21 @@ def trigger_external_event(self, eventId: int = None, # TODO to check eventName: str = None) -> dict[str, object] | str: + """ + Trigger an external event in Surveillance Station. + + Parameters + ---------- + eventId : int, optional + ID of the event to trigger. + eventName : str, optional + Name of the event to trigger. + + Returns + ------- + dict[str, object] or str + Result of the trigger operation or error details. + """ api_name = 'SYNO.SurveillanceStation.ExternalEvent' info = self.gen_list[api_name] api_path = info['path'] @@ -3731,6 +7602,25 @@ def get_list_io_modules(self, blFromList: bool = None, # TODO to check ownerDsId: int = None) -> dict[str, object] | str: + """ + Get a list of I/O modules. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + blFromList : bool, optional + Whether to get from list. + ownerDsId : int, optional + Owner device station ID. + + Returns + ------- + dict[str, object] or str + List of I/O modules or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3752,6 +7642,31 @@ def get_io_port_list(self, Vendor: str = None, # TODO to check Model: str = None) -> dict[str, object] | str: + """ + Get a list of I/O ports for a module. + + Parameters + ---------- + Id : int, optional + Module ID. + Port : int, optional + Port number. + IP : str, optional + IP address. + User : str, optional + Username. + Pass : str, optional + Password. + Vendor : str, optional + Vendor name. + Model : str, optional + Model name. + + Returns + ------- + dict[str, object] or str + List of I/O ports or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3766,6 +7681,14 @@ def get_io_port_list(self, # TODO to check def get_supported_list_io_modules(self) -> dict[str, object] | str: + """ + Get a list of supported I/O module vendor models. + + Returns + ------- + dict[str, object] or str + List of supported vendor models or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3790,6 +7713,45 @@ def save_setting_io_module(self, ntpEnable: bool = None, # TODO to check DIOdata: Any = None) -> dict[str, object] | str: + """ + Save or update the settings for an I/O module in Surveillance Station. + + Parameters + ---------- + name : str, optional + Name of the I/O module. + id : int, optional + ID of the I/O module. + ownerDsId : int, optional + Owner device station ID. + vendor : str, optional + Vendor name of the I/O module. + model : str, optional + Model name of the I/O module. + ip : str, optional + IP address of the I/O module. + port : int, optional + Port number for the I/O module. + userName : str, optional + Username for authentication. + enabled : bool, optional + Whether the I/O module is enabled. + status : int, optional + Status code of the I/O module. + timeServer : str, optional + Time server address. + passWord : str, optional + Password for authentication. + ntpEnable : bool, optional + Whether NTP is enabled. + DIOdata : Any, optional + Digital I/O data (structure to be checked). + + Returns + ------- + dict[str, object] or str + Result of the save operation or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3805,6 +7767,19 @@ def save_setting_io_module(self, def enable_io_modules(self, # TODO to check iomlist: str = None) -> dict[str, object] | str: + """ + Enable specified I/O modules. + + Parameters + ---------- + iomlist : str, optional + Comma-separated list of I/O module IDs to enable. + + Returns + ------- + dict[str, object] or str + Result of the enable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3820,6 +7795,19 @@ def enable_io_modules(self, def disable_io_modules(self, # TODO to check iomlist: str = None) -> dict[str, object] | str: + """ + Disable specified I/O modules. + + Parameters + ---------- + iomlist : str, optional + Comma-separated list of I/O module IDs to disable. + + Returns + ------- + dict[str, object] or str + Result of the disable operation or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3835,6 +7823,19 @@ def disable_io_modules(self, def delete_io_modules(self, # TODO to check iomlist: str = None) -> dict[str, object] | str: + """ + Delete specified I/O modules. + + Parameters + ---------- + iomlist : str, optional + Comma-separated list of I/O module IDs to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3855,6 +7856,29 @@ def test_connection_to_io_module(self, passWord: str = None, # TODO to check model: str = None) -> dict[str, object] | str: + """ + Test the connection to a specified I/O module. + + Parameters + ---------- + id : int, optional + ID of the I/O module. + port : str, optional + Port number for the I/O module. + ip : str, optional + IP address of the I/O module. + userName : str, optional + Username for authentication. + passWord : str, optional + Password for authentication. + model : str, optional + Model name of the I/O module. + + Returns + ------- + dict[str, object] or str + Result of the connection test or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3871,6 +7895,21 @@ def get_capability_io_module(self, vendor: str = None, # TODO to check model: str = None) -> dict[str, object] | str: + """ + Get the capability information for a specified I/O module. + + Parameters + ---------- + vendor : str, optional + Vendor name of the I/O module. + model : str, optional + Model name of the I/O module. + + Returns + ------- + dict[str, object] or str + Capability information or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3887,6 +7926,21 @@ def configure_io_port_setting(self, id: int = None, # TODO to check DIOdata: Any = None) -> dict[str, object] | str: + """ + Configure the port settings for a specified I/O module. + + Parameters + ---------- + id : int, optional + ID of the I/O module. + DIOdata : Any, optional + Digital I/O data for port configuration (structure to be checked). + + Returns + ------- + dict[str, object] or str + Result of the configuration or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3904,6 +7958,23 @@ def poll_trigger_state_io_module(self, list: Any = None, # TODO to check timeOut: int = None) -> dict[str, object] | str: + """ + Poll the trigger state of digital input (DI) ports for a specified I/O module. + + Parameters + ---------- + Id : int, optional + ID of the I/O module. + list : Any, optional + List of DI ports to poll (structure to be checked). + timeOut : int, optional + Timeout for polling operation. + + Returns + ------- + dict[str, object] or str + Polling result or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3923,6 +7994,27 @@ def poll_do_trigger_module(self, trigger: bool = None, # TODO to check timeOut: int = None) -> dict[str, object] | str: + """ + Poll the trigger state of digital output (DO) ports for a specified I/O module. + + Parameters + ---------- + id : int, optional + ID of the I/O module. + idx : int, optional + Index of the DO port. + normal : int, optional + Normal state value. + trigger : bool, optional + Trigger state. + timeOut : int, optional + Timeout for polling operation. + + Returns + ------- + dict[str, object] or str + Polling result or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3937,6 +8029,14 @@ def poll_do_trigger_module(self, # TODO to check def get_number_of_devices(self) -> dict[str, object] | str: + """ + Get the number of I/O devices for each device station. + + Returns + ------- + dict[str, object] or str + Number of devices or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3955,6 +8055,25 @@ def get_category_count_io_module(self, ownerDsId: int = None, # TODO to check blFromList: bool = None) -> dict[str, object] | str: + """ + Get the count of I/O modules by category. + + Parameters + ---------- + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + ownerDsId : int, optional + Owner device station ID. + blFromList : bool, optional + Whether to get count from a list (to be checked). + + Returns + ------- + dict[str, object] or str + Count by category or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule' info = self.gen_list[api_name] api_path = info['path'] @@ -3969,20 +8088,36 @@ def get_category_count_io_module(self, return self.request_data(api_name, api_path, req_param) def start_search_io_module(self) -> dict[str, object] | str: + """ + Start searching for I/O modules. + + Returns + ------- + dict[str, object] or str + Result of the search operation or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule.Search' info = self.gen_list[api_name] api_path = info['path'] req_param = {'version': info['maxVersion'], 'method': 'Start'} - for key, val in locals().items(): - if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: - if val is not None: - req_param[str(key)] = val - return self.request_data(api_name, api_path, req_param) def get_search_io_module_info(self, pid: int = None) -> dict[str, object] | str: + """ + Get information about the current I/O module search. + + Parameters + ---------- + pid : int, optional + Process ID of the search. + + Returns + ------- + dict[str, object] or str + Search information or error details. + """ api_name = 'SYNO.SurveillanceStation.IOModule.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -3998,6 +8133,19 @@ def get_search_io_module_info(self, def get_current_camera_status(self, # TODO not working id_list: str = None) -> dict[str, object] | str: + """ + Get the current status of specified cameras. + + Parameters + ---------- + id_list : str, optional + Comma-separated list of camera IDs. + + Returns + ------- + dict[str, object] or str + Camera status information or error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Status' info = self.gen_list[api_name] api_path = info['path'] @@ -4013,6 +8161,19 @@ def get_current_camera_status(self, def enum_preset_camera_list(self, # TODO not working cameraId: Any = None) -> dict[str, object] | str: + """ + Enumerate the list of presets for a specified camera. + + Parameters + ---------- + cameraId : Any, optional + ID of the camera. + + Returns + ------- + dict[str, object] or str + List of camera presets or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Preset' info = self.gen_list[api_name] api_path = info['path'] @@ -4028,6 +8189,19 @@ def enum_preset_camera_list(self, def get_preset_camera_capability(self, # TODO not working cameraId: int = None) -> dict[str, object] | str: + """ + Get the capability information for camera presets. + + Parameters + ---------- + cameraId : int, optional + ID of the camera. + + Returns + ------- + dict[str, object] or str + Preset capability information or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Preset' info = self.gen_list[api_name] api_path = info['path'] @@ -4046,6 +8220,25 @@ def record_current_camera_position(self, speed: int = None, # TODO not working name: str = None) -> dict[str, object] | str: + """ + Record the current position of a camera as a preset. + + Parameters + ---------- + cameraId : int, optional + ID of the camera. + position : int, optional + Preset position index. + speed : int, optional + Speed for moving to the preset. + name : str, optional + Name for the preset. + + Returns + ------- + dict[str, object] or str + Result of the record operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Preset' info = self.gen_list[api_name] api_path = info['path'] @@ -4062,6 +8255,21 @@ def delete_list_preset_camera(self, cameraId: Any = None, # TODO not working position: str = None) -> dict[str, object] | str: + """ + Delete specified presets from a camera. + + Parameters + ---------- + cameraId : Any, optional + ID of the camera. + position : str, optional + Preset position(s) to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Preset' info = self.gen_list[api_name] api_path = info['path'] @@ -4080,6 +8288,25 @@ def go_specific_preset_by_given_speed(self, speed: int = None, # TODO not working type: int = None) -> dict[str, object] | str: + """ + Move a camera to a specific preset position at a given speed. + + Parameters + ---------- + cameraId : Any, optional + ID of the camera. + position : int, optional + Preset position index. + speed : int, optional + Speed for moving to the preset. + type : int, optional + Type of preset move (to be checked). + + Returns + ------- + dict[str, object] or str + Result of the move operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Preset' info = self.gen_list[api_name] api_path = info['path'] @@ -4096,6 +8323,21 @@ def set_current_camera_position(self, cameraId: Any = None, # TODO not working bindPosition: int = None) -> dict[str, object] | str: + """ + Set the current position of a camera as the home position. + + Parameters + ---------- + cameraId : Any, optional + ID of the camera. + bindPosition : int, optional + Position to bind as home. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Preset' info = self.gen_list[api_name] api_path = info['path'] @@ -4110,6 +8352,19 @@ def set_current_camera_position(self, def enum_patrol_list(self, cam: Any = None) -> dict[str, object] | str: + """ + Enumerate the list of patrols for a specified camera. + + Parameters + ---------- + cam : Any, optional + Camera identifier. + + Returns + ------- + dict[str, object] or str + List of patrols or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4124,6 +8379,19 @@ def enum_patrol_list(self, def enum_patrol_name_list(self, camId: Any = None) -> dict[str, object] | str: + """ + Enumerate the list of patrol names for a specified camera. + + Parameters + ---------- + camId : Any, optional + Camera identifier. + + Returns + ------- + dict[str, object] or str + List of patrol names or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4139,6 +8407,19 @@ def enum_patrol_name_list(self, def load_patrol_detail(self, # TODO not working id: int = None) -> dict[str, object] | str: + """ + Load the details of a specific patrol. + + Parameters + ---------- + id : int, optional + Patrol ID. + + Returns + ------- + dict[str, object] or str + Patrol details or error information. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4159,6 +8440,29 @@ def add_or_modify_patrol(self, name: str = None, # TODO not working presetList: Any = None) -> dict[str, object] | str: + """ + Add or modify a patrol for a camera. + + Parameters + ---------- + camId : Any, optional + Camera identifier. + id : int, optional + Patrol ID. + stayTime : int, optional + Stay time at each preset. + speed : int, optional + Patrol speed. + name : str, optional + Name of the patrol. + presetList : Any, optional + List of presets for the patrol (structure to be checked). + + Returns + ------- + dict[str, object] or str + Result of the add/modify operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4175,6 +8479,21 @@ def delete_specific_patrol(self, camId: Any = None, # TODO not working patrolId: str = None) -> dict[str, object] | str: + """ + Delete a specific patrol from a camera. + + Parameters + ---------- + camId : Any, optional + Camera identifier. + patrolId : str, optional + Patrol ID to delete. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4190,6 +8509,21 @@ def delete_specific_patrol(self, def run_patrol(self, camId: Any = None, id: int = None) -> dict[str, object] | str: # TODO not working + """ + Run a specified patrol on a camera. + + Parameters + ---------- + camId : Any, optional + Camera identifier. + id : int, optional + Patrol ID. + + Returns + ------- + dict[str, object] or str + Result of the run operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4204,6 +8538,19 @@ def run_patrol(self, def stop_patrol(self, camId: Any = None) -> dict[str, object] | str: # TODO not working + """ + Stop the currently running patrol on a camera. + + Parameters + ---------- + camId : Any, optional + Camera identifier. + + Returns + ------- + dict[str, object] or str + Result of the stop operation or error details. + """ api_name = 'SYNO.SurveillanceStation.PTZ.Patrol' info = self.gen_list[api_name] api_path = info['path'] @@ -4217,6 +8564,14 @@ def stop_patrol(self, return self.request_data(api_name, api_path, req_param) def start_camera_search_process(self) -> dict[str, object] | str: + """ + Start searching for cameras. + + Returns + ------- + dict[str, object] or str + Result of the search operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -4227,6 +8582,21 @@ def start_camera_search_process(self) -> dict[str, object] | str: def get_camera_search_info(self, pid: int = None, offset: int = None) -> dict[str, object] | str: + """ + Get information about the current camera search. + + Parameters + ---------- + pid : int, optional + Process ID of the search. + offset : int, optional + Offset for pagination. + + Returns + ------- + dict[str, object] or str + Search information or error details. + """ api_name = 'SYNO.SurveillanceStation.Camera.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -4241,6 +8611,19 @@ def get_camera_search_info(self, def toggle_home_mode(self, on: bool = None) -> dict[str, object] | str: + """ + Toggle the Home Mode in Surveillance Station. + + Parameters + ---------- + on : bool, optional + Whether to enable (True) or disable (False) Home Mode. + + Returns + ------- + dict[str, object] or str + Result of the toggle operation or error details. + """ api_name = 'SYNO.SurveillanceStation.HomeMode' info = self.gen_list[api_name] api_path = info['path'] @@ -4255,6 +8638,19 @@ def toggle_home_mode(self, def get_home_mode_settings(self, need_mobiles: bool = None) -> dict[str, object] | str: + """ + Get the current Home Mode settings. + + Parameters + ---------- + need_mobiles : bool, optional + Whether to include mobile device information. + + Returns + ------- + dict[str, object] or str + Home Mode settings or error details. + """ api_name = 'SYNO.SurveillanceStation.HomeMode' info = self.gen_list[api_name] api_path = info['path'] @@ -4275,6 +8671,29 @@ def get_transaction_list(self, start: int = None, # TODO not working limit: int = None) -> dict[str, object] | str: + """ + Get a list of device transactions with optional filters. + + Parameters + ---------- + filterIds : str, optional + Comma-separated list of transaction IDs to filter. + filterDsIds : str, optional + Comma-separated list of device station IDs to filter. + filterEnable : bool, optional + Filter by enabled status. + filterStatus : int, optional + Filter by status code. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + + Returns + ------- + dict[str, object] or str + List of transactions or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Device' info = self.gen_list[api_name] api_path = info['path'] @@ -4299,6 +8718,37 @@ def get_all_transaction_list(self, start: int = None, # TODO not working limit: int = None) -> dict[str, object] | str: + """ + Get a list of all transactions with optional filters. + + Parameters + ---------- + filterIds : str, optional + Comma-separated list of transaction IDs to filter. + dsId : int, optional + Device station ID. + filterTimeFrom : Any, optional + Start time for filtering. + filterStatus : int, optional + Filter by status code. + filterLock : bool, optional + Filter by lock status. + filterTimeTo : Any, optional + End time for filtering. + filterTimeRangeIntersect : bool, optional + Whether to intersect time ranges. + filterKeyword : str, optional + Keyword for filtering. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + + Returns + ------- + dict[str, object] or str + List of transactions or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4322,6 +8772,37 @@ def lock_history_records(self, filterKeyword: str = None, start: int = None, limit: int = None) -> dict[str, object] | str: + """ + Lock specified history records. + + Parameters + ---------- + filterIds : str, optional + Comma-separated list of record IDs to lock. + dsId : int, optional + Device station ID. + filterStatus : int, optional + Filter by status code. + filterLock : bool, optional + Filter by lock status. + filterTimeFrom : Any, optional + Start time for filtering. + filterTimeTo : Any, optional + End time for filtering. + filterTimeRangeIntersect : bool, optional + Whether to intersect time ranges. + filterKeyword : str, optional + Keyword for filtering. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + + Returns + ------- + dict[str, object] or str + Result of the lock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4345,6 +8826,37 @@ def unlock_history_records(self, filterKeyword: str = None, start: int = None, limit: int = None) -> dict[str, object] | str: + """ + Unlock specified history records. + + Parameters + ---------- + filterIds : str, optional + Comma-separated list of record IDs to unlock. + dsId : int, optional + Device station ID. + filterStatus : int, optional + Filter by status code. + filterLock : bool, optional + Filter by lock status. + filterTimeFrom : Any, optional + Start time for filtering. + filterTimeTo : Any, optional + End time for filtering. + filterTimeRangeIntersect : bool, optional + Whether to intersect time ranges. + filterKeyword : str, optional + Keyword for filtering. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + + Returns + ------- + dict[str, object] or str + Result of the unlock operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4368,6 +8880,37 @@ def delete_history_records(self, filterKeyword: str = None, start: int = None, limit: int = None) -> dict[str, object] | str: + """ + Delete specified history records. + + Parameters + ---------- + filterIds : str, optional + Comma-separated list of record IDs to delete. + dsId : int, optional + Device station ID. + filterStatus : int, optional + Filter by status code. + filterLock : bool, optional + Filter by lock status. + filterTimeFrom : Any, optional + Start time for filtering. + filterTimeTo : Any, optional + End time for filtering. + filterTimeRangeIntersect : bool, optional + Whether to intersect time ranges. + filterKeyword : str, optional + Keyword for filtering. + start : int, optional + Start index for pagination. + limit : int, optional + Maximum number of results to return. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4385,6 +8928,23 @@ def start_session_with_specified_session_id(self, session_id: str = None, # TODO not working timeout: int = None) -> dict[str, object] | str: + """ + Start a session with a specified session ID. + + Parameters + ---------- + device_name : str, optional + Name of the device. + session_id : str, optional + Session ID to start. + timeout : int, optional + Timeout for the session. + + Returns + ------- + dict[str, object] or str + Result of the start operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4401,6 +8961,21 @@ def complete_session_with_specified_id(self, device_name: str = None, # TODO not working session_id: str = None) -> dict[str, object] | str: + """ + Complete a session with a specified session ID. + + Parameters + ---------- + device_name : str, optional + Name of the device. + session_id : str, optional + Session ID to complete. + + Returns + ------- + dict[str, object] or str + Result of the complete operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4417,6 +8992,21 @@ def cancel_session_with_specified_session_id(self, device_name: str = None, # TODO not working session_id: str = None) -> dict[str, object] | str: + """ + Cancel a session with a specified session ID. + + Parameters + ---------- + device_name : str, optional + Name of the device. + session_id : str, optional + Session ID to cancel. + + Returns + ------- + dict[str, object] or str + Result of the cancel operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4434,6 +9024,23 @@ def carry_data_into_session_id(self, session_id: str = None, # TODO not working content: str = None) -> dict[str, object] | str: + """ + Append data to a session with a specified session ID. + + Parameters + ---------- + device_name : str, optional + Name of the device. + session_id : str, optional + Session ID to append data to. + content : str, optional + Data content to append. + + Returns + ------- + dict[str, object] or str + Result of the append operation or error details. + """ api_name = 'SYNO.SurveillanceStation.Transactions.Transaction' info = self.gen_list[api_name] api_path = info['path'] @@ -4471,6 +9078,63 @@ def add_edit_active_vault_task(self, storagePath: str = None, # TODO to check type: int = None) -> dict[str, object] | str: + """ + Add or edit an active vault task for archiving. + + Parameters + ---------- + blCustomFolder : bool, optional + Whether to use a custom folder for storage. + blLimitBySize : bool, optional + Whether to limit the archive by size. + blRotateFile : bool, optional + Whether to enable file rotation. + blSrcRecNoOverlap : bool, optional + Whether to avoid overlapping source recordings. + blUseRecDet : bool, optional + Whether to use recording detection. + camId : Any, optional + Camera ID. + camInfo : Any, optional + Camera information. + dayLimit : int, optional + Day limit for the archive. + didCode : str, optional + Device code. + dsSerial : str, optional + Device serial number. + execTime : Any, optional + Execution time. + hostname : str, optional + Hostname of the source server. + id : int, optional + Task ID (for editing). + name : str, optional + Name of the task. + passwd : str, optional + Password for authentication. + port : str, optional + Port number. + recEndTm : Any, optional + Recording end time. + recMode : str, optional + Recording mode. + recSchedule : str, optional + Recording schedule. + recStartTm : Any, optional + Recording start time. + schedule : str, optional + Task schedule. + storagePath : str, optional + Path for storage. + type : int, optional + Type of the task. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4493,6 +9157,33 @@ def login_source_server_get_info(self, didCode: str = None, # TODO not working srcDsId: int = None) -> dict[str, object] | str: + """ + Log in to the source server and retrieve information. + + Parameters + ---------- + port : str, optional + Port number of the source server. + hostname : str, optional + Hostname of the source server. + protocol : bool, optional + Protocol to use (e.g., HTTPS). + username : str, optional + Username for authentication. + passwd : str, optional + Password for authentication. + archId : int, optional + Archive ID. + didCode : str, optional + Device code. + srcDsId : int, optional + Source device ID (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4508,6 +9199,21 @@ def login_source_server_get_info(self, def delete_archive_vault_task(self, id: int = None, keepRec: bool = None) -> dict[str, object] | str: + """ + Delete an archive vault task. + + Parameters + ---------- + id : int, optional + Task ID to delete. + keepRec : bool, optional + Whether to keep the recordings. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4521,6 +9227,14 @@ def delete_archive_vault_task(self, return self.request_data(api_name, api_path, req_param) def list_exist_archive_vault(self) -> dict[str, object] | str: + """ + List all existing archive vault tasks. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4536,6 +9250,19 @@ def list_exist_archive_vault(self) -> dict[str, object] | str: def enable_archive_vault_task(self, # TODO not working id: int = None) -> dict[str, object] | str: + """ + Enable an archive vault task. + + Parameters + ---------- + id : int, optional + Task ID to enable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4550,6 +9277,19 @@ def enable_archive_vault_task(self, def disable_archive_vault_task(self, id: int = None) -> dict[str, object] | str: + """ + Disable an archive vault task. + + Parameters + ---------- + id : int, optional + Task ID to disable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4566,6 +9306,21 @@ def disable_archive_vault_batchedit_task(self, taskIds: str = None, # TODO not working attrs: Any = None) -> dict[str, object] | str: + """ + Batch edit (disable) archive vault tasks. + + Parameters + ---------- + taskIds : str, optional + Comma-separated list of task IDs. + attrs : Any, optional + Additional attributes for batch edit (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4581,6 +9336,19 @@ def disable_archive_vault_batchedit_task(self, def get_batch_edit_progress(self, # TODO not working pid: int = None) -> dict[str, object] | str: + """ + Get the progress of a batch edit operation. + + Parameters + ---------- + pid : int, optional + Process ID of the batch edit operation (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4597,6 +9365,19 @@ def get_batch_edit_progress(self, def get_batchedit_proress_info(self, # TODO not working pid: int = None) -> dict[str, object] | str: + """ + Get detailed information about batch edit progress. + + Parameters + ---------- + pid : int, optional + Process ID of the batch edit operation (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4612,6 +9393,19 @@ def get_batchedit_proress_info(self, def clean_batchedit_progress_data(self, pid: int = None) -> dict[str, object] | str: + """ + Clean up batch edit progress data. + + Parameters + ---------- + pid : int, optional + Process ID of the batch edit operation. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Archiving.Pull' info = self.gen_list[api_name] api_path = info['path'] @@ -4626,6 +9420,14 @@ def clean_batchedit_progress_data(self, return self.request_data(api_name, api_path, req_param) def get_youtube_live_broadcast_setting(self) -> dict[str, object] | str: + """ + Get the current YouTube Live broadcast settings. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.YoutubeLive' info = self.gen_list[api_name] api_path = info['path'] @@ -4639,6 +9441,27 @@ def set_youtube_live_broadcast_info(self, cam_id: int = None, stream_profile: int = None, live_on: bool = None) -> dict[str, object] | str: + """ + Set YouTube Live broadcast information. + + Parameters + ---------- + rtmp_path : str, optional + RTMP path for the broadcast. + key : str, optional + Stream key. + cam_id : int, optional + Camera ID. + stream_profile : int, optional + Stream profile. + live_on : bool, optional + Whether to enable live broadcast. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.YoutubeLive' info = self.gen_list[api_name] api_path = info['path'] @@ -4652,6 +9475,14 @@ def set_youtube_live_broadcast_info(self, return self.request_data(api_name, api_path, req_param) def close_youtube_live_broadcast(self) -> dict[str, object] | str: + """ + Close the current YouTube Live broadcast. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.YoutubeLive' info = self.gen_list[api_name] api_path = info['path'] @@ -4661,6 +9492,14 @@ def close_youtube_live_broadcast(self) -> dict[str, object] | str: # TODO not working def get_deep_video_analytic(self) -> dict[str, object] | str: + """ + Get the list of deep video analytic tasks. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA' info = self.gen_list[api_name] api_path = info['path'] @@ -4702,6 +9541,81 @@ def create_edit_DVA_task(self, people_hint_pos: str = None, # TODO not working blEditMode: bool = None) -> dict[str, object] | str: + """ + Create or edit a Deep Video Analytics (DVA) task. + + Parameters + ---------- + analyze_type : int, optional + Type of analysis to perform. + actFromHost : bool, optional + Whether the action is triggered from the host. + name : str, optional + Name of the DVA task. + camera_id : int, optional + ID of the camera associated with the task. + enable : bool, optional + Whether to enable the task. + enable_recording : bool, optional + Whether to enable recording for the task. + pre_rec_time : int, optional + Pre-recording time in seconds. + post_rec_time : int, optional + Post-recording time in seconds. + event_integration : int, optional + Event integration setting. + region_type : int, optional + Type of detection region. + det_region_cnt : int, optional + Number of detection regions. + det_region : int, optional + Detection region configuration. + people_mode : int, optional + People counting mode. + reset_cnt_frequency : int, optional + Frequency for resetting the counter. + reset_weekday : int, optional + Weekday for counter reset. + reset_date : int, optional + Date for counter reset. + reset_time_minute : int, optional + Minute for counter reset. + reset_time_hour : int, optional + Hour for counter reset. + fence_dir_flag : int, optional + Fence direction flag. + people_display_pos : int, optional + Display position for people counting. + stream_profile : int, optional + Stream profile to use. + people_enable_stay_max : bool, optional + Whether to enable maximum stay for people. + intrusion_detect_target : int, optional + Target for intrusion detection. + min_obj_size : Any, optional + Minimum object size for detection. + min_obj_size_option : int, optional + Option for minimum object size. + enable_min_duration : int, optional + Enable minimum duration for detection. + people_display_info : int, optional + Display information for people counting. + people_enter : int, optional + Number of people entering. + people_stay_max : int, optional + Maximum number of people staying. + people_region : str, optional + Region for people counting. + people_hint_pos : str, optional + Hint position for people counting. + blEditMode : bool, optional + Edit mode flag (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA' info = self.gen_list[api_name] api_path = info['path'] @@ -4716,6 +9630,19 @@ def create_edit_DVA_task(self, def delete_dva_task(self, ids: str = None) -> dict[str, object] | str: # TODO not working + """ + Delete a Deep Video Analytics (DVA) task. + + Parameters + ---------- + ids : str, optional + Comma-separated list of DVA task IDs to delete. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA' info = self.gen_list[api_name] api_path = info['path'] @@ -4730,6 +9657,19 @@ def delete_dva_task(self, def enable_dva_task(self, ids: str = None) -> dict[str, object] | str: # TODO not working + """ + Enable one or more Deep Video Analytics (DVA) tasks. + + Parameters + ---------- + ids : str, optional + Comma-separated list of DVA task IDs to enable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA' info = self.gen_list[api_name] api_path = info['path'] @@ -4745,6 +9685,19 @@ def enable_dva_task(self, def disable_dva_task(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Disable one or more Deep Video Analytics (DVA) tasks. + + Parameters + ---------- + ids : str, optional + Comma-separated list of DVA task IDs to disable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA' info = self.gen_list[api_name] api_path = info['path'] @@ -4760,6 +9713,19 @@ def disable_dva_task(self, def reset_counter_people_counting_task(self, # TODO not working taskId: str = None) -> dict[str, object] | str: + """ + Reset the people counting counter for a specific DVA task. + + Parameters + ---------- + taskId : str, optional + ID of the people counting task to reset. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA' info = self.gen_list[api_name] api_path = info['path'] @@ -4779,6 +9745,25 @@ def get_people_enter_leave_count(self, timeEnd: str = None, timezone: int = None, ) -> dict[str, object] | str: # TODO not working + """ + Get the count of people entering and leaving for specified DVA tasks. + + Parameters + ---------- + ids : str, optional + Comma-separated list of DVA task IDs. + timeStart : str, optional + Start time for the count (ISO format or timestamp). + timeEnd : str, optional + End time for the count (ISO format or timestamp). + timezone : int, optional + Timezone offset. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Report' info = self.gen_list[api_name] api_path = info['path'] @@ -4799,6 +9784,29 @@ def get_people_count_of_day(self, timestamp: int = None, # TODO not working blOccupancy: int = None) -> dict[str, object] | str: + """ + Get the people count report for a specific day. + + Parameters + ---------- + ids : str, optional + Comma-separated list of DVA task IDs. + interval : int, optional + Interval for the report. + intervalUnit : int, optional + Unit for the interval. + timezone : int, optional + Timezone offset. + timestamp : int, optional + Timestamp for the report. + blOccupancy : int, optional + Occupancy flag (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Report' info = self.gen_list[api_name] api_path = info['path'] @@ -4815,6 +9823,21 @@ def list_people_counting_task(self, taskList: str = None, # TODO not working limit: int = None) -> dict[str, object] | str: + """ + List people counting tasks. + + Parameters + ---------- + taskList : str, optional + Comma-separated list of task IDs to list. + limit : int, optional + Limit the number of tasks returned (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -4831,6 +9854,21 @@ def delete_recording_file_of_detection(self, slaveDsParam: str = None, # TODO not working deleteMethod: int = None) -> dict[str, object] | str: + """ + Delete recording files associated with detection events. + + Parameters + ---------- + slaveDsParam : str, optional + Parameters for the slave device. + deleteMethod : int, optional + Method for deletion (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -4848,6 +9886,23 @@ def get_info_of_task_and_frame(self, taskId: int = None, # TODO not working blAlertEvt: bool = None) -> dict[str, object] | str: + """ + Get analytic result information for a specific task and frame. + + Parameters + ---------- + eventId : int, optional + Event ID to query. + taskId : int, optional + Task ID to query. + blAlertEvt : bool, optional + Alert event flag (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -4865,6 +9920,21 @@ def lock_recording_file_of_detection(self, dsId: int = None, # TODO not working idList: int = None) -> dict[str, object] | str: + """ + Lock recording files associated with detection events. + + Parameters + ---------- + dsId : int, optional + Device server ID. + idList : int, optional + List of recording file IDs to lock (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -4881,6 +9951,21 @@ def unlock_recording_file_of_detection(self, dsId: int = None, # TODO not working idList: str = None) -> dict[str, object] | str: + """ + Unlock recording files associated with detection events. + + Parameters + ---------- + dsId : int, optional + Device server ID. + idList : str, optional + List of recording file IDs to unlock (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.Recording' info = self.gen_list[api_name] api_path = info['path'] @@ -4895,6 +9980,14 @@ def unlock_recording_file_of_detection(self, # TODO not working def get_info_people_counting_task(self) -> dict[str, object] | str: + """ + Get information about people counting tasks. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -4920,6 +10013,39 @@ def create_people_counting_task(self, resert_tome_hour: int = None, # TODO not working resert_tome_minute: int = None) -> dict[str, object] | str: + """ + Create a new people counting task. + + Parameters + ---------- + enable : bool, optional + Whether to enable the task. + task_ids : str, optional + Comma-separated list of task IDs. + owner_ds_id : int, optional + Owner device server ID. + name : str, optional + Name of the task. + people_display_info : str, optional + Display information for people counting. + people_enable_stay_max : int, optional + Enable maximum stay for people. + reset_cnt_frequency : int, optional + Frequency for resetting the counter. + resert_date : int, optional + Date for counter reset. + resert_weekday : int, optional + Weekday for counter reset. + resert_tome_hour : int, optional + Hour for counter reset. + resert_tome_minute : int, optional + Minute for counter reset (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -4945,6 +10071,39 @@ def modify_setting_of_people_counting_task(self, resert_tome_hour: int = None, # TODO not working resert_tome_minute: int = None) -> dict[str, object] | str: + """ + Modify the settings of an existing people counting task. + + Parameters + ---------- + enable : bool, optional + Whether to enable the task. + id : int, optional + ID of the task to modify. + task_ids : str, optional + Comma-separated list of task IDs. + name : str, optional + Name of the task. + people_display_info : int, optional + Display information for people counting. + people_enable_max : int, optional + Enable maximum stay for people. + reset_cnt_frequency : int, optional + Frequency for resetting the counter. + resert_date : int, optional + Date for counter reset. + resert_weekday : int, optional + Weekday for counter reset. + resert_tome_hour : int, optional + Hour for counter reset. + resert_tome_minute : int, optional + Minute for counter reset (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -4960,6 +10119,19 @@ def modify_setting_of_people_counting_task(self, def delete_task_group(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Delete a people counting task group. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task group IDs to delete. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -4975,6 +10147,19 @@ def delete_task_group(self, def start_count_people_task_in_groups(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Enable people counting tasks in specified groups. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task group IDs to enable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -4990,6 +10175,19 @@ def start_count_people_task_in_groups(self, def stop_count_people_task_in_groups(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Disable people counting tasks in specified groups. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task group IDs to disable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -5005,6 +10203,19 @@ def stop_count_people_task_in_groups(self, def get_number_counting_task_group(self, # TODO not working id: int = None) -> dict[str, object] | str: + """ + Get the people count for a specific task group. + + Parameters + ---------- + id : int, optional + ID of the task group. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -5020,6 +10231,19 @@ def get_number_counting_task_group(self, def lock_recording_file_result(self, # TODO not working id: int = None) -> dict[str, object] | str: + """ + Reset the people count for a specific IVA task group. + + Parameters + ---------- + id : int, optional + ID of the IVA task group. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.IVA.TaskGroup' info = self.gen_list[api_name] api_path = info['path'] @@ -5038,6 +10262,23 @@ def get_face_list_task(self, ownerDsId: int = None, blOnlyEnableDs: bool = None, ) -> dict[str, object] | str: # TODO not working + """ + Retrieve the list of face detection tasks. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task IDs to filter. + ownerDsId : int, optional + ID of the owner DiskStation. + blOnlyEnableDs : bool, optional + Whether to include only enabled DiskStations. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5084,6 +10325,81 @@ def create_or_edit_task(self, scheduleOn: bool = None, # TODO not working ignore_bad_quality: bool = None) -> dict[str, object] | str: + """ + Create or edit a face detection task. + + Parameters + ---------- + id : int, optional + Task ID. + id_on_rec_server : int, optional + Task ID on the recording server. + camera_id : int, optional + Camera ID. + camera_id_on_rec : int, optional + Camera ID on the recording server. + owner_ds_id : int, optional + Owner DiskStation ID. + enable : bool, optional + Whether to enable the task. + blEditMode : bool, optional + Edit mode flag. + stream_profile : int, optional + Stream profile index. + name : str, optional + Name of the task. + similarity : float, optional + Similarity threshold for face recognition. + allowed_color : int, optional + Color code for allowed faces. + allowed_list : Any, optional + List of allowed faces. + blocked_color : int, optional + Color code for blocked faces. + blocked_list : Any, optional + List of blocked faces. + vip_color : int, optional + Color code for VIP faces. + vip_list : Any, optional + List of VIP faces. + recognized_color : int, optional + Color code for recognized faces. + unrecognized_color : int, optional + Color code for unrecognized faces. + deleted : bool, optional + Whether the task is deleted. + det_region : str, optional + Detection region. + det_region_cnt : int, optional + Number of detection regions. + region_type : int, optional + Type of region. + display_info : int, optional + Display information. + display_type : int, optional + Display type. + frame_display_info : int, optional + Frame display information. + enable_min_ogj_size : bool, optional + Enable minimum object size. + min_ogj_size : float, optional + Minimum object size. + post_rec_time : int, optional + Post-recording time in seconds. + pre_rec_time : int, optional + Pre-recording time in seconds. + schedule : str, optional + Task schedule. + scheduleOn : bool, optional + Whether the schedule is enabled. + ignore_bad_quality : bool, optional + Ignore bad quality flag (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5100,6 +10416,21 @@ def delete_face_task(self, ids: str = None, # TODO not working keepRecording: bool = None) -> dict[str, object] | str: + """ + Delete one or more face detection tasks. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task IDs to delete. + keepRecording : bool, optional + Whether to keep the associated recordings (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5115,6 +10446,19 @@ def delete_face_task(self, def enable_task_to_start_detection_recording(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Enable face detection tasks to start detection and recording. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task IDs to enable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5130,6 +10474,19 @@ def enable_task_to_start_detection_recording(self, def disable_task_to_stop_detection_recording(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Disable face detection tasks to stop detection and recording. + + Parameters + ---------- + ids : str, optional + Comma-separated list of task IDs to disable. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5145,6 +10502,19 @@ def disable_task_to_stop_detection_recording(self, def list_task_with_privilege_to_watch(self, # TODO not working ids: int = None) -> dict[str, object] | str: + """ + List face detection tasks with privilege to watch. + + Parameters + ---------- + ids : int, optional + Task group ID to filter. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5163,6 +10533,23 @@ def create_face_group(self, description: str = None, # TODO not working update_registered_face: Any = None) -> dict[str, object] | str: + """ + Create a new face group. + + Parameters + ---------- + name : str, optional + Name of the face group. + description : str, optional + Description of the face group. + update_registered_face : Any, optional + Registered face update information (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5179,6 +10566,19 @@ def create_face_group(self, def disable_face_grooup(self, # TODO not working ids: Any = None) -> dict[str, object] | str: + """ + Delete (disable) one or more face groups. + + Parameters + ---------- + ids : Any, optional + IDs of the face groups to delete (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5197,6 +10597,25 @@ def edit_face_group(self, description: str = None, update_registered_face: Any = None, id: int = None) -> dict[str, object] | str: # TODO not working + """ + Edit an existing face group. + + Parameters + ---------- + name : str, optional + Name of the face group. + description : str, optional + Description of the face group. + update_registered_face : Any, optional + Registered face update information. + id : int, optional + ID of the face group to edit. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5213,6 +10632,21 @@ def get_face_group_list(self, id_only: bool = None, # TODO not working filter: Any = None) -> dict[str, object] | str: + """ + Retrieve the list of face groups. + + Parameters + ---------- + id_only : bool, optional + Whether to return only IDs. + filter : Any, optional + Filter criteria (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5228,6 +10662,19 @@ def get_face_group_list(self, def count_face_groups(self, # TODO not working filter: Any = None) -> dict[str, object] | str: + """ + Count the number of face groups. + + Parameters + ---------- + filter : Any, optional + Filter criteria (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5244,6 +10691,21 @@ def detect_faces_image(self, image_data: str = None, # TODO not working image_size: int = None) -> dict[str, object] | str: + """ + Detect faces in an image. + + Parameters + ---------- + image_data : str, optional + Base64-encoded image data. + image_size : int, optional + Size of the image (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5269,6 +10731,37 @@ def create_registered_face(self, update_unrecognized_captured_face: bool = None, # TODO not working append_image_data: bool = None) -> dict[str, object] | str: + """ + Create a new registered face. + + Parameters + ---------- + account : str, optional + Account associated with the face. + name : str, optional + Name of the person. + description : str, optional + Description of the face. + image_data : str, optional + Base64-encoded image data. + image_size : int, optional + Size of the image. + face : Any, optional + Face data. + update_face_group : Any, optional + Face group update information. + captured_face_id : int, optional + ID of the captured face. + update_unrecognized_captured_face : bool, optional + Whether to update unrecognized captured face. + append_image_data : bool, optional + Append image data flag (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5285,6 +10778,19 @@ def create_registered_face(self, def delete_registered_face(self, # TODO not working ids: Any = None) -> dict[str, object] | str: + """ + Delete one or more registered faces. + + Parameters + ---------- + ids : Any, optional + IDs of the registered faces to delete (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5311,6 +10817,39 @@ def edit_registered_face(self, update_unrecognized_captured_face: bool = None, append_image_data: bool = None, ) -> dict[str, object] | str: # TODO not working + """ + Edit an existing registered face. + + Parameters + ---------- + id : int, optional + ID of the registered face. + account : str, optional + Account associated with the face. + name : str, optional + Name of the person. + description : str, optional + Description of the face. + image_data : str, optional + Base64-encoded image data. + image_size : int, optional + Size of the image. + face : Any, optional + Face data. + update_face_group : Any, optional + Face group update information. + captured_face_id : int, optional + ID of the captured face. + update_unrecognized_captured_face : bool, optional + Whether to update unrecognized captured face. + append_image_data : bool, optional + Append image data flag. + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5329,6 +10868,23 @@ def list_registered_face(self, filter: Any = None, append_image_data: bool = None, ) -> dict[str, object] | str: # TODO not working + """ + List registered faces. + + Parameters + ---------- + id_only : bool, optional + Whether to return only IDs. + filter : Any, optional + Filter criteria. + append_image_data : bool, optional + Whether to append image data (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5345,6 +10901,19 @@ def list_registered_face(self, def count_registered_face(self, # TODO not working filter: Any = None) -> dict[str, object] | str: + """ + Count the number of registered faces. + + Parameters + ---------- + filter : Any, optional + Filter criteria (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5362,6 +10931,21 @@ def search_registered_face(self, keywords: str = None, # TODO not working append_image_data: bool = None) -> dict[str, object] | str: + """ + Search for registered faces by keywords. + + Parameters + ---------- + keywords : str, optional + Search keywords. + append_image_data : bool, optional + Whether to append image data (not working). + + Returns + ------- + dict of str to object or str + API response from the request. + """ api_name = 'SYNO.SurveillanceStation.Face' info = self.gen_list[api_name] api_path = info['path'] @@ -5382,6 +10966,27 @@ def get_face_result_list(self, limit: int = None, # TODO not working slaveDsParam: int = None) -> dict[str, object] | str: + """ + Retrieve a list of face recognition results. + + Parameters + ---------- + filter : Any, optional + Filter criteria for the face results. + blIncludeSnapshot : bool, optional + Whether to include snapshot images in the results. + blIncludeRegisteredFace : bool, optional + Whether to include registered face information. + limit : int, optional + Maximum number of results to return. + slaveDsParam : int, optional + Additional parameter for slave DiskStation (not working). + + Returns + ------- + dict of str to object or str + API response containing the list of face recognition results. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5398,6 +11003,21 @@ def delete_face_result(self, filter: Any = None, # TODO not working slaveDsParam: Any = None) -> dict[str, object] | str: + """ + Delete face recognition results. + + Parameters + ---------- + filter : Any, optional + Filter criteria for selecting face results to delete. + slaveDsParam : Any, optional + Additional parameter for slave DiskStation (not working). + + Returns + ------- + dict of str to object or str + API response indicating the result of the delete operation. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5414,6 +11034,21 @@ def lock_face_result(self, filter: Any = None, # TODO not working slaveDsParam: Any = None) -> dict[str, object] | str: + """ + Lock face recognition results to prevent modification or deletion. + + Parameters + ---------- + filter : Any, optional + Filter criteria for selecting face results to lock. + slaveDsParam : Any, optional + Additional parameter for slave DiskStation (not working). + + Returns + ------- + dict of str to object or str + API response indicating the result of the lock operation. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5430,6 +11065,21 @@ def unlock_face_result(self, filter: Any = None, # TODO not working slaveDsParam: Any = None) -> dict[str, object] | str: + """ + Unlock face recognition results to allow modification or deletion. + + Parameters + ---------- + filter : Any, optional + Filter criteria for selecting face results to unlock. + slaveDsParam : Any, optional + Additional parameter for slave DiskStation (not working). + + Returns + ------- + dict of str to object or str + API response indicating the result of the unlock operation. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5445,6 +11095,19 @@ def unlock_face_result(self, def get_recording_file_of_face_info(self, # TODO not working capturedFaceId: int = None) -> dict[str, object] | str: + """ + Retrieve the recording file associated with a specific captured face. + + Parameters + ---------- + capturedFaceId : int, optional + ID of the captured face (not working). + + Returns + ------- + dict of str to object or str + API response containing the recording file information. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5464,6 +11127,27 @@ def get_recognition_face_information(self, endTime: int = None, # TODO not working blIncludeRegisteredFace: int = None) -> dict[str, object] | str: + """ + Retrieve analytic results for face recognition events. + + Parameters + ---------- + taskId : int, optional + ID of the face recognition task. + eventId : int, optional + ID of the event. + startTime : int, optional + Start time for the query (timestamp). + endTime : int, optional + End time for the query (timestamp). + blIncludeRegisteredFace : int, optional + Whether to include registered face information (not working). + + Returns + ------- + dict of str to object or str + API response containing analytic results. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5481,6 +11165,21 @@ def correct_face_result(self, id: int = None, # TODO not working registered_face_id: int = None) -> dict[str, object] | str: + """ + Correct the result of a face recognition event by associating it with a registered face. + + Parameters + ---------- + id : int, optional + ID of the face recognition result to correct. + registered_face_id : int, optional + ID of the registered face to associate (not working). + + Returns + ------- + dict of str to object or str + API response indicating the result of the correction. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5496,6 +11195,19 @@ def correct_face_result(self, def mark_face_result_as_stranger(self, # TODO not working ids: str = None) -> dict[str, object] | str: + """ + Mark one or more face recognition results as strangers. + + Parameters + ---------- + ids : str, optional + Comma-separated list of face result IDs to mark as strangers (not working). + + Returns + ------- + dict of str to object or str + API response indicating the result of the operation. + """ api_name = 'SYNO.SurveillanceStation.Face.Result' info = self.gen_list[api_name] api_path = info['path'] @@ -5517,6 +11229,31 @@ def add_new_bookmark(self, timestamp: Any = None, comment: str = None, ) -> dict[str, object] | str: # TODO not working + """ + Add a new bookmark to a recording. + + Parameters + ---------- + id : int, optional + ID of the bookmark. + eventId : int, optional + ID of the associated event. + cameraId : int, optional + ID of the camera. + archId : int, optional + ID of the archive. + name : str, optional + Name of the bookmark. + timestamp : Any, optional + Timestamp for the bookmark. + comment : str, optional + Comment for the bookmark. + + Returns + ------- + dict of str to object or str + API response indicating the result of the add operation. + """ api_name = 'SYNO.SurveillanceStation.Recording.Bookmark' info = self.gen_list[api_name] api_path = info['path'] @@ -5532,6 +11269,19 @@ def add_new_bookmark(self, def delete_bookmark(self, # TODO not working bookmarkIds: Any = None) -> dict[str, object] | str: + """ + Delete one or more bookmarks from recordings. + + Parameters + ---------- + bookmarkIds : Any, optional + IDs of the bookmarks to delete (not working). + + Returns + ------- + dict of str to object or str + API response indicating the result of the delete operation. + """ api_name = 'SYNO.SurveillanceStation.Recording.Bookmark' info = self.gen_list[api_name] api_path = info['path'] @@ -5551,6 +11301,27 @@ def list_bookmark_detail(self, fromTime: int = None, # TODO not working toTime: int = None) -> dict[str, object] | str: + """ + List details of bookmarks for recordings. + + Parameters + ---------- + offset : int, optional + Offset for pagination. + limit : int, optional + Maximum number of bookmarks to return. + cameraIds : str, optional + Comma-separated list of camera IDs to filter. + fromTime : int, optional + Start time for filtering bookmarks (timestamp). + toTime : int, optional + End time for filtering bookmarks (not working). + + Returns + ------- + dict of str to object or str + API response containing bookmark details. + """ api_name = 'SYNO.SurveillanceStation.Recording.Bookmark' info = self.gen_list[api_name] api_path = info['path'] From cb05e58f6f3208fe4b9261a24ce01a8253762c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 17:58:49 +0700 Subject: [PATCH 041/126] fix: synology_api/task_scheduler.py update docstrings to comply with Numpydoc standards --- synology_api/task_scheduler.py | 1161 +++++++++++++++++--------------- 1 file changed, 601 insertions(+), 560 deletions(-) diff --git a/synology_api/task_scheduler.py b/synology_api/task_scheduler.py index d343b3bc..f2e8b9bc 100644 --- a/synology_api/task_scheduler.py +++ b/synology_api/task_scheduler.py @@ -1,3 +1,4 @@ +"""Task Scheduler API implementation for Synology DSM.""" from __future__ import annotations from . import base_api from .core_user import User @@ -5,6 +6,40 @@ class _Schedule(): + """ + Schedule configuration class for Synology DSM task scheduling. + + This class encapsulates the parameters required to define a schedule for a task, + such as frequency, days, dates, repeat patterns, and time settings. + + Parameters + ---------- + run_frequently : bool, optional + If True, the schedule runs frequently (default is True). + run_days : str, optional + Comma-separated string of week days to run the task (default is '0,1,2,3,4,5,6'). + run_date : str, optional + Specific date to run the task (default is ''). + repeat : str, optional + Repeat pattern for the schedule, e.g., 'Daily' (default is 'Daily'). + monthly_week : list of str, optional + List of weeks in the month to run the task (default is empty list). + start_time_h : int, optional + Start time hour for the schedule (default is 0). + start_time_m : int, optional + Start time minute for the schedule (default is 0). + same_day_repeat_h : int, optional + Repeat interval in hours within the same day (default is 0). + same_day_repeat_m : int, optional + Repeat interval in minutes within the same day (default is 0). + same_day_repeat_until : int, optional + Time (in minutes) until which the same day repeat is active (default is 0). + + See Also + -------- + TaskScheduler : Main API class for managing scheduled tasks. + """ + def __init__( self, run_frequently: bool = True, # date_type @@ -18,6 +53,32 @@ def __init__( same_day_repeat_m: int = 0, same_day_repeat_until: int = 0, ): + """ + Initialize a schedule configuration for a Synology DSM task. + + Parameters + ---------- + run_frequently : bool, optional + If True, the schedule runs frequently (default is True). + run_days : str, optional + Comma-separated string of week days to run the task (default is '0,1,2,3,4,5,6'). + run_date : str, optional + Specific date to run the task (default is ''). + repeat : str, optional + Repeat pattern for the schedule, e.g., 'Daily' (default is 'Daily'). + monthly_week : list of str, optional + List of weeks in the month to run the task (default is empty list). + start_time_h : int, optional + Start time hour for the schedule (default is 0). + start_time_m : int, optional + Start time minute for the schedule (default is 0). + same_day_repeat_h : int, optional + Repeat interval in hours within the same day (default is 0). + same_day_repeat_m : int, optional + Repeat interval in minutes within the same day (default is 0). + same_day_repeat_until : int, optional + Time (in minutes) until which the same day repeat is active (default is 0). + """ self.run_frequently = run_frequently self.run_days = run_days self.run_date = run_date @@ -30,6 +91,24 @@ def __init__( self.same_day_repeat_until = same_day_repeat_until def _generate_dict(self) -> dict: + """ + Generate a dictionary representation of the schedule configuration. + + This method converts the schedule parameters into a dictionary format + suitable for use with the Synology DSM Task Scheduler API. + + Returns + ------- + dict + Dictionary containing the schedule configuration, including date type, + repeat modality, start time, repeat intervals, and other relevant fields. + + Notes + ----- + - The `repeat_date` field is set based on the `repeat` and `run_frequently` attributes. + - The `monthly_week` field is JSON-encoded. + - The `last_work_hour` defaults to `start_time_h` if `same_day_repeat_until` is not set. + """ schedule_dict = { 'date_type': 0 if self.run_frequently else 1, 'monthly_week': json.dumps(self.monthly_week), @@ -75,7 +154,8 @@ def _generate_dict(self) -> dict: class TaskScheduler(base_api.BaseApi): - """Task Scheduler API implementation. + """ + Task Scheduler API implementation. This API provides the functionality to get information related to the scheduler settings and current tasks. @@ -97,6 +177,17 @@ class TaskScheduler(base_api.BaseApi): """ def __get_root_token(self) -> str: + """ + Retrieve a root confirmation token for privileged operations. + + This method authenticates the current user and retrieves a Synology DSM root confirmation token, + which is required for executing privileged actions (e.g., creating or modifying root-owned tasks). + + Returns + ------- + str + The SynoConfirmPWToken if authentication is successful, otherwise an empty string. + """ user_api = User(ip_address=self.session._ip_address, port=self.session._port, username=self.session._username, password=self.session._password, secure=self.session._secure, cert_verify=self.session._verify, dsm_version=self.session._version, debug=self.session._debug, otp_code=self.session._otp_code, application=self.application) @@ -107,25 +198,26 @@ def __get_root_token(self) -> str: return '' def get_output_config(self) -> dict[str, object]: - """Retrieve tasks output configuration. - - Returns - ------- - dict[str, object] - A dictionary containing a list of the tasks and information related to them. - - Examples - -------- - ```json - { - "data": { - "enable_output": true, - "output_path": "share/scripts_output", - "type": "esynoscheduler", - }, - "success": true - } - ``` + """ + Retrieve tasks output configuration. + + Returns + ------- + dict[str, object] + A dictionary containing a list of the tasks and information related to them. + + Examples + -------- + ```json + { + "data": { + "enable_output": true, + "output_path": "share/scripts_output", + "type": "esynoscheduler", + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.EventScheduler' info = self.gen_list[api_name] @@ -145,76 +237,77 @@ def get_task_list( offset: int = 0, limit: int = 50 ) -> dict[str, object]: - """List all present scheduled tasks and event triggered tasks. - - Parameters - ---------- - sort_by : str, optional - The field to sort tasks by. Defaults to `"next_trigger_time"`. - - Possible values: - - "next_trigger_time" - - "name" - - "type" - - "action" - - "owner" - - sort_direction : str, optional - The sort direction. Defaults to `"ASC"`. - - Possible values: - - "ASC" - - "DESC" - - offset : int, optional - Task offset for pagination. Defaults to `0`. - - limit : int, optional - Number of tasks to retrieve. Defaults to `50`. - - Returns - ------- - dict[str, object] - A dictionary containing a list of the tasks and information related to them. - - Examples - -------- - ```json - { - "data": { - "tasks": [ - { - "action": "Run: rsync -aP --delete /volume1/test/ /volume1/test2/", - "can_delete": true, - "can_edit": true, - "can_run": true, - "enable": false, - "id": 13, - "name": "Sync folders", - "next_trigger_time": "2024-09-09 12:26", - "owner": "root", - "real_owner": "root", - "type": "script" - }, - { - "action": "Run: echo hello > /tmp/awacate.out", - "can_delete": true, - "can_edit": true, - "can_run": true, - "enable": true, - "id": 11, - "name": "TEST_CRONTAB", - "next_trigger_time": "2024-09-10 00:00", - "owner": "root", - "real_owner": "root", - "type": "script" - } - ] - "total": 2 - }, - "success": true - } - ``` + """ + List all present scheduled tasks and event triggered tasks. + + Parameters + ---------- + sort_by : str, optional + The field to sort tasks by. Defaults to `"next_trigger_time"`. + + Possible values: + - "next_trigger_time" + - "name" + - "type" + - "action" + - "owner" + + sort_direction : str, optional + The sort direction. Defaults to `"ASC"`. + + Possible values: + - "ASC" + - "DESC" + + offset : int, optional + Task offset for pagination. Defaults to `0`. + + limit : int, optional + Number of tasks to retrieve. Defaults to `50`. + + Returns + ------- + dict[str, object] + A dictionary containing a list of the tasks and information related to them. + + Examples + -------- + ```json + { + "data": { + "tasks": [ + { + "action": "Run: rsync -aP --delete /volume1/test/ /volume1/test2/", + "can_delete": true, + "can_edit": true, + "can_run": true, + "enable": false, + "id": 13, + "name": "Sync folders", + "next_trigger_time": "2024-09-09 12:26", + "owner": "root", + "real_owner": "root", + "type": "script" + }, + { + "action": "Run: echo hello > /tmp/awacate.out", + "can_delete": true, + "can_edit": true, + "can_run": true, + "enable": true, + "id": 11, + "name": "TEST_CRONTAB", + "next_trigger_time": "2024-09-10 00:00", + "owner": "root", + "real_owner": "root", + "type": "script" + } + ] + "total": 2 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.TaskScheduler' info = self.gen_list[api_name] @@ -236,68 +329,67 @@ def get_task_config( real_owner: str, type: str = '' ) -> dict[str, object]: - """Retrieve the configuration for a specific task or list of all the available services and their corresponding IDs. - - Parameters - ---------- - task_id : int - The ID of the task to retrieve the configuration for. Pass `-1` to get a list of all available services with their IDs. - - real_owner : str - The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. - - type : str, optional - The type of task (e.g., 'service'). Pass "service" to get a list of all available services with their IDs. Defaults to `""`. - - Returns - ------- - dict[str, object] - A dictionary containing the task configuration. - - Examples - -------- - ```json - { - "data": { - "action": "Run: echo hello > /tmp/awacate.out", - "can_edit_name": true, - "can_edit_owner": true, - "enable": true, - "extra": { - "notify_enable": false, - "notify_if_error": false, - "notify_mail": "", - "script": "echo hello > /tmp/awacate.out" - }, - "id": 11, - "name": "TEST_CRONTAB", - "owner": "root", - "real_owner": "root", - "schedule": { - "date": "2024/9/11", - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "minute": 0, - "monthly_week": [], - "repeat_date": 1001, - "repeat_hour": 0, - "repeat_hour_store_config": [ - 1..23 - ], - "repeat_min": 0, - "repeat_min_store_config": [ - 1, - ... - ], - "version": 4, - "week_day": "0,1,2,3,4,5,6" - }, - "type": "script" + """ + Retrieve the configuration for a specific task or list all available services and their corresponding IDs. + + Parameters + ---------- + task_id : int + The ID of the task to retrieve the configuration for. Pass `-1` to get a list of all available services with their IDs. + real_owner : str + The real owner of the task, usually `root`. You can double check from the result of `get_task_config()`. + type : str, optional + The type of task (e.g., 'service'). Pass `"service"` to get a list of all available services with their IDs. Defaults to `""`. + + Returns + ------- + dict[str, object] + A dictionary containing the task configuration. + + Examples + -------- + ```json + { + "data": { + "action": "Run: echo hello > /tmp/awacate.out", + "can_edit_name": true, + "can_edit_owner": true, + "enable": true, + "extra": { + "notify_enable": false, + "notify_if_error": false, + "notify_mail": "", + "script": "echo hello > /tmp/awacate.out" }, - "success": true - } - ``` + "id": 11, + "name": "TEST_CRONTAB", + "owner": "root", + "real_owner": "root", + "schedule": { + "date": "2024/9/11", + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "minute": 0, + "monthly_week": [], + "repeat_date": 1001, + "repeat_hour": 0, + "repeat_hour_store_config": [ + 1..23 + ], + "repeat_min": 0, + "repeat_min_store_config": [ + 1, + ... + ], + "version": 4, + "week_day": "0,1,2,3,4,5,6" + }, + "type": "script" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.TaskScheduler' info = self.gen_list[api_name] @@ -318,41 +410,42 @@ def get_task_results( self, task_id: int ) -> dict[str, object]: - """Retrieve the results list for a specific task. - - Parameters - ---------- - task_id : int - The ID of the task to retrieve the results for. - - Returns - ------- - dict[str, object] - A dictionary containing the task results. - - Examples - -------- - ```json - { - "data": [ - { - "exit_code": 127, - "exit_type": "by_signal", - "start_time": "2024-09-11 00:00:01", - "stop_time": "2024-09-11 00:00:06", - "timestamp": "1726005601" - }, - { - "exit_code": 0, - "exit_type": "normal", - "start_time": "2024-06-01 00:00:01", - "stop_time": "2024-06-01 00:00:02", - "timestamp": "1717192801" - } - ], - "success": true - } - ``` + """ + Retrieve the results list for a specific task. + + Parameters + ---------- + task_id : int + The ID of the task to retrieve the results for. + + Returns + ------- + dict[str, object] + A dictionary containing the task results. + + Examples + -------- + ```json + { + "data": [ + { + "exit_code": 127, + "exit_type": "by_signal", + "start_time": "2024-09-11 00:00:01", + "stop_time": "2024-09-11 00:00:06", + "timestamp": "1726005601" + }, + { + "exit_code": 0, + "exit_type": "normal", + "start_time": "2024-06-01 00:00:01", + "stop_time": "2024-06-01 00:00:02", + "timestamp": "1717192801" + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.TaskScheduler' info = self.gen_list[api_name] @@ -414,7 +507,8 @@ def set_output_config( enable_output: bool, output_path: str = '' ) -> dict[str, object]: - """Configure the output settings for tasks results. + """ + Configure the output settings for tasks results. Parameters ---------- @@ -422,7 +516,7 @@ def set_output_config( Whether to enable result logging or not. output_path : str, optional - The path where the result logs will be stored, e.g. `share/scripts_output'`. Defaults to `""`. + The path where the result logs will be stored, e.g. `share/scripts_output`. Defaults to `""`. Returns ------- @@ -456,7 +550,8 @@ def task_set_enable( real_owner: str, enable: bool ) -> dict[str, object]: - """Enable or disable a task. + """ + Enable or disable a task. Parameters ---------- @@ -504,7 +599,8 @@ def task_run( task_id: int, real_owner: str ) -> dict[str, object]: - """Run a specific task. + """ + Run a specific task. Parameters ---------- @@ -548,7 +644,8 @@ def task_delete( task_id: int, real_owner: str ) -> dict[str, object]: - """Delete a specific task. + """ + Delete a specific task. Parameters ---------- @@ -606,7 +703,8 @@ def create_script_task( notify_email: str = '', notify_only_on_error: bool = False ) -> dict[str, object]: - """Create a new Script task with the provided schedule and notification settings. + """ + Create a new Script task with the provided schedule and notification settings. Tip: If the task needs to run with root privileges, please specify the owner as "root". @@ -753,7 +851,8 @@ def modify_script_task( notify_email: str = '', notify_only_on_error: bool = False ) -> dict[str, object]: - """Modify settings of a Script task. + """ + Modify settings of a Script task. Warning: This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. @@ -901,88 +1000,74 @@ def create_beep_control_task( same_day_repeat_m: int = 0, same_day_repeat_until: int = -1 ) -> dict[str, object]: - """Create a new Beep Control task with the provided schedule and beep duration. - - Parameters - ---------- - task_name : str - The name of the task. - - owner : str - The task owner. - - beep_duration : int, optional - The amount of seconds the beep will be triggered for, in seconds. Defaults to `60`. - - enable : bool, optional - Whether the task should be enabled upon creation. Defaults to `True`. - - run_frequently : bool, optional - Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. - - run_days : str, optional - Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). - - run_date : str, optional - The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. - - repeat : str, optional - How often the task should repeat. Defaults to `'daily'`. - - Possible values: - - `daily` -> Only when 'run_frequently=True' - - `weekly` -> Only when 'run_frequently=True' - - `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' - - `no_repeat` -> Only when 'run_frequently=False' - - `every_3_months` -> Only when 'run_frequently=False' - - `every_6_months` -> Only when 'run_frequently=False' - - `yearly` -> Only when 'run_frequently=False' - - - monthly_week : list[str], optional - If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. - Defaults to `[]`. - - start_time_h : int, optional - Hour at which the task should start. Defaults to `0`. - - start_time_m : int, optional - Minute at which the task should start. Defaults to `0`. - - same_day_repeat_h : int, optional - Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. - Set to `0` to disable same-day repeats. Defaults to `0`. - - Possible values: `0..23` - - The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_m : int, optional - Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. - Set to `0` to disable same-day repeats. Defaults to `0`. - - Posible values: `1`, `5`, `10`, `15`, `20`, `30` - - The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_until : int, optional - Last hour of the day when the task can repeat. Defaults to `start_time_h`. - - Returns - ------- - dict[str, object] - A dictionary with the id of the created task. - - Examples - -------- - ```json - { - "data": { - "id": 20 - }, - "success": true - } - ``` + """ + Create a new Beep Control task with the provided schedule and beep duration. + + Parameters + ---------- + task_name : str + The name of the task. + owner : str + The task owner. + enable : bool, optional + Whether the task should be enabled upon creation. Defaults to True. + beep_duration : int, optional + The amount of seconds the beep will be triggered for. Defaults to 60. + run_frequently : bool, optional + Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to True. + run_days : str, optional + Days of the week when the task should run, used if `run_frequently` is set to True, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to '0,1,2,3,4,5,6'. + run_date : str, optional + The specific date the task should run, used if `run_frequently` is set to False. Format: yyyy/m/d (no prefix zeros). Defaults to "". + repeat : str, optional + How often the task should repeat. Defaults to 'daily'. + + Possible values: + - 'daily' -> Only when run_frequently=True + - 'weekly' -> Only when run_frequently=True + - 'monthly' -> Works for both run_frequently=True and run_frequently=False + - 'no_repeat' -> Only when run_frequently=False + - 'every_3_months' -> Only when run_frequently=False + - 'every_6_months' -> Only when run_frequently=False + - 'yearly' -> Only when run_frequently=False + monthly_week : list[str], optional + If run_frequently=True and repeat='monthly', specifies the weeks the task should run, e.g., ['first', 'third']. Defaults to []. + start_time_h : int, optional + Hour at which the task should start. Defaults to 0. + start_time_m : int, optional + Minute at which the task should start. Defaults to 0. + same_day_repeat_h : int, optional + Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. + Set to 0 to disable same-day repeats. Defaults to 0. + + Possible values: 0..23 + + The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time, if both are passed, same_day_repeat_h will be prioritized. + same_day_repeat_m : int, optional + Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. + Set to 0 to disable same-day repeats. Defaults to 0. + + Possible values: 1, 5, 10, 15, 20, 30 + + The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time, if both are passed, same_day_repeat_h will be prioritized. + same_day_repeat_until : int, optional + Last hour of the day when the task can repeat. Defaults to start_time_h. + + Returns + ------- + dict[str, object] + A dictionary with the id of the created task. + + Examples + -------- + ```json + { + "data": { + "id": 20 + }, + "success": true + } + ``` """ schedule = _Schedule(run_frequently, run_days, run_date, repeat, monthly_week, start_time_h, start_time_m, @@ -1028,92 +1113,82 @@ def modify_beep_control_task( same_day_repeat_m: int = 0, same_day_repeat_until: int = -1 ) -> dict[str, object]: - """Modify settings of a Beep Control task. - - Warning: This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. - - Parameters - ---------- - task_name : str - The name of the task. - - real_owner : str - The task owner. - - beep_duration : int, optional - The amount of seconds the beep will be triggered for, in seconds. Defaults to `60`. - - enable : bool, optional - Whether the task should be enabled upon creation. Defaults to `True`. - - run_frequently : bool, optional - Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. - - run_days : str, optional - Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). - - run_date : str, optional - The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. - - repeat : str, optional - How often the task should repeat. Defaults to `'daily'`. - - Possible values: - - `daily` -> Only when 'run_frequently=True' - - `weekly` -> Only when 'run_frequently=True' - - `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' - - `no_repeat` -> Only when 'run_frequently=False' - - `every_3_months` -> Only when 'run_frequently=False' - - `every_6_months` -> Only when 'run_frequently=False' - - `yearly` -> Only when 'run_frequently=False' - - monthly_week : list[str], optional - If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. - - start_time_h : int, optional - Hour at which the task should start. Defaults to `0`. - - start_time_m : int, optional - Minute at which the task should start. Defaults to `0`. - - same_day_repeat_h : int, optional - Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. - - Set to `0` to disable same-day repeats. Defaults to `0`. - - Possible values: `0..23` - - Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_m : int, optional - Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. - - Set to `0` to disable same-day repeats. Defaults to `0`. - - Posible values: `1`, `5`, `10`, `15`, `20`, `30` - - Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_until : int, optional - Last hour of the day when the task can repeat. Defaults to `start_time_h`. - - Returns - ------- - dict[str, object] - A dictionary with the id of the created task. - - Examples - -------- - ```json - { - "data": { - "id": 20 - }, - "success": true - } - ``` """ - + Modify settings of a Beep Control task. + + Parameters + ---------- + task_id : int + The ID of the task to modify. + task_name : str + The name of the task. + real_owner : str + The task owner. + enable : bool, optional + Whether the task should be enabled upon modification. Defaults to `True`. + beep_duration : int, optional + The amount of seconds the beep will be triggered for, in seconds. Defaults to `60`. + run_frequently : bool, optional + Determines whether the task runs on a recurring schedule (`True`) or only on a specific date (`False`). Defaults to `True`. + run_days : str, optional + Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). + run_date : str, optional + The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. + repeat : str, optional + How often the task should repeat. Defaults to `'daily'`. + + Possible values: + - `daily` -> Only when `run_frequently=True` + - `weekly` -> Only when `run_frequently=True` + - `monthly` -> Works for both `run_frequently=True` and `run_frequently=False` + - `no_repeat` -> Only when `run_frequently=False` + - `every_3_months` -> Only when `run_frequently=False` + - `every_6_months` -> Only when `run_frequently=False` + - `yearly` -> Only when `run_frequently=False` + monthly_week : list[str], optional + If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. + start_time_h : int, optional + Hour at which the task should start. Defaults to `0`. + start_time_m : int, optional + Minute at which the task should start. Defaults to `0`. + same_day_repeat_h : int, optional + Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. + Set to `0` to disable same-day repeats. Defaults to `0`. + + Possible values: `0..23` + + Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. + same_day_repeat_m : int, optional + Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. + Set to `0` to disable same-day repeats. Defaults to `0`. + + Possible values: `1`, `5`, `10`, `15`, `20`, `30` + + Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. + same_day_repeat_until : int, optional + Last hour of the day when the task can repeat. Defaults to `start_time_h`. + + Returns + ------- + dict[str, object] + A dictionary with the id of the modified task. + + Notes + ----- + Warning: This method overwrites all the settings of the task, so if you only want to change one setting, + you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. + + Examples + -------- + ```json + { + "data": { + "id": 20 + }, + "success": true + } + ``` + """ schedule = _Schedule(run_frequently, run_days, run_date, repeat, monthly_week, start_time_h, start_time_m, same_day_repeat_h, same_day_repeat_m, same_day_repeat_until) @@ -1157,7 +1232,8 @@ def create_service_control_task( same_day_repeat_m: int = 0, same_day_repeat_until: int = -1 ) -> dict[str, object]: - """Create a new Service Control task with the provided schedule and services to start/stop. + """ + Create a new Service Control task with the provided schedule and services to start/stop. Parameters ---------- @@ -1167,7 +1243,7 @@ def create_service_control_task( owner : str The task owner. - services (list): + services : list[dict] A list containing the services and their type to be influenced by the specified action (start / stop). To get a list of all the available services and their corresponding IDs, call `get_task_config(task_id=-1, real_owner=your_username, type='service')`. @@ -1179,7 +1255,7 @@ def create_service_control_task( {'id': 'HyperBackup', 'type': 'package'}, {'id': 'Samba', 'type': 'service'} ] - ``` + ```. action : str The action to apply to the services. Either `'start'` or `'stop'`. @@ -1309,7 +1385,8 @@ def modify_service_control_task( same_day_repeat_m: int = 0, same_day_repeat_until: int = -1 ) -> dict[str, object]: - """Modify settings of a Service Control task. + """ + Modify settings of a Service Control task. Warning: This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. @@ -1324,7 +1401,7 @@ def modify_service_control_task( real_owner : str The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. - services (list): + services : list[dict] A list containing the services and their type to be influenced by the specified action (start / stop). To get a list of all the available services and their corresponding IDs, call `get_task_config(task_id=-1, real_owner=your_username, type='service')`. @@ -1336,7 +1413,7 @@ def modify_service_control_task( {'id': 'HyperBackup', 'type': 'package'}, {'id': 'Samba', 'type': 'service'} ] - ``` + ```. action : str The action to apply to the services. Either `'start'` or `'stop'`. @@ -1468,95 +1545,76 @@ def create_recycle_bin_task( same_day_repeat_m: int = 0, same_day_repeat_until: int = -1 ) -> dict[str, object]: - """Create a new Recycle Bin Control task with the provided schedule and services to start/stop. - - Parameters - ---------- - task_name : str - The name of the task. - - owner : str - The task owner. - - clean_all_shares : bool - Whether the task should empty the recycle bins of all shares or not, if set to `False`, shares must be specified. - - shares : list[str], optional - List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to `[]`. - - policy (dict): - Determines what files will be deleted from the recycle bins. - - Possible values are: - - `{"policy": "clean_all"}` -> Clean all files - - `{"policy": "time", "time": int}` -> Clean all files older than X days, days being possed as value for "time" key. - - `{"policy": "size", "size": int , "sort_type": int}` -> Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". - - Possible values for "sort_type" are: - - `0` -> Delete bigger files first - - `1` -> Delete older files first - - enable : bool, optional - Whether the task should be enabled upon creation. Defaults to `True`. - - run_frequently : bool, optional - Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. - - run_days : str, optional - Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). - - run_date : str, optional - The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). - Defaults to `""`. - - repeat : str, optional - How often the task should repeat. Defaults to `'daily'`. - - Possible values: - - `daily` -> Only when 'run_frequently=True' - - `weekly` -> Only when 'run_frequently=True' - - `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' - - `no_repeat` -> Only when 'run_frequently=False' - - `every_3_months` -> Only when 'run_frequently=False' - - `every_6_months` -> Only when 'run_frequently=False' - - `yearly` -> Only when 'run_frequently=False' - - monthly_week : list[str], optional - If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. - - Defaults to `[]`. - - start_time_h : int, optional - Hour at which the task should start. Defaults to `0`. - - start_time_m : int, optional - Minute at which the task should start. Defaults to `0`. - - same_day_repeat_h : int, optional - Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. - - Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). - - Possible values: `0..23` - - Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_m : int, optional - Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. - - Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). - - Posible values: `1`, `5`, `10`, `15`, `20`, `30` - - Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_until : int, optional - Last hour of the day when the task can repeat. Defaults to `start_time_h`. - - Returns - ------- - dict[str, object] - A dictionary with the id of the created task. + """ + Create a new Recycle Bin Control task with the provided schedule and policy. + + Parameters + ---------- + task_name : str + The name of the task. + owner : str + The task owner. + clean_all_shares : bool + Whether the task should empty the recycle bins of all shares. If set to False, `shares` must be specified. + policy : dict + Determines what files will be deleted from the recycle bins. + + Possible values are: + - {"policy": "clean_all"}: Clean all files. + - {"policy": "time", "time": int}: Clean all files older than X days, where X is the value for "time". + - {"policy": "size", "size": int, "sort_type": int}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". + + Possible values for "sort_type": + - 0: Delete bigger files first. + - 1: Delete older files first. + shares : list[str], optional + List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to []. + enable : bool, optional + Whether the task should be enabled upon creation. Defaults to True. + run_frequently : bool, optional + Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to True. + run_days : str, optional + Days of the week when the task should run, used if `run_frequently` is True, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to '0,1,2,3,4,5,6'. + run_date : str, optional + The specific date the task should run, used if `run_frequently` is False. Format: yyyy/m/d (no prefix zeros). Defaults to "". + repeat : str, optional + How often the task should repeat. Defaults to 'daily'. + + Possible values: + - 'daily' (only when run_frequently=True) + - 'weekly' (only when run_frequently=True) + - 'monthly' (works for both run_frequently=True and run_frequently=False) + - 'no_repeat' (only when run_frequently=False) + - 'every_3_months' (only when run_frequently=False) + - 'every_6_months' (only when run_frequently=False) + - 'yearly' (only when run_frequently=False) + monthly_week : list[str], optional + If run_frequently=True and repeat='monthly', specifies the weeks the task should run, e.g., ['first', 'third']. Defaults to []. + start_time_h : int, optional + Hour at which the task should start. Defaults to 0. + start_time_m : int, optional + Minute at which the task should start. Defaults to 0. + same_day_repeat_h : int, optional + Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. + Set to 0 to disable same-day repeats. Defaults to 0. + + Possible values: 0..23 + + Note: The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time; if both are passed, same_day_repeat_h will be prioritized. + same_day_repeat_m : int, optional + Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. + Set to 0 to disable same-day repeats. Defaults to 0. + + Possible values: 1, 5, 10, 15, 20, 30 + + Note: The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time; if both are passed, same_day_repeat_h will be prioritized. + same_day_repeat_until : int, optional + Last hour of the day when the task can repeat. Defaults to start_time_h. + + Returns + ------- + dict[str, object] + A dictionary with the id of the created task. Examples -------- @@ -1621,111 +1679,94 @@ def modify_recycle_bin_task( same_day_repeat_m: int = 0, same_day_repeat_until: int = -1 ) -> dict[str, object]: - """Modify settings of a Recycle Bin Control task. - - Warning: This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. - - Parameters - ---------- - task_id : int - The ID of the task. - - task_name : str - The name of the task. - - real_owner : str - The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. - - clean_all_shares : bool - Whether the task should empty the recycle bins of all shares or not, if set to `False`, shares must be specified. - - shares : list[str], optional - List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to `[]`. - - policy (dict): - Determines what files will be deleted from the recycle bins. - - Possible values are: - - `{"policy": "clean_all"}` -> Clean all files - - `{"policy": "time", "time": int}` -> Clean all files older than X days, days being possed as value for "time" key. - - `{"policy": "size", "size": int , "sort_type": int}` -> Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". - - Possible values for "sort_type" are: - - `0` -> Delete bigger files first - - `1` -> Delete older files first - - enable : bool, optional - Whether the task should be enabled upon creation. Defaults to `True`. - - run_frequently : bool, optional - Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. - - run_days : str, optional - Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). - - run_date : str, optional - The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). - Defaults to `""`. - - repeat : str, optional - How often the task should repeat. Defaults to `'daily'`. - - Possible values: - - `daily` -> Only when 'run_frequently=True' - - `weekly` -> Only when 'run_frequently=True' - - `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' - - `no_repeat` -> Only when 'run_frequently=False' - - `every_3_months` -> Only when 'run_frequently=False' - - `every_6_months` -> Only when 'run_frequently=False' - - `yearly` -> Only when 'run_frequently=False' - - monthly_week : list[str], optional - If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. - - Defaults to `[]`. - - start_time_h : int, optional - Hour at which the task should start. Defaults to `0`. - - start_time_m : int, optional - Minute at which the task should start. Defaults to `0`. - - same_day_repeat_h : int, optional - Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. - - Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). - - Possible values: `0..23` - - Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_m : int, optional - Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. - - Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). - - Posible values: `1`, `5`, `10`, `15`, `20`, `30` - - Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. - - same_day_repeat_until : int, optional - Last hour of the day when the task can repeat. Defaults to `start_time_h`. - - Returns - ------- - dict[str, object] - A dictionary with the id of the created task. - - Examples - -------- - ```json - { - "data": { - "id": 20 - }, - "success": true - } - ``` + """ + Modify settings of a Recycle Bin Control task. + + Parameters + ---------- + task_id : int + The ID of the task. + task_name : str + The name of the task. + real_owner : str + The task real owner, usually it is `root`. You can double check from the result of `get_task_config()`. + clean_all_shares : bool + Whether the task should empty the recycle bins of all shares. If set to `False`, `shares` must be specified. + policy : dict + Determines what files will be deleted from the recycle bins. + + Possible values are: + - {"policy": "clean_all"}: Clean all files. + - {"policy": "time", "time": int}: Clean all files older than X days, where X is the value for "time". + - {"policy": "size", "size": int, "sort_type": int}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". + + Possible values for "sort_type": + - 0: Delete bigger files first. + - 1: Delete older files first. + shares : list[str], optional + List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to []. + enable : bool, optional + Whether the task should be enabled upon modification. Defaults to `True`. + run_frequently : bool, optional + Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. + run_days : str, optional + Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'`. + run_date : str, optional + The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. + repeat : str, optional + How often the task should repeat. Defaults to `'daily'`. + + Possible values: + - `daily` (only when run_frequently=True) + - `weekly` (only when run_frequently=True) + - `monthly` (works for both run_frequently=True and run_frequently=False) + - `no_repeat` (only when run_frequently=False) + - `every_3_months` (only when run_frequently=False) + - `every_6_months` (only when run_frequently=False) + - `yearly` (only when run_frequently=False) + monthly_week : list[str], optional + If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to []. + start_time_h : int, optional + Hour at which the task should start. Defaults to `0`. + start_time_m : int, optional + Minute at which the task should start. Defaults to `0`. + same_day_repeat_h : int, optional + Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. + Set to `0` to disable same-day repeats. Defaults to `0`. + + Possible values: `0..23` + + Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. + same_day_repeat_m : int, optional + Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. + Set to `0` to disable same-day repeats. Defaults to `0`. + + Possible values: `1`, `5`, `10`, `15`, `20`, `30` + + Info: The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. + same_day_repeat_until : int, optional + Last hour of the day when the task can repeat. Defaults to `start_time_h`. + + Returns + ------- + dict[str, object] + A dictionary with the id of the modified task. + + Notes + ----- + Warning: This method overwrites all the settings of the task, so if you only want to change one setting, + you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. + + Examples + -------- + ```json + { + "data": { + "id": 20 + }, + "success": true + } + ``` """ schedule = _Schedule(run_frequently, run_days, run_date, repeat, monthly_week, start_time_h, start_time_m, From 60fa9348aa3f6f2380d0ff3622f8a4a2add33067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:00:10 +0700 Subject: [PATCH 042/126] fix: synology_api/universal_search.py update docstrings to comply with Numpydoc standards --- synology_api/universal_search.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/synology_api/universal_search.py b/synology_api/universal_search.py index 2605c7cb..b2d1ba4e 100644 --- a/synology_api/universal_search.py +++ b/synology_api/universal_search.py @@ -1,11 +1,30 @@ +"""Synology Universal Search API Wrapper.""" from __future__ import annotations from typing import Optional, Any from . import base_api class UniversalSearch(base_api.BaseApi): + """ + API wrapper for Synology Universal Search. + + Provides methods to perform keyword-based searches using Synology's Universal Search API. + """ def search(self, keyword: str) -> dict[str, object] | str: + """ + Search for files and metadata matching the given keyword. + + Parameters + ---------- + keyword : str + The search keyword. + + Returns + ------- + dict[str, object] or str + Search results as a dictionary, or a string with error details. + """ api_name = 'SYNO.Finder.FileIndexing.Search' info = self.gen_list[api_name] api_path = info['path'] From a119ec37f0024a2d13cb0a8d983adc15b78dd880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:03:57 +0700 Subject: [PATCH 043/126] fix: synology_api/usb_copy.py update docstrings to comply with Numpydoc standards --- synology_api/usb_copy.py | 237 ++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 118 deletions(-) diff --git a/synology_api/usb_copy.py b/synology_api/usb_copy.py index d318dd42..9390893a 100644 --- a/synology_api/usb_copy.py +++ b/synology_api/usb_copy.py @@ -1,42 +1,45 @@ +"""USB Copy API wrapper for Synology NAS.""" from __future__ import annotations from typing import Optional from . import base_api class USBCopy(base_api.BaseApi): - """USB Copy Implementation. + """ + USB Copy API wrapper for Synology NAS. - Supported methods: - - Getters: - - Get package settings - - Get package logs - - Get task settings + Methods + ------- + Getters: + - Get package settings + - Get package logs + - Get task settings - - Actions: - - Enable / Disable task + Actions: + - Enable / Disable task """ def get_package_settings(self) -> dict[str, object]: - """Retrieve package settings. + """ + Retrieve package settings. - Returns - ------- - dict[str, object] - Parsed JSON into `dict` + Returns + ------- + dict[str, object] + Parsed JSON into a dictionary. - Examples - -------- - ```python + Examples + -------- + ```python { - "data" : { - "beep_on_task_start_end" : True, - "log_rotate_count" : 100000, - "repo_volume_path" : "/volume2" + "data": { + "beep_on_task_start_end": True, + "log_rotate_count": 100000, + "repo_volume_path": "/volume2" }, - "success" : True + "success": True } - ``` - + ``` """ api_name = 'SYNO.USBCopy' info = self.gen_list[api_name] @@ -47,42 +50,41 @@ def get_package_settings(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_package_logs(self, offset: int = 0, limit: int = 200) -> dict[str, object]: - """Retrieve package logs. - - Parameters - ---------- - offset : int - Defaults to `0`. - - limit : int - Defaults to `200`. - - Returns - ------- - dict[str, object] - Parsed response JSON into `dict` - - Examples - -------- - ```python + """ + Retrieve package logs. + + Parameters + ---------- + offset : int, optional + Offset for logs. Defaults to 0. + limit : int, optional + Maximum number of logs to retrieve. Defaults to 200. + + Returns + ------- + dict[str, object] + Parsed response JSON into a dictionary. + + Examples + -------- + ```python { - "data" : { - "count" : 1, - "log_list" : [ + "data": { + "count": 1, + "log_list": [ { - "description_id" : 101, - "description_parameter" : "[\"asdf\"]", - "error" : 0, - "log_type" : 1, - "task_id" : 2, - "timestamp" : 1738341351 - }, + "description_id": 101, + "description_parameter": "[\"asdf\"]", + "error": 0, + "log_type": 1, + "task_id": 2, + "timestamp": 1738341351 + } ] }, - "success" : True + "success": True } - ``` - + ``` """ api_name = 'SYNO.USBCopy' info = self.gen_list[api_name] @@ -93,57 +95,57 @@ def get_package_logs(self, offset: int = 0, limit: int = 200) -> dict[str, objec return self.request_data(api_name, api_path, req_param) def get_task_settings(self, task_id: int) -> dict[str, object]: - """Retrieve task settings + """ + Retrieve task settings. - Parameters - ---------- - task_id: int - Task ID to retrieve info for + Parameters + ---------- + task_id : int + Task ID to retrieve info for. - Returns - ------- - dict[str, object] - Parsed response JSON into `dict` + Returns + ------- + dict[str, object] + Parsed response JSON into a dictionary. - Examples - -------- - ```python + Examples + -------- + ```python { - "data" : { - "task" : { - "conflict_policy" : "rename", - "copy_file_path" : "", - "copy_strategy" : "versioning", - "default_device_port" : "NA", - "destination_path" : "[USB]", - "eject_when_task_done" : True, - "enable_rotation" : False, - "error_code" : 0, - "id" : 2, - "is_default_task" : False, - "is_ds_mounted" : False, - "is_task_runnable" : False, - "is_usb_mounted" : False, - "latest_finish_time" : 1738341351, - "max_version_count" : 256, - "name" : "asdf", - "next_run_time" : "N/A", - "not_keep_dir_structure" : False, - "remove_src_file" : False, - "rename_photo_video" : False, - "rotation_policy" : "oldest_version", - "run_when_plug_in" : False, - "schedule_id" : 13, - "smart_create_date_dir" : False, - "source_path" : "/music", - "status" : "unmounted", - "type" : "export_general" + "data": { + "task": { + "conflict_policy": "rename", + "copy_file_path": "", + "copy_strategy": "versioning", + "default_device_port": "NA", + "destination_path": "[USB]", + "eject_when_task_done": True, + "enable_rotation": False, + "error_code": 0, + "id": 2, + "is_default_task": False, + "is_ds_mounted": False, + "is_task_runnable": False, + "is_usb_mounted": False, + "latest_finish_time": 1738341351, + "max_version_count": 256, + "name": "asdf", + "next_run_time": "N/A", + "not_keep_dir_structure": False, + "remove_src_file": False, + "rename_photo_video": False, + "rotation_policy": "oldest_version", + "run_when_plug_in": False, + "schedule_id": 13, + "smart_create_date_dir": False, + "source_path": "/music", + "status": "unmounted", + "type": "export_general" } }, - "success" : True + "success": True } - ``` - + ``` """ api_name = 'SYNO.USBCopy' info = self.gen_list[api_name] @@ -154,29 +156,28 @@ def get_task_settings(self, task_id: int) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def toggle_task(self, task_id: int, enable: bool = True) -> dict[str, object]: - """Enable or disable USB Copy task - - Parameters - ---------- - task_id : int - Task ID to apply the setting to. - - enable : bool - Whether to enable (`True`) or disable (`False`) USB Copy. Defaults to `True`. - - Returns - ------- - dict[str, object] - Parsed response JSON into `dict` - - Examples - -------- - ```python + """ + Enable or disable a USB Copy task. + + Parameters + ---------- + task_id : int + Task ID to apply the setting to. + enable : bool, optional + Whether to enable (True) or disable (False) the USB Copy task. Defaults to True. + + Returns + ------- + dict[str, object] + Parsed response JSON into a dictionary. + + Examples + -------- + ```python { "success": True } - ``` - + ``` """ api_name = 'SYNO.USBCopy' info = self.gen_list[api_name] From 4e2ef5d727d3ab53864a98cdc5bc53331c1bca37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:06:56 +0700 Subject: [PATCH 044/126] fix: synology_api/utils.py update docstrings to comply with Numpydoc standards --- synology_api/utils.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/synology_api/utils.py b/synology_api/utils.py index cc2e8aa2..bf40049e 100644 --- a/synology_api/utils.py +++ b/synology_api/utils.py @@ -1,3 +1,4 @@ +"""Utility functions for Synology API operations.""" import json import sys # my_package/my_module.py @@ -5,6 +6,21 @@ def merge_dicts(x, y): + """ + Merge two dictionaries. + + Parameters + ---------- + x : dict + The first dictionary. + y : dict + The second dictionary. + + Returns + ------- + dict + A new dictionary containing the merged keys and values from both input dictionaries. + """ z = x.copy() # start with keys and values of x z.update(y) # modifies z with keys and values of y return z @@ -14,11 +30,15 @@ def make_folder_meta_list_from_path(path): """ Create a list of folder metadata dictionaries from a given path. - Args: - path (str): The file path to be split into folder metadata. + Parameters + ---------- + path : str + The file path to be split into folder metadata. - Returns: - list: A list of dictionaries containing folder metadata. + Returns + ------- + list of dict + A list of dictionaries containing folder metadata for each folder in the path. """ folder_list = [] path_list = path.split('/') # Split the path into components From 435dbddaabf849649edb71e1ad5e159259b45c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:09:12 +0700 Subject: [PATCH 045/126] fix: synology_api/virtualization.py update docstrings to comply with Numpydoc standards --- synology_api/virtualization.py | 350 ++++++++++++++++++++++++++++++--- 1 file changed, 318 insertions(+), 32 deletions(-) diff --git a/synology_api/virtualization.py b/synology_api/virtualization.py index 872a6299..e561a642 100644 --- a/synology_api/virtualization.py +++ b/synology_api/virtualization.py @@ -1,9 +1,43 @@ +""" +Virtualization API wrapper for Synology Virtual Machine Manager. + +This module provides the Virtualization class for managing tasks, networks, storage, hosts, VMs, and images +on Synology NAS devices via the Virtual Machine Manager API. +""" + from __future__ import annotations from typing import Optional, Any from . import base_api class Virtualization(base_api.BaseApi): + """ + API wrapper for Synology Virtual Machine Manager. + + Provides methods to manage tasks, networks, storage, hosts, VMs, and images. + + Parameters + ---------- + ip_address : str + IP address of the Synology NAS. + port : str + Port number to connect to. + username : str + DSM username. + password : str + DSM password. + secure : bool, optional + Use HTTPS if True. Default is False. + cert_verify : bool, optional + Verify SSL certificate if True. Default is False. + dsm_version : int, optional + DSM version. Default is 7. + debug : bool, optional + Enable debug mode. Default is True. + otp_code : str, optional + One-time password for 2FA, if required. + """ + def __init__(self, ip_address: str, port: str, @@ -15,6 +49,30 @@ def __init__(self, debug: bool = True, otp_code: Optional[str] = None ) -> None: + """ + Initialize the Virtualization API wrapper. + + Parameters + ---------- + ip_address : str + IP address of the Synology NAS. + port : str + Port number. + username : str + DSM username. + password : str + DSM password. + secure : bool, optional + Use HTTPS if True. Default is False. + cert_verify : bool, optional + Verify SSL certificate if True. Default is False. + dsm_version : int, optional + DSM version. Default is 7. + debug : bool, optional + Enable debug mode. Default is True. + otp_code : str, optional + One-time password for 2FA, if required. + """ super(Virtualization, self).__init__(ip_address, port, username, password, secure, cert_verify, dsm_version, debug, otp_code) @@ -32,6 +90,14 @@ def __init__(self, self.file_station_list: Any = self.session.app_api_list def get_task_list(self) -> list[str]: + """ + Get the list of virtualization tasks. + + Returns + ------- + list of str + List of task IDs. + """ api_name = 'SYNO.Virtualization.API.Task.Info' info = self.file_station_list[api_name] api_path = info['path'] @@ -42,6 +108,19 @@ def get_task_list(self) -> list[str]: return self._taskid_list def clear_task(self, taskid: str) -> dict[str, object] | str: + """ + Clear a specific task by its ID. + + Parameters + ---------- + taskid : str + Task ID to clear. + + Returns + ------- + dict[str, object] or str + Result of the clear operation or error message. + """ api_name = 'SYNO.Virtualization.API.Task.Info' info = self.file_station_list[api_name] api_path = info['path'] @@ -55,6 +134,19 @@ def clear_task(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_task_info(self, taskid: str) -> dict[str, object] | str: + """ + Get information about a specific task. + + Parameters + ---------- + taskid : str + Task ID to retrieve information for. + + Returns + ------- + dict[str, object] or str + Task information or error message. + """ api_name = 'SYNO.Virtualization.API.Task.Info' info = self.file_station_list[api_name] api_path = info['path'] @@ -68,6 +160,14 @@ def get_task_info(self, taskid: str) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def get_network_group_list(self) -> list[dict[str, object]]: + """ + Get the list of network groups. + + Returns + ------- + list of dict + List of network group information. + """ api_name = 'SYNO.Virtualization.API.Network' info = self.file_station_list[api_name] api_path = info['path'] @@ -79,6 +179,14 @@ def get_network_group_list(self) -> list[dict[str, object]]: return self._network_group_list def get_storage_operation(self) -> list[str]: + """ + Get the list of storage operations. + + Returns + ------- + list of str + List of storage operation information. + """ api_name = 'SYNO.Virtualization.API.Storage' info = self.file_station_list[api_name] api_path = info['path'] @@ -89,6 +197,14 @@ def get_storage_operation(self) -> list[str]: return self._storages_list def get_host_operation(self) -> list[str]: + """ + Get the list of host operations. + + Returns + ------- + list of str + List of host operation information. + """ api_name = 'SYNO.Virtualization.API.Host' info = self.file_station_list[api_name] api_path = info['path'] @@ -100,6 +216,19 @@ def get_host_operation(self) -> list[str]: return self._host_operation_list def get_vm_operation(self, additional: bool = False) -> list[dict[str, object]]: + """ + Get the list of virtual machines. + + Parameters + ---------- + additional : bool, optional + Whether to include additional information. Default is False. + + Returns + ------- + list of dict + List of VM information. + """ api_name = 'SYNO.Virtualization.API.Guest' info = self.file_station_list[api_name] api_path = info['path'] @@ -116,11 +245,29 @@ def get_vm_operation(self, additional: bool = False) -> list[dict[str, object]]: return info - def get_specific_vm_info(self, - additional: Optional[str | list[str]] = None, - guest_id: Optional[str] = None, - guest_name: Optional[str] = None - ) -> dict[str, object] | str: + def get_specific_vm_info( + self, + additional: Optional[str | list[str]] = None, + guest_id: Optional[str] = None, + guest_name: Optional[str] = None + ) -> dict[str, object] | str: + """ + Get information about a specific virtual machine. + + Parameters + ---------- + additional : str or list of str, optional + Additional fields to include. + guest_id : str, optional + Guest VM ID. + guest_name : str, optional + Guest VM name. + + Returns + ------- + dict[str, object] or str + VM information or error message. + """ api_name = 'SYNO.Virtualization.API.Guest' info = self.file_station_list[api_name] api_path = info['path'] @@ -137,15 +284,41 @@ def get_specific_vm_info(self, return self.request_data(api_name, api_path, req_param) - def set_vm_property(self, - guest_id: Optional[str] = None, - guest_name: Optional[str] = None, - autorun: Optional[int] = None, - description: Optional[str] = None, - new_guest_name: Optional[str] = None, - vcpu_num: Optional[int] = None, - vram_size: Optional[int] = None - ) -> dict[str, object] | str: + def set_vm_property( + self, + guest_id: Optional[str] = None, + guest_name: Optional[str] = None, + autorun: Optional[int] = None, + description: Optional[str] = None, + new_guest_name: Optional[str] = None, + vcpu_num: Optional[int] = None, + vram_size: Optional[int] = None + ) -> dict[str, object] | str: + """ + Set properties for a virtual machine. + + Parameters + ---------- + guest_id : str, optional + Guest VM ID. + guest_name : str, optional + Guest VM name. + autorun : int, optional + Autorun setting (0: off, 1: last state, 2: on). + description : str, optional + VM description. + new_guest_name : str, optional + New VM name. + vcpu_num : int, optional + Number of virtual CPUs. + vram_size : int, optional + RAM size in MB. + + Returns + ------- + dict[str, object] or str + Result of the set operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest' info = self.file_station_list[api_name] api_path = info['path'] @@ -186,6 +359,21 @@ def set_vm_property(self, return self.request_data(api_name, api_path, req_param) def delete_vm(self, guest_id: Optional[str] = None, guest_name: Optional[str] = None) -> dict[str, object] | str: + """ + Delete a virtual machine. + + Parameters + ---------- + guest_id : str, optional + Guest VM ID. + guest_name : str, optional + Guest VM name. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest' info = self.file_station_list[api_name] api_path = info['path'] @@ -202,12 +390,32 @@ def delete_vm(self, guest_id: Optional[str] = None, guest_name: Optional[str] = return self.request_data(api_name, api_path, req_param) - def vm_power_on(self, - guest_id: Optional[str] = None, - guest_name: Optional[str] = None, - host_id: Optional[str] = None, - host_name: Optional[str] = None - ) -> dict[str, object] | str: + def vm_power_on( + self, + guest_id: Optional[str] = None, + guest_name: Optional[str] = None, + host_id: Optional[str] = None, + host_name: Optional[str] = None + ) -> dict[str, object] | str: + """ + Power on a virtual machine. + + Parameters + ---------- + guest_id : str, optional + Guest VM ID. + guest_name : str, optional + Guest VM name. + host_id : str, optional + Host ID. + host_name : str, optional + Host name. + + Returns + ------- + dict[str, object] or str + Result of the power on operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest.Action' info = self.file_station_list[api_name] api_path = info['path'] @@ -233,10 +441,26 @@ def vm_power_on(self, return self.request_data(api_name, api_path, req_param) - def vm_force_power_off(self, - guest_id: Optional[str] = None, - guest_name: Optional[str] = None - ) -> dict[str, object] | str: + def vm_force_power_off( + self, + guest_id: Optional[str] = None, + guest_name: Optional[str] = None + ) -> dict[str, object] | str: + """ + Force power off a virtual machine. + + Parameters + ---------- + guest_id : str, optional + Guest VM ID. + guest_name : str, optional + Guest VM name. + + Returns + ------- + dict[str, object] or str + Result of the power off operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest.Action' info = self.file_station_list[api_name] api_path = info['path'] @@ -254,6 +478,21 @@ def vm_force_power_off(self, return self.request_data(api_name, api_path, req_param) def vm_shut_down(self, guest_id: Optional[str] = None, guest_name: Optional[str] = None) -> dict[str, object] | str: + """ + Shut down a virtual machine. + + Parameters + ---------- + guest_id : str, optional + Guest VM ID. + guest_name : str, optional + Guest VM name. + + Returns + ------- + dict[str, object] or str + Result of the shutdown operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest.Action' info = self.file_station_list[api_name] api_path = info['path'] @@ -271,6 +510,14 @@ def vm_shut_down(self, guest_id: Optional[str] = None, guest_name: Optional[str] return self.request_data(api_name, api_path, req_param) def get_images_list(self) -> dict[str, object]: + """ + Get the list of VM images. + + Returns + ------- + dict[str, object] + Dictionary containing image information. + """ api_name = 'SYNO.Virtualization.API.Guest.Image' info = self.file_station_list[api_name] api_path = info['path'] @@ -279,6 +526,21 @@ def get_images_list(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def delete_image(self, image_id: Optional[str] = None, image_name: Optional[str] = None) -> dict[str, object] | str: + """ + Delete a VM image. + + Parameters + ---------- + image_id : str, optional + Image ID. + image_name : str, optional + Image name. + + Returns + ------- + dict[str, object] or str + Result of the delete operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest.Image' info = self.file_station_list[api_name] api_path = info['path'] @@ -295,14 +557,38 @@ def delete_image(self, image_id: Optional[str] = None, image_name: Optional[str] return self.request_data(api_name, api_path, req_param) - def create_image(self, - auto_clean_task: bool = True, - storage_names: Optional[str] = None, - storage_ids: Optional[str] = None, - type: Optional[str] = None, - ds_file_path: Optional[str] = None, - image_name: Optional[str] = None - ) -> dict[str, object] | str: + def create_image( + self, + auto_clean_task: bool = True, + storage_names: Optional[str] = None, + storage_ids: Optional[str] = None, + type: Optional[str] = None, + ds_file_path: Optional[str] = None, + image_name: Optional[str] = None + ) -> dict[str, object] | str: + """ + Create a new VM image. + + Parameters + ---------- + auto_clean_task : bool, optional + Whether to auto-clean the task after creation. Default is True. + storage_names : str, optional + Storage names. + storage_ids : str, optional + Storage IDs. + type : str, optional + Image type ('disk', 'vdsm', or 'iso'). + ds_file_path : str, optional + File path (should begin with a shared folder). + image_name : str, optional + Name of the image. + + Returns + ------- + dict[str, object] or str + Result of the create operation or error message. + """ api_name = 'SYNO.Virtualization.API.Guest.Image' info = self.file_station_list[api_name] api_path = info['path'] From c127ab2088b8923c30d8330d5c6453a9461a1c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:10:17 +0700 Subject: [PATCH 046/126] fix: synology_api/vpn.py update docstrings to comply with Numpydoc standards --- synology_api/vpn.py | 125 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 9 deletions(-) diff --git a/synology_api/vpn.py b/synology_api/vpn.py index f33e1d14..93badd51 100644 --- a/synology_api/vpn.py +++ b/synology_api/vpn.py @@ -1,3 +1,4 @@ +"""VPN API Wrapper for Synology NAS.""" from __future__ import annotations from io import BytesIO from zipfile import ZipFile @@ -6,8 +7,22 @@ class VPN(base_api.BaseApi): + """ + API wrapper for Synology VPN Server. + + Provides methods to retrieve VPN settings, active connections, logs, network interfaces, + security autoblock settings, permissions, and VPN protocol-specific settings. + """ def settings_list(self) -> dict[str, object] | str: + """ + Retrieve VPN server settings. + + Returns + ------- + dict[str, object] or str + VPN server settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Settings.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -21,6 +36,25 @@ def active_connections_list(self, start: int = 0, limit: int = 100 ) -> dict[str, object] | str: + """ + Retrieve a list of active VPN connections. + + Parameters + ---------- + sort : str, optional + Field to sort by. Default is 'login_time'. + sort_dir : str, optional + Sort direction ('ASC' or 'DESC'). Default is 'DESC'. + start : int, optional + Pagination start index. Default is 0. + limit : int, optional + Maximum number of results to return. Default is 100. + + Returns + ------- + dict[str, object] or str + Active connections as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Management.Connection' info = self.gen_list[api_name] api_path = info['path'] @@ -30,6 +64,23 @@ def active_connections_list(self, return self.request_data(api_name, api_path, req_param) def log_list(self, start: int = 0, limit: int = 50, prtltype: int = 0) -> dict[str, object] | str: + """ + Retrieve VPN server logs. + + Parameters + ---------- + start : int, optional + Pagination start index. Default is 0. + limit : int, optional + Maximum number of logs to return. Default is 50. + prtltype : int, optional + Protocol type filter. Default is 0 (all). + + Returns + ------- + dict[str, object] or str + Logs as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Management.Log' info = self.gen_list[api_name] api_path = info['path'] @@ -39,6 +90,14 @@ def log_list(self, start: int = 0, limit: int = 50, prtltype: int = 0) -> dict[s return self.request_data(api_name, api_path, req_param) def network_interface_setting(self) -> dict[str, object] | str: + """ + Retrieve VPN network interface settings. + + Returns + ------- + dict[str, object] or str + Network interface settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Management.Interface' info = self.gen_list[api_name] api_path = info['path'] @@ -47,6 +106,14 @@ def network_interface_setting(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def security_autoblock_setting(self) -> dict[str, object] | str: + """ + Retrieve security autoblock settings. + + Returns + ------- + dict[str, object] or str + Autoblock settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.Core.Security.AutoBlock' info = self.gen_list[api_name] api_path = info['path'] @@ -55,6 +122,21 @@ def security_autoblock_setting(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def permission_setting(self, start: int = 0, limit: int = 100) -> dict[str, object] | str: + """ + Retrieve VPN permission settings. + + Parameters + ---------- + start : int, optional + Pagination start index. Default is 0. + limit : int, optional + Maximum number of results to return. Default is 100. + + Returns + ------- + dict[str, object] or str + Permission settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Management.Account' info = self.gen_list[api_name] api_path = info['path'] @@ -64,6 +146,14 @@ def permission_setting(self, start: int = 0, limit: int = 100) -> dict[str, obje return self.request_data(api_name, api_path, req_param) def pptp_settings_info(self) -> dict[str, object] | str: + """ + Retrieve PPTP VPN settings. + + Returns + ------- + dict[str, object] or str + PPTP settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Settings.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -73,6 +163,14 @@ def pptp_settings_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def openvpn_settings_info(self) -> dict[str, object] | str: + """ + Retrieve OpenVPN settings. + + Returns + ------- + dict[str, object] or str + OpenVPN settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Settings.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -82,6 +180,14 @@ def openvpn_settings_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def l2tp_settings_info(self) -> dict[str, object] | str: + """ + Retrieve L2TP VPN settings. + + Returns + ------- + dict[str, object] or str + L2TP settings as a dictionary, or an error message as a string. + """ api_name = 'SYNO.VPNServer.Settings.Config' info = self.gen_list[api_name] api_path = info['path'] @@ -91,17 +197,18 @@ def l2tp_settings_info(self) -> dict[str, object] | str: return self.request_data(api_name, api_path, req_param) def openvpn_export_configuration(self, as_zip_file=False) -> bytes | ZipFile: - """Downloads the openvpn\.zip containing the VPNConfig\.ovpn file + """ + Download the OpenVPN configuration as a zip file or bytes. - Parameters - ---------- - as_zip_file : bool - If the bytes should be converted to a ZipFile + Parameters + ---------- + as_zip_file : bool, optional + If True, return a ZipFile object. If False, return bytes. Default is False. - Returns - ------- - dict[str, object] - A dictionary containing the OpenVPN configuration file as bytes or a ZipFile object if `as_zip_file` is True. + Returns + ------- + bytes or ZipFile + The OpenVPN configuration file as bytes, or a ZipFile object if `as_zip_file` is True. """ api_name = 'SYNO.VPNServer.Settings.Certificate' info = self.gen_list[api_name] From 57e37dea1c64bec59d4f4fe391248bd56f0bce9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:15:57 +0700 Subject: [PATCH 047/126] feat: add GitHub Actions workflow for pre-commit autoupdate --- .github/workflows/pre-commit-autoupdate.yml | 49 +++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 .github/workflows/pre-commit-autoupdate.yml diff --git a/.github/workflows/pre-commit-autoupdate.yml b/.github/workflows/pre-commit-autoupdate.yml new file mode 100644 index 00000000..65dae581 --- /dev/null +++ b/.github/workflows/pre-commit-autoupdate.yml @@ -0,0 +1,49 @@ +name: pre-commit + +permissions: + contents: write + pull-requests: write + +concurrency: + group: pre-commit-${{ github.ref }}-autoupdate + cancel-in-progress: true + +on: + schedule: + - cron: '0 3 * * 1' + workflow_dispatch: + +jobs: + autoupdate: + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache asdf + uses: actions/cache@v4 + with: + path: | + ~/.asdf + key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }} + restore-keys: | + ${{ runner.os }}-asdf- + - uses: asdf-vm/actions/install@v4 + - name: Run pre-commit autoupdate + id: pre_commit_autoupdate + run: | + pre-commit autoupdate + if git diff --quiet ".pre-commit-config.yaml"; then + echo "No changes to commit" + echo "autoupdate=false" >> "$GITHUB_ENV" + exit 0 + fi + echo "autoupdate=true" >> "$GITHUB_ENV" + - name: Create Pull Request + if: success() && steps.pre_commit_autoupdate.outcome == 'success' && env.autoupdate == 'true' + uses: peter-evans/create-pull-request@v7 + with: + title: "chore(pre-commit): autoupdate hooks" + body: "Automated pre-commit autoupdate." + commit-message: "chore(pre-commit): autoupdate hooks" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 43e7808bab241d1d1cc750523f790f047e86d617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:20:35 +0700 Subject: [PATCH 048/126] feat: add pre-commit GitHub Actions workflow for validation --- .github/workflows/pre-commit.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/pre-commit.yml diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml new file mode 100644 index 00000000..71f0488f --- /dev/null +++ b/.github/workflows/pre-commit.yml @@ -0,0 +1,28 @@ +name: pre-commit + +concurrency: + group: pre-commit-${{ github.ref }} + cancel-in-progress: true + +on: + pull_request: + push: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Cache asdf + uses: actions/cache@v4 + with: + path: | + ~/.asdf + key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }} + restore-keys: | + ${{ runner.os }}-asdf- + - uses: asdf-vm/actions/install@v4 + - uses: pre-commit/action@v3.0.1 +# env: +# SKIP: hook-id-to-skip From 87e7af13e24f1ef41488ee969229fb0a7f8f3d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 18:29:06 +0700 Subject: [PATCH 049/126] fix: update Python version in .tool-versions to 3.13.5 --- .tool-versions | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.tool-versions b/.tool-versions index 5761f346..8eb21b90 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,5 +1,5 @@ nodejs 18.18.0 -python 3.9.6 +python 3.13.5 task 3.44.0 shfmt 3.11.0 shellcheck 0.10.0 From 6caad5f798e3a018581692be64ceeaf15cf03fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 22:24:47 +0700 Subject: [PATCH 050/126] feat: specify files for numpydoc validation in pre-commit configuration --- .pre-commit-config.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 70a0b1a9..81a8ef31 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,4 +25,5 @@ repos: rev: v1.9.0 stages: [ pre-commit ] hooks: - - id: numpydoc-validation \ No newline at end of file + - id: numpydoc-validation + files: ^synology_api/ From 2594ae6efc7c127d4fbfc6f6ca66309fdde921ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sat, 12 Jul 2025 22:24:54 +0700 Subject: [PATCH 051/126] feat: add module docstring for Synology API Python Client --- synology_api/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/synology_api/__init__.py b/synology_api/__init__.py index 1f5f8a19..a4c346b4 100755 --- a/synology_api/__init__.py +++ b/synology_api/__init__.py @@ -1,3 +1,4 @@ +"""Synology API Python Client.""" from . import \ audiostation, \ auth, \ From 861e9dba8509509e103e4793735c3ada3d6e2a39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 11:38:54 +0700 Subject: [PATCH 052/126] fix: add pydocstringformatter to development requirements --- requirements-dev.txt | Bin 92 -> 148 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 24c1bd4c29c092f4397f6416ffdfcf3b1b00f6ab..8be12690eec9893f51791754683e49485f95a141 100644 GIT binary patch delta 62 zcma!jTr#80}L7f delta 5 McmbQj7&9RT00n&k-T(jq From a6e6ac9ef676acbe36ffd52290d81391207f4911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 11:43:38 +0700 Subject: [PATCH 053/126] feat: add numpydoc linting and validation tasks to Taskfile --- Taskfile.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Taskfile.yml b/Taskfile.yml index 7dc49a86..3b0cbb13 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -96,3 +96,17 @@ tasks: cmds: - echo "Validating numpydoc format..." - pre-commit run numpydoc-validation -a + + numpydoc-lint: + desc: Lint the numpydoc format of the documentation + dir: '{{.TASKFILE_DIR}}' + cmds: + - echo "Linting numpydoc format..." + - pydocstringformatter -w ./synology_api/ + + numpydoc: + desc: Lint and validate the numpydoc format of the documentation + dir: '{{.TASKFILE_DIR}}' + cmds: + - task: numpydoc-lint + - task: numpydoc-validation From 0dee92e7b48f2b588dbec94a92c78bb433b6a6b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 11:43:47 +0700 Subject: [PATCH 054/126] fix: improve docstring formatting across multiple files --- synology_api/abm.py | 4 +--- synology_api/auth.py | 12 +++--------- synology_api/core_active_backup.py | 8 ++++++-- synology_api/core_share.py | 4 +++- synology_api/directory_server.py | 4 +++- synology_api/exceptions.py | 4 +++- 6 files changed, 19 insertions(+), 17 deletions(-) diff --git a/synology_api/abm.py b/synology_api/abm.py index 41025428..e6304220 100644 --- a/synology_api/abm.py +++ b/synology_api/abm.py @@ -1,6 +1,4 @@ -""" -Active Backup for Microsoft 365 Implementation. -""" +"""Active Backup for Microsoft 365 Implementation.""" from __future__ import annotations import json diff --git a/synology_api/auth.py b/synology_api/auth.py index 32710226..07f6440f 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -1,6 +1,4 @@ -""" -Provides authentication and API request handling for Synology DSM, including session management, encryption utilities, and error handling for various Synology services. -""" +"""Provides authentication and API request handling for Synology DSM, including session management, encryption utilities, and error handling for various Synology services.""" from __future__ import annotations from random import randint from typing import Optional @@ -325,9 +323,7 @@ def get_api_list(self, app: Optional[str] = None) -> None: return def show_api_name_list(self) -> None: - """ - Print the list of available API names. - """ + """Print the list of available API names.""" prev_key = '' for key in self.full_api_list: if key != prev_key: @@ -336,9 +332,7 @@ def show_api_name_list(self) -> None: return def show_json_response_type(self) -> None: - """ - Print API names that return JSON data. - """ + """Print API names that return JSON data.""" for key in self.full_api_list: for sub_key in self.full_api_list[key]: if sub_key == 'requestFormat': diff --git a/synology_api/core_active_backup.py b/synology_api/core_active_backup.py index a826735a..c0e25581 100644 --- a/synology_api/core_active_backup.py +++ b/synology_api/core_active_backup.py @@ -872,7 +872,9 @@ def list_logs( limit: int = 200, ) -> dict[str, object]: """ - Get logs from the package, tasks and devices. From `[Activities -> Log]` screen in ABB. + Get logs from the package, tasks and devices. + + From `[Activities -> Log]` screen in ABB. For specific task logs `[Task List -> Details -> Log]`, specify `task_id` parameter. @@ -1140,7 +1142,9 @@ def result_details( direction: str = "ASC" ) -> dict[str, object]: """ - Get details of a task result log. `result_id` can be retrieved from `list_logs()` function. + Get details of a task result log. + + `result_id` can be retrieved from `list_logs()` function. Parameters ---------- diff --git a/synology_api/core_share.py b/synology_api/core_share.py index 1be08625..fd14c241 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -752,7 +752,9 @@ def verify(self) -> dict: def explore(self) -> dict: """ - Explore KeyManagerStore API. Get list of existing stores. + Explore KeyManagerStore API. + + Get list of existing stores. Returns ------- diff --git a/synology_api/directory_server.py b/synology_api/directory_server.py index 75379cd0..3750f69c 100644 --- a/synology_api/directory_server.py +++ b/synology_api/directory_server.py @@ -468,7 +468,9 @@ def add_user_to_group(self, userDn: str, groupDn: str) -> dict[str, object]: def does_dn_exist(self, groupName: str) -> dict[str, object]: """ - Check if a container exists. This can be used to verify the username or group name is unique. + Check if a container exists. + + This can be used to verify the username or group name is unique. Parameters ---------- diff --git a/synology_api/exceptions.py b/synology_api/exceptions.py index 5653dac2..3fb409e3 100644 --- a/synology_api/exceptions.py +++ b/synology_api/exceptions.py @@ -12,7 +12,9 @@ # Base exception: class SynoBaseException(Exception): """ - Base class for an exception. Defines error_message. + Base class for an exception. + + Defines error_message. Parameters ---------- From bf684c4022719a50165c3e01ea51412409844d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 11:50:03 +0700 Subject: [PATCH 055/126] fix: exclude PR09 check from numpydoc Some parameters that end with examples should not end with a period, otherwise it will break the documentation generation. --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index efa19967..f8e32896 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [tool:numpydoc_validation] ; to ignore some check add them after for example: checks = all,GL02, GL08 -checks = all,SA01,ES01,EX01,RT04 +checks = all,SA01,ES01,EX01,RT04,PR09 exclude = \.undocumented_method$,\.__repr__$ From 0c60a82df49c80e4f1392f9a1c5a209a284ffa09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 11:50:31 +0700 Subject: [PATCH 056/126] fix: correct closing backticks in docstrings across multiple files --- synology_api/abm.py | 2 +- synology_api/cloud_sync.py | 2 +- synology_api/core_active_backup.py | 2 +- synology_api/event_scheduler.py | 4 ++-- synology_api/snapshot.py | 5 ++--- synology_api/task_scheduler.py | 4 ++-- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/synology_api/abm.py b/synology_api/abm.py index e6304220..03961dc6 100644 --- a/synology_api/abm.py +++ b/synology_api/abm.py @@ -733,7 +733,7 @@ def set_task_schedule(self, "repeat_every_hours": 1, "run_days": [0, 1, 2, 3, 4, 5, 6] } - ```. + ``` Returns ------- diff --git a/synology_api/cloud_sync.py b/synology_api/cloud_sync.py index 4ce5aff0..1c90ba07 100644 --- a/synology_api/cloud_sync.py +++ b/synology_api/cloud_sync.py @@ -930,7 +930,7 @@ def set_connection_schedule( '111111111111111111111111', # saturday - hours from 0 to 23 ] set_connection_schedule(conn_id=3, enable=True, schedule_info=days) - ```. + ``` Returns ------- diff --git a/synology_api/core_active_backup.py b/synology_api/core_active_backup.py index c0e25581..eaaa4eb2 100644 --- a/synology_api/core_active_backup.py +++ b/synology_api/core_active_backup.py @@ -338,7 +338,7 @@ def set_traffic_throttle( Example: ```python ["192.168.0.1", "192.168.0.10"] - ```. + ``` Returns ------- diff --git a/synology_api/event_scheduler.py b/synology_api/event_scheduler.py index 1e683fa9..69efe5f0 100644 --- a/synology_api/event_scheduler.py +++ b/synology_api/event_scheduler.py @@ -370,7 +370,7 @@ def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: Lis "min": 59, # Minutes 0-59 "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) } - ```. + ``` poweroff_tasks : List[dict], optional List of tasks for power off. Defaults to `[]`. Example of a task: @@ -381,7 +381,7 @@ def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: Lis "min": 59, # Minutes 0-59 "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) } - ```. + ``` Returns ------- diff --git a/synology_api/snapshot.py b/synology_api/snapshot.py index 80bd45a9..7672247b 100644 --- a/synology_api/snapshot.py +++ b/synology_api/snapshot.py @@ -1119,8 +1119,6 @@ def delete_snapshots_lun(self, snapshot_uuids: list[str]) -> dict[str, object]: Returns ------- dict[str, object] - API response if successful. - If deletion fails, an error code is returned alongside the snapshot uuid: ```json { @@ -1131,7 +1129,8 @@ def delete_snapshots_lun(self, snapshot_uuids: list[str]) -> dict[str, object]: ], "success": true } - ```. + ``` + API response if successful. Notes ----- diff --git a/synology_api/task_scheduler.py b/synology_api/task_scheduler.py index f2e8b9bc..0c6d84ed 100644 --- a/synology_api/task_scheduler.py +++ b/synology_api/task_scheduler.py @@ -1255,7 +1255,7 @@ def create_service_control_task( {'id': 'HyperBackup', 'type': 'package'}, {'id': 'Samba', 'type': 'service'} ] - ```. + ``` action : str The action to apply to the services. Either `'start'` or `'stop'`. @@ -1413,7 +1413,7 @@ def modify_service_control_task( {'id': 'HyperBackup', 'type': 'package'}, {'id': 'Samba', 'type': 'service'} ] - ```. + ``` action : str The action to apply to the services. Either `'start'` or `'stop'`. From 1cc0e9e4a1a86e1c485d488eb2dbd9ab82382f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 12:04:16 +0700 Subject: [PATCH 057/126] fix: escape special characters in docstring examples across multiple files --- synology_api/surveillancestation.py | 18 +++++++++--------- synology_api/task_scheduler.py | 12 ++++++------ 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/synology_api/surveillancestation.py b/synology_api/surveillancestation.py index 1ca96fa6..4570f724 100644 --- a/synology_api/surveillancestation.py +++ b/synology_api/surveillancestation.py @@ -957,7 +957,7 @@ def check_licence_quota(self) -> dict[str, object] | str: api_path = info['path'] req_param = {'version': info['maxVersion'], 'method': 'CheckQuota'} - return self.request_data(api_name, api_path, req_param) + return self.request_data(api_name, api_path, req_param) def format_specific_sd_card(self, camId: Any = None, @@ -3460,7 +3460,7 @@ def set_advanced_setting_logs(self, data : Any, optional List of log type settings to apply. Example: - data=[{"SSLogType":321912835,"enable":1},{"SSLogType":321912836,"enable":0}] + data=\\[\\{"SSLogType":321912835,"enable":1\\},\\{"SSLogType":321912836,"enable":0\\}\\] Returns ------- @@ -3515,7 +3515,7 @@ def check_license_quota(self, camList : Any, optional List of camera information dictionaries. Example: - camList = [{"ip": "10.13.22.141", "model": "DCS-3110", "vendor": "DLink", "port": 80}] + camList = \\[\\{"ip": "10.13.22.141", "model": "DCS-3110", "vendor": "DLink", "port": 80\\}\\] camServerId : int, optional Camera server ID. @@ -6842,10 +6842,10 @@ def save_controller_settings(self, ---------- arrayJson : str, optional JSON string representing controller settings. Example: - [{"enable": true, "id": 97, "name": "ctrler1", "host": "10.13.12.173", "port": 80, + \\[\\{"enable": true, "id": 97, "name": "ctrler1", "host": "10.13.12.173", "port": 80, "model": "A1001", "username": "root", "password": "Q__Q-__-", "time_server": - "SurveillanceStation", "time_zone": "Fiji", "door": [{"id": 231, "name": "FrontDoor", - "enable_cam": true, "cam_ds_id": 0, "cam_id": 13}]}] + "SurveillanceStation", "time_zone": "Fiji", "door": \\[\\{"id": 231, "name": "FrontDoor", + "enable_cam": true, "cam_ds_id": 0, "cam_id": 13\\}\\]\\}\\] Returns ------- @@ -6859,10 +6859,10 @@ def save_controller_settings(self, """arrayJson example: - arrayJson="[{\"enable\":true,\"id\":97,\"name\":\"ctrler1\",\"host\":\"10.13.12.173\",\"port\":80, + arrayJson="\\[\\{\"enable\":true,\"id\":97,\"name\":\"ctrler1\",\"host\":\"10.13.12.173\",\"port\":80, \"model\":\"A1001\",\"username\":\"root\",\"password\":\"Q__Q-__-\",\"time_server\": - \"SurveillanceStation\",\"time_zone\":\"Fiji\",\"door\":[{\"id\":231,\"name\":\"FrontDoor\", - \"enable_cam\":true,\"cam_ds_id\":0,\"cam_id\":13}]}]\" """ + \"SurveillanceStation\",\"time_zone\":\"Fiji\",\"door\":\\[\\{\"id\":231,\"name\":\"FrontDoor\", + \"enable_cam\":true,\"cam_ds_id\":0,\"cam_id\":13\\}\\]\\}\\]\" """ for key, val in locals().items(): if key not in ['self', 'api_name', 'info', 'api_path', 'req_param']: diff --git a/synology_api/task_scheduler.py b/synology_api/task_scheduler.py index 0c6d84ed..2c439c8e 100644 --- a/synology_api/task_scheduler.py +++ b/synology_api/task_scheduler.py @@ -1560,9 +1560,9 @@ def create_recycle_bin_task( Determines what files will be deleted from the recycle bins. Possible values are: - - {"policy": "clean_all"}: Clean all files. - - {"policy": "time", "time": int}: Clean all files older than X days, where X is the value for "time". - - {"policy": "size", "size": int, "sort_type": int}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". + - \\{"policy": "clean_all"\\}: Clean all files. + - \\{"policy": "time", "time": int\\}: Clean all files older than X days, where X is the value for "time". + - \\{"policy": "size", "size": int, "sort_type": int\\}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". Possible values for "sort_type": - 0: Delete bigger files first. @@ -1696,9 +1696,9 @@ def modify_recycle_bin_task( Determines what files will be deleted from the recycle bins. Possible values are: - - {"policy": "clean_all"}: Clean all files. - - {"policy": "time", "time": int}: Clean all files older than X days, where X is the value for "time". - - {"policy": "size", "size": int, "sort_type": int}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". + - \\{"policy": "clean_all"\\}: Clean all files. + - \\{"policy": "time", "time": int\\}: Clean all files older than X days, where X is the value for "time". + - \\{"policy": "size", "size": int, "sort_type": int\\}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". Possible values for "sort_type": - 0: Delete bigger files first. From b911db6c987a7f33b7a93b71871f13caa8e42487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 12:12:13 +0700 Subject: [PATCH 058/126] fix: update test workflow for documentation generation --- .github/workflows/test-deploy.yml | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index 1ca6a8ff..63434564 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -10,23 +10,20 @@ on: - master jobs: - test-deploy: - name: Test deployment + test-docs-gen: + name: Test Docs Generation runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Get Node.js version from .tool-versions - id: node-version - run: echo "NODE_VERSION=$(cat .tool-versions | egrep nodejs | awk '{print $2}' | xargs)" >> $GITHUB_ENV - - uses: actions/setup-node@v4 + - name: Cache asdf + uses: actions/cache@v4 with: - node-version: ${{ env.NODE_VERSION }} - cache: npm - cache-dependency-path: ./documentation/package-lock.json - - - name: Install dependencies - run: npm ci - - name: Test build website - run: npm run build \ No newline at end of file + path: | + ~/.asdf + key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }} + restore-keys: | + ${{ runner.os }}-asdf- + - uses: asdf-vm/actions/install@v4 + - run: task docs From fafc32e45cb04b8ec6d8d588a574d1111bb87745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 12:20:56 +0700 Subject: [PATCH 059/126] fix: add Python dependency installation step in deployment workflow --- .github/workflows/test-deploy.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index 63434564..4a492cf3 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -26,4 +26,9 @@ jobs: restore-keys: | ${{ runner.os }}-asdf- - uses: asdf-vm/actions/install@v4 + - name: Install Python dependencies + run: | + pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-dev.txt - run: task docs From b74054fe0c9d74c81ab31549d0edb3ba0adfbc13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 16:59:21 +0700 Subject: [PATCH 060/126] fix: remove working-directory setting from documentation deployment workflow --- .github/workflows/test-deploy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-deploy.yml index 4a492cf3..9f1a62e6 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-deploy.yml @@ -2,7 +2,6 @@ name: Test deployment defaults: run: shell: bash - working-directory: ./documentation on: pull_request: From 28b7044487ccbc98bf1bc95f09b3183a73fd4433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 19:49:56 +0700 Subject: [PATCH 061/126] fix: rename test-deploy.yml to test-docs.yml and update job name --- .../{test-deploy.yml => test-docs.yml} | 65 +++++++++---------- 1 file changed, 32 insertions(+), 33 deletions(-) rename .github/workflows/{test-deploy.yml => test-docs.yml} (86%) diff --git a/.github/workflows/test-deploy.yml b/.github/workflows/test-docs.yml similarity index 86% rename from .github/workflows/test-deploy.yml rename to .github/workflows/test-docs.yml index 9f1a62e6..924a79ed 100644 --- a/.github/workflows/test-deploy.yml +++ b/.github/workflows/test-docs.yml @@ -1,33 +1,32 @@ -name: Test deployment -defaults: - run: - shell: bash - -on: - pull_request: - branches: - - master - -jobs: - test-docs-gen: - name: Test Docs Generation - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Cache asdf - uses: actions/cache@v4 - with: - path: | - ~/.asdf - key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }} - restore-keys: | - ${{ runner.os }}-asdf- - - uses: asdf-vm/actions/install@v4 - - name: Install Python dependencies - run: | - pip install --upgrade pip - pip install -r requirements.txt - pip install -r requirements-dev.txt - - run: task docs +name: test-docs +defaults: + run: + shell: bash + +on: + pull_request: + branches: + - master + +jobs: + generate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Cache asdf + uses: actions/cache@v4 + with: + path: | + ~/.asdf + key: ${{ runner.os }}-asdf-${{ hashFiles('.tool-versions') }} + restore-keys: | + ${{ runner.os }}-asdf- + - uses: asdf-vm/actions/install@v4 + - name: Install Python dependencies + run: | + pip install --upgrade pip + pip install -r requirements.txt + pip install -r requirements-dev.txt + - run: task docs From eb199c95ca8f85057f56ecf959de2452e640667c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 20:09:26 +0700 Subject: [PATCH 062/126] fix: core_active_backup.py fix docstrings for docs_parser.py --- synology_api/core_active_backup.py | 124 +++++++++++++++-------------- 1 file changed, 64 insertions(+), 60 deletions(-) diff --git a/synology_api/core_active_backup.py b/synology_api/core_active_backup.py index eaaa4eb2..21830afb 100644 --- a/synology_api/core_active_backup.py +++ b/synology_api/core_active_backup.py @@ -874,6 +874,8 @@ def list_logs( """ Get logs from the package, tasks and devices. + Notes + ----- From `[Activities -> Log]` screen in ABB. For specific task logs `[Task List -> Details -> Log]`, specify `task_id` parameter. @@ -1144,75 +1146,77 @@ def result_details( """ Get details of a task result log. - `result_id` can be retrieved from `list_logs()` function. + Parameters + ---------- + result_id : int + ID of the result to get details from. - Parameters - ---------- - result_id : int - ID of the result to get details from. + limit : int, optional + Amount of results to be returned. Defaults to `500`. - limit : int, optional - Amount of results to be returned. Defaults to `500`. + order_by : str, optional + What to order the results by. Defaults to `"log_level"`. - order_by : str, optional - What to order the results by. Defaults to `"log_level"`. + Possible values: + - `"log_level"` + - `"log_time"` - Possible values: - - `"log_level"` - - `"log_time"` + direction : str, optional + Direction of the order. Defaults to `"ASC"`. - direction : str, optional - Direction of the order. Defaults to `"ASC"`. + Possible values: + - `"ASC"` + - `"DESC"` - Possible values: - - `"ASC"` - - `"DESC"` + Returns + ------- + dict[str, object] + Dictionary containing a list of result details. - Returns - ------- - dict[str, object] - Dictionary containing a list of result details. + Notes + ----- + `result_id` can be retrieved from `list_logs()` function. - Examples - -------- - ```json - { - "data": { - "count": 2, - "result_detail_list": [ - { - "error_code": 0, - "log_level": 0, - "log_time": 1741897456, - "log_type": 6002, - "other_params": { - "fs_error": -65, - "os_name": "smb", - "path": "/D", - "task_id": 8 - }, - "result_detail_id": 9526, - "result_id": 592 + Examples + -------- + ```json + { + "data": { + "count": 2, + "result_detail_list": [ + { + "error_code": 0, + "log_level": 0, + "log_time": 1741897456, + "log_type": 6002, + "other_params": { + "fs_error": -65, + "os_name": "smb", + "path": "abc", + "task_id": 8 }, - { - "error_code": 0, - "log_level": 0, - "log_time": 1741897498, - "log_type": 1104, - "other_params": { - "os_name": "smb", - "path": "", - "task_id": 8, - "task_name": "SMB LAPTOP" - }, - "result_detail_id": 9527, - "result_id": 592 - } - ] - }, - "success": true - } - ``` + "result_detail_id": 9526, + "result_id": 592 + }, + { + "error_code": 0, + "log_level": 0, + "log_time": 1741897498, + "log_type": 1104, + "other_params": { + "os_name": "smb", + "path": "", + "task_id": 8, + "task_name": "SMB LAPTOP" + }, + "result_detail_id": 9527, + "result_id": 592 + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.ActiveBackup.Log' info = self.gen_list[api_name] From 721f2254f0e0728b34da53856c2ef5c1d67ff003 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 20:28:40 +0700 Subject: [PATCH 063/126] fix: add --exit-on-warning flag to docs_parser.py for improved error handling --- docs_parser.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs_parser.py b/docs_parser.py index 7ce686ba..0ccf852c 100644 --- a/docs_parser.py +++ b/docs_parser.py @@ -178,6 +178,9 @@ def init_parser() -> argparse.ArgumentParser: parser.add_argument('-e', '--excluded', action='store_true', help='Show a list of the excluded files to parse.') + parser.add_argument('--exit-on-warning', + action='store_true', + help='Exit if a warning is encountered.') return parser @@ -388,13 +391,38 @@ def write(path: str, content: str): f.write(content) +class WarningCatcher: + def __init__(self): + self.warnings = [] + + def __call__(self, message, category, filename, lineno, file=None, line=None): + msg = warnings.formatwarning(message, category, filename, lineno, line) + self.warnings.append(msg) + + def has_warnings(self): + return bool(self.warnings) + + def print_warnings(self): + for w in self.warnings: + print(w, end='') + + def main(): parser = init_parser() files, parse_api_list, parse_docs = validate_args(parser) + # Setup warning catcher + warning_catcher = WarningCatcher() + warnings.showwarning = warning_catcher + # Generation for Getting Started/Supported APIs with all the APIs user per class. supported_apis = gen_supported_apis() + # Check if --exit-on-warning flag is set + exit_on_warning = any(arg in ('--exit-on-warning',) for arg in sys.argv) + + any_warning = False + for file_name in files: doc_content = '' file_path = join(PARSE_DIR, file_name) @@ -427,10 +455,18 @@ def main(): if parse_docs: write(DOCS_DIR + file_name.replace('.py', '.md'), doc_content) print('='*20) + + if warning_catcher.has_warnings(): + any_warning = True + # else: continue to process all files + # Write to md files if the args were set if parse_api_list: write(API_LIST_FILE, supported_apis) + if any_warning and exit_on_warning: + sys.exit(1) + if __name__ == "__main__": main() From 0ba623f8f20fc42736aefc282b844e0fdf9650fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Z=C3=ADma?= Date: Sun, 13 Jul 2025 20:29:29 +0700 Subject: [PATCH 064/126] fix: add --exit-on-warning flag to docs_parser.py in Taskfile.yml for better error handling --- Taskfile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index 3b0cbb13..03b21bf5 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -36,7 +36,7 @@ tasks: dir: '{{.TASKFILE_DIR}}' cmds: - echo "Parsing the documentation files..." - - python3 docs_parser.py -a + - python3 docs_parser.py -a --exit-on-warning docs-build: desc: Build the documentation website From 3a4d5ef15589b563de81aca31a66fc34e6c2803a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Jul 2025 21:30:02 +0000 Subject: [PATCH 065/126] chore(deps): bump on-headers and compression in /documentation Bumps [on-headers](https://github.com/jshttp/on-headers) and [compression](https://github.com/expressjs/compression). These dependencies needed to be updated together. Updates `on-headers` from 1.0.2 to 1.1.0 - [Release notes](https://github.com/jshttp/on-headers/releases) - [Changelog](https://github.com/jshttp/on-headers/blob/master/HISTORY.md) - [Commits](https://github.com/jshttp/on-headers/compare/v1.0.2...v1.1.0) Updates `compression` from 1.7.5 to 1.8.1 - [Release notes](https://github.com/expressjs/compression/releases) - [Changelog](https://github.com/expressjs/compression/blob/master/HISTORY.md) - [Commits](https://github.com/expressjs/compression/compare/1.7.5...v1.8.1) --- updated-dependencies: - dependency-name: on-headers dependency-version: 1.1.0 dependency-type: indirect - dependency-name: compression dependency-version: 1.8.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- documentation/package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index bf0941f1..27151381 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -6434,16 +6434,16 @@ } }, "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", "license": "MIT", "dependencies": { "bytes": "3.1.2", "compressible": "~2.0.18", "debug": "2.6.9", "negotiator": "~0.6.4", - "on-headers": "~1.0.2", + "on-headers": "~1.1.0", "safe-buffer": "5.2.1", "vary": "~1.1.2" }, @@ -13123,9 +13123,9 @@ } }, "node_modules/on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", "license": "MIT", "engines": { "node": ">= 0.8" From bd30001776ded4fc67e71115c89a5752f6b47255 Mon Sep 17 00:00:00 2001 From: kelreeeeey Date: Wed, 13 Aug 2025 22:31:48 +0700 Subject: [PATCH 066/126] add: Recursive constrain to `generate_file_tree` --- synology_api/filestation.py | 61 +++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index 2daac609..b0c99901 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -16,6 +16,7 @@ import tqdm from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor import sys +import warnings from urllib import parse from treelib import Tree from . import base_api @@ -120,7 +121,7 @@ def __init__(self, self.session.get_api_list('FileStation') - self.file_station_list: Any = self.session.app_api_list + self.file_station_list: dict = self.session.app_api_list self.interactive_output: bool = interactive_output @@ -200,7 +201,7 @@ def get_file_list(self, pattern: Optional[str] = None, filetype: Optional[str] = None, goto_path: Optional[str] = None, - additional: Optional[str | list[str]] = None) -> dict[str, object] | str: + additional: Optional[str | list[str]] = None) -> dict[str, object]: """ List files in a folder. @@ -227,7 +228,7 @@ def get_file_list(self, Returns ------- - dict[str, object] or str + dict[str, object] List of files or error message. """ api_name = 'SYNO.FileStation.List' @@ -235,14 +236,14 @@ def get_file_list(self, api_path = info['path'] req_param = {'version': info['maxVersion'], 'method': 'list'} + if not isinstance(folder_path, str): + raise ValueError('Enter a valid folder_path') # break instead of return + for key, val in locals().items(): if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: if val is not None: req_param[str(key)] = val - if folder_path is None: - return 'Enter a valid folder_path' - if filetype is not None: req_param['filetype'] = str(req_param['filetype']).lower() @@ -2150,9 +2151,9 @@ def get_file(self, r.raise_for_status() return io.BytesIO(r.content) - def generate_file_tree(self, folder_path: str, tree: Tree) -> None: + def generate_file_tree(self, folder_path: str, tree: Tree, max_depth: Optional[int] = 1, start_depth: Optional[int] = 0) -> None: """ - Generate the file tree based on the folder path you give. + Recursively generate the file tree based on the folder path you give constrained with You need to create the root node before calling this function. @@ -2162,24 +2163,46 @@ def generate_file_tree(self, folder_path: str, tree: Tree) -> None: Folder path to generate file tree. tree : Tree Instance of the Tree from the `treelib` library. + max_depth : int, optional + Non-negative number of maximum depth of tree generation if node tree is + directory, default to `1` to generate full tree. If `max_depth=0` it + will be equivalent to no recursion + start_depth : int, optional + Non negative number to start to control tree generation default to `0`. + + Returns + ------- + None """ api_name = 'hotfix' # fix for docs_parser.py issue - data: dict = self.get_file_list( + if start_depth < 0: + start_depth = 0 + warnings.warn( + f"`start_depth={start_depth}`. It should not be less or than 0, setting `start_depth` to 0!", + RuntimeWarning, + stacklevel=2 + ) + + assert start_depth <= max_depth, ValueError(f"`start_depth` should not be greater than `max_depth`. Got `{start_depth=}, {max_depth=}`!") + assert isinstance(tree, Tree), ValueError(f"`tree` has to be a type of `treelib.Tree`! Got {type(tree)=}") + + data: dict[str, object] = self.get_file_list( folder_path=folder_path ).get("data") files = data.get("files") - file: dict - for file in files: - file_name: str = file.get("name") - file_path: str = file.get("path") - if file.get("isdir"): - - tree.create_node(file_name, file_path, parent=folder_path) - self.generate_file_tree(file_path, tree) - else: - tree.create_node(file_name, file_path, parent=folder_path) + _file_info_getter = map(lambda x: (x.get('isdir'), x.get('name'), x.get('path')), files) + for isdir, file_name, file_path in _file_info_getter: + if isdir and (start_depth >= max_depth): + tree.create_node(file_name, file_path, parent=folder_path, data={"isdir":isdir, "max_depth":True}) + + elif isdir: + tree.create_node(file_name, file_path, parent=folder_path, data={"isdir":isdir, "max_depth":False}) + self.generate_file_tree(file_path, tree, max_depth, start_depth + 1) + + else: + tree.create_node(file_name, file_path, parent=folder_path, data={"isdir":isdir, "max_depth":False}) # TODO SYNO.FileStation.Thumb to be done From 0dca6c0f02e3e8eb2b1686c04f8d7c53d729efa3 Mon Sep 17 00:00:00 2001 From: kelreeeeey Date: Wed, 13 Aug 2025 22:33:34 +0700 Subject: [PATCH 067/126] add: Type annotation note --- synology_api/filestation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index b0c99901..f9ad492d 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -491,7 +491,7 @@ def stop_search_task(self, taskid: str) -> dict[str, object] | str: req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': self._search_taskid} - if taskid is None: + if taskid is None: # NOTE this is unreachable return 'Enter a valid taskid, choose between ' + str(self._search_taskid_list) self._search_taskid_list.remove(taskid) @@ -2044,7 +2044,7 @@ def get_list_of_all_background_task(self, limit: Optional[int] = None, sort_by: Optional[str] = None, sort_direction: Optional[str] = None, - api_filter: Optional[str] = None + api_filter: Optional[str, list] = None ) -> dict[str, object] | str: """ Get a list of all background tasks. @@ -2077,7 +2077,7 @@ def get_list_of_all_background_task(self, if val is not None: req_param[str(key)] = val - if type(api_filter) is list: + if isinstance(api_filter, list): new_path = [] [new_path.append('"' + x + '"') for x in api_filter] api_filter = new_path From 6fe76fb9f19edbad09109b622efb57d5c10c163a Mon Sep 17 00:00:00 2001 From: kelreeeeey Date: Fri, 15 Aug 2025 17:56:36 +0700 Subject: [PATCH 068/126] fix-precommit-issue: autopep and numpydoc-validation --- synology_api/filestation.py | 49 +++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index f9ad492d..993ca8aa 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -237,7 +237,8 @@ def get_file_list(self, req_param = {'version': info['maxVersion'], 'method': 'list'} if not isinstance(folder_path, str): - raise ValueError('Enter a valid folder_path') # break instead of return + # break instead of return + raise ValueError('Enter a valid folder_path') for key, val in locals().items(): if key not in ['self', 'api_name', 'info', 'api_path', 'req_param', 'additional']: @@ -491,7 +492,7 @@ def stop_search_task(self, taskid: str) -> dict[str, object] | str: req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': self._search_taskid} - if taskid is None: # NOTE this is unreachable + if taskid is None: # NOTE this is unreachable return 'Enter a valid taskid, choose between ' + str(self._search_taskid_list) self._search_taskid_list.remove(taskid) @@ -513,7 +514,7 @@ def stop_all_search_task(self) -> str: req_param = {'version': info['maxVersion'], 'method': 'stop', 'taskid': ''} - assert len(self._search_taskid_list), 'Task list is empty' + \ + assert len(self._search_taskid_list), 'Task list is empty' +\ str(self._search_taskid_list) for task_id in self._search_taskid_list: @@ -2151,9 +2152,13 @@ def get_file(self, r.raise_for_status() return io.BytesIO(r.content) - def generate_file_tree(self, folder_path: str, tree: Tree, max_depth: Optional[int] = 1, start_depth: Optional[int] = 0) -> None: + def generate_file_tree(self, + folder_path: str, + tree: Tree, + max_depth: Optional[int] = 1, + start_depth: Optional[int] = 0) -> None: """ - Recursively generate the file tree based on the folder path you give constrained with + Recursively generate the file tree based on the folder path you give constrained with. You need to create the root node before calling this function. @@ -2164,45 +2169,47 @@ def generate_file_tree(self, folder_path: str, tree: Tree, max_depth: Optional[i tree : Tree Instance of the Tree from the `treelib` library. max_depth : int, optional - Non-negative number of maximum depth of tree generation if node tree is - directory, default to `1` to generate full tree. If `max_depth=0` it - will be equivalent to no recursion + Non-negative number of maximum depth of tree generation if node tree is directory, default to '1' to generate full tree. If 'max_depth=0' it will be equivalent to no recursion. start_depth : int, optional - Non negative number to start to control tree generation default to `0`. - - Returns - ------- - None + Non negative number to start to control tree generation default to '0'. """ api_name = 'hotfix' # fix for docs_parser.py issue if start_depth < 0: start_depth = 0 warnings.warn( - f"`start_depth={start_depth}`. It should not be less or than 0, setting `start_depth` to 0!", + f"'start_depth={start_depth}'. It should not be less or than 0, setting 'start_depth' to 0!", RuntimeWarning, stacklevel=2 ) - assert start_depth <= max_depth, ValueError(f"`start_depth` should not be greater than `max_depth`. Got `{start_depth=}, {max_depth=}`!") - assert isinstance(tree, Tree), ValueError(f"`tree` has to be a type of `treelib.Tree`! Got {type(tree)=}") + assert start_depth <= max_depth, ValueError( + f"'start_depth' should not be greater than 'max_depth'. Got '{start_depth=}, {max_depth=}'") + assert isinstance(tree, Tree), ValueError( + "'tree' has to be a type of 'Tree'") data: dict[str, object] = self.get_file_list( folder_path=folder_path ).get("data") files = data.get("files") - _file_info_getter = map(lambda x: (x.get('isdir'), x.get('name'), x.get('path')), files) + _file_info_getter = map(lambda x: ( + x.get('isdir'), x.get('name'), x.get('path')), files) for isdir, file_name, file_path in _file_info_getter: if isdir and (start_depth >= max_depth): - tree.create_node(file_name, file_path, parent=folder_path, data={"isdir":isdir, "max_depth":True}) + tree.create_node(file_name, file_path, parent=folder_path, data={ + "isdir": isdir, "max_depth": True}) elif isdir: - tree.create_node(file_name, file_path, parent=folder_path, data={"isdir":isdir, "max_depth":False}) - self.generate_file_tree(file_path, tree, max_depth, start_depth + 1) + tree.create_node(file_name, file_path, parent=folder_path, data={ + "isdir": isdir, "max_depth": False}) + self.generate_file_tree( + file_path, tree, max_depth, start_depth + 1) else: - tree.create_node(file_name, file_path, parent=folder_path, data={"isdir":isdir, "max_depth":False}) + tree.create_node(file_name, file_path, parent=folder_path, data={ + "isdir": isdir, "max_depth": False}) + # TODO SYNO.FileStation.Thumb to be done From 45c659d542ac87e228560a0923da173a1fbe7f57 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:20:46 +0200 Subject: [PATCH 069/126] Add: - decrypt_folder - encrypt_folder - export_encryption_key - Add encryption param to create shared foldere --- synology_api/DSM/ControlPanel/SharedFolder.py | 151 +++++++++++++++++- 1 file changed, 149 insertions(+), 2 deletions(-) diff --git a/synology_api/DSM/ControlPanel/SharedFolder.py b/synology_api/DSM/ControlPanel/SharedFolder.py index 46659df1..7bda91c3 100644 --- a/synology_api/DSM/ControlPanel/SharedFolder.py +++ b/synology_api/DSM/ControlPanel/SharedFolder.py @@ -199,6 +199,7 @@ def create_folder(self, enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, hide_unreadable: bool = False, enable_share_cow: bool = False, enable_share_compress: bool = False, share_quota: int = 0, name_org: str = "", + encryption: bool = False, enc_passwd: str = "" ) -> dict: """Create a new shared folder Parameters @@ -235,6 +236,12 @@ def create_folder(self, name_org : str, optional Defaults to `""`. + + encryption : bool, optional + Enable encryption. Defaults to `False`. + + enc_passwd : str, optional + Encrypted password. Defaults to `""`. Returns ------- @@ -273,6 +280,8 @@ def create_folder(self, "hidden": hidden, "hide_unreadable": hide_unreadable, "share_quota": share_quota, + "encryption": encryption, + "enc_passwd": enc_passwd, }) } # If using https don't use encryption @@ -734,6 +743,127 @@ def set_local_group_permissions( return self.request_data(api_name, api_path, req_param) + + def export_encryption_key(self, name: str, password: str) -> dict: + """Export encryption key for a given share. + Parameters + ---------- + name : str + The share name to export the encryption key for. + + password : str + The password to use for exporting the encryption key. + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto.Key" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "export", + "version": info['maxVersion'], + "name": name, + } + + enc_req_param = { + "password": password, + } + # If using https don't use encryption + if self.session._secure: + req_param.update(enc_req_param) + else: + encrypted_params = self.session.encrypt_params(enc_req_param) + req_param.update(encrypted_params) + + return self.request_data(api_name, api_path, req_param, method="post") + + + def decrypt_folder(self, name: str, password: str) -> dict: + """Decrypt a given share. + Parameters + ---------- + name : str + The share name to decrypt. + + password : str + The password to use for decrypting the share. + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "decrypt", + "version": info['maxVersion'], + "name": name, + } + + req_param_encrypted = { + "password": password, + } + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + return self.request_data(api_name, api_path, req_param, method="post") + + def encrypt_folder(self, name: str) -> dict: + """Encrypt a given share. + Parameters + ---------- + name : str + The share name to encrypt. + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "encrypt", + "version": info['maxVersion'], + "name": name, + } + return self.request_data(api_name, api_path, req_param, method="post") + + class KeyManagerStore(base_api.BaseApi): """ Core Share KeyManager Store API implementation. @@ -822,6 +952,24 @@ def explore(self) -> dict: return self.request_data(api_name, api_path, req_param) + def add(self, share_name: str, share_cypher: int, share_password: str) -> dict: + + raise NotImplementedError("This method is not completly implemented yet. API return error 403") + + api_name = "SYNO.Core.Share.KeyManager.Key" + version = self.core_list[api_name]["maxVersion"] + api_path = self.core_list[api_name]["path"] + req_param = { + "version": version, + "method": "add", + "share_name": share_name, + "share_cypher": share_cypher, + "share_password": share_password, + "passphrase": "2PassValidation", + } + + return self.request_data(api_name, api_path, req_param, method="post") + class KeyManagerAutoKey(base_api.BaseApi): """ Core Share KeyManager AutoKey API implementation. @@ -853,5 +1001,4 @@ def list(self) -> dict: "method": "list", } - return self.request_data(api_name, api_path, req_param) - + return self.request_data(api_name, api_path, req_param) \ No newline at end of file From d4b906abab46bba3a534a8600a6d0b3bd1103773 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:32:34 +0200 Subject: [PATCH 070/126] Add: - decrypt_folder - encrypt_folder - encryption params to create folder --- synology_api/core_share.py | 80 +++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index fd14c241..4640c939 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -185,6 +185,7 @@ def create_folder(self, enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, hide_unreadable: bool = False, enable_share_cow: bool = False, enable_share_compress: bool = False, share_quota: int = 0, name_org: str = "", + encryption: bool = False, enc_passwd: str = "" ) -> dict: """ Create a new shared folder. @@ -213,6 +214,10 @@ def create_folder(self, Share quota. Defaults to `0`. name_org : str, optional Defaults to `""`. + encryption : bool, optional + Enable encryption. Defaults to `False`. + enc_passwd : str, optional + Encrypted password. Defaults to `""`. Returns ------- @@ -251,6 +256,8 @@ def create_folder(self, "hidden": hidden, "hide_unreadable": hide_unreadable, "share_quota": share_quota, + "encryption": encryption, + "enc_passwd": enc_passwd, }) } # If using https don't use encryption @@ -378,6 +385,78 @@ def clone(self, return self.request_data(api_name, api_path, req_param, method="post") + def decrypt_folder(self, name: str, password: str) -> dict: + """Decrypt a given share. + Parameters + ---------- + name : str + The share name to decrypt. + password : str + The password to use for decrypting the share. + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "decrypt", + "version": info['maxVersion'], + "name": name, + } + + req_param_encrypted = { + "password": password, + } + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + return self.request_data(api_name, api_path, req_param, method="post") + + def encrypt_folder(self, name: str) -> dict: + """Encrypt a given share. + Parameters + ---------- + name : str + The share name to encrypt. + + Returns + ------- + dict + Success + + Example return + -------------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "encrypt", + "version": info['maxVersion'], + "name": name, + } + return self.request_data(api_name, api_path, req_param, method="post") class SharePermission(base_api.BaseApi): """Core Share Permission API implementation.""" @@ -678,7 +757,6 @@ def set_local_group_permissions( return self.request_data(api_name, api_path, req_param) - class KeyManagerStore(base_api.BaseApi): """Core Share KeyManager Store API implementation.""" From 9f1fff95fc709a2ef90e6a04c771c789ec7355b0 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:39:36 +0200 Subject: [PATCH 071/126] Fixing docstring to pass pre-commit tests --- synology_api/core_share.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index 4640c939..6c4b850e 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -399,8 +399,8 @@ def decrypt_folder(self, name: str, password: str) -> dict: dict Success - Example return - -------------- + Examples + -------- ```json { "success": true @@ -440,8 +440,8 @@ def encrypt_folder(self, name: str) -> dict: dict Success - Example return - -------------- + Examples + -------- ```json { "success": true From a050658dd0844983b93d52b4f62587fb75dfde90 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:41:30 +0200 Subject: [PATCH 072/126] Fix missing new lines in docstrings --- synology_api/core_share.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index 6c4b850e..e11096ed 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -387,6 +387,7 @@ def clone(self, def decrypt_folder(self, name: str, password: str) -> dict: """Decrypt a given share. + Parameters ---------- name : str @@ -430,6 +431,7 @@ def decrypt_folder(self, name: str, password: str) -> dict: def encrypt_folder(self, name: str) -> dict: """Encrypt a given share. + Parameters ---------- name : str From d68f46395ccd18cc7b3b7c4b2addd601669d4436 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:48:16 +0200 Subject: [PATCH 073/126] Docstring fix --- synology_api/core_share.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index e11096ed..c69f998d 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -386,7 +386,8 @@ def clone(self, return self.request_data(api_name, api_path, req_param, method="post") def decrypt_folder(self, name: str, password: str) -> dict: - """Decrypt a given share. + """ + Decrypt a given share. Parameters ---------- @@ -430,7 +431,8 @@ def decrypt_folder(self, name: str, password: str) -> dict: return self.request_data(api_name, api_path, req_param, method="post") def encrypt_folder(self, name: str) -> dict: - """Encrypt a given share. + """ + Encrypt a given share. Parameters ---------- From 2990032eed53a188ec07dde8a601747e5141d3fd Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:50:05 +0200 Subject: [PATCH 074/126] Docstring --- synology_api/core_share.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index c69f998d..bd185217 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -399,7 +399,7 @@ def decrypt_folder(self, name: str, password: str) -> dict: Returns ------- dict - Success + Success. Examples -------- @@ -442,7 +442,7 @@ def encrypt_folder(self, name: str) -> dict: Returns ------- dict - Success + Success. Examples -------- From 2118fcc266ab35e1a61d464065a7d4431362f236 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 00:54:16 +0200 Subject: [PATCH 075/126] Fixing trailing whitespaces and format autopep8 --- synology_api/core_share.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/synology_api/core_share.py b/synology_api/core_share.py index bd185217..62b0a4bb 100644 --- a/synology_api/core_share.py +++ b/synology_api/core_share.py @@ -388,11 +388,11 @@ def clone(self, def decrypt_folder(self, name: str, password: str) -> dict: """ Decrypt a given share. - + Parameters ---------- name : str - The share name to decrypt. + The share name to decrypt. password : str The password to use for decrypting the share. @@ -417,7 +417,7 @@ def decrypt_folder(self, name: str, password: str) -> dict: "version": info['maxVersion'], "name": name, } - + req_param_encrypted = { "password": password, } @@ -427,13 +427,13 @@ def decrypt_folder(self, name: str, password: str) -> dict: else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - + return self.request_data(api_name, api_path, req_param, method="post") - + def encrypt_folder(self, name: str) -> dict: """ Encrypt a given share. - + Parameters ---------- name : str @@ -462,6 +462,7 @@ def encrypt_folder(self, name: str) -> dict: } return self.request_data(api_name, api_path, req_param, method="post") + class SharePermission(base_api.BaseApi): """Core Share Permission API implementation.""" @@ -761,6 +762,7 @@ def set_local_group_permissions( return self.request_data(api_name, api_path, req_param) + class KeyManagerStore(base_api.BaseApi): """Core Share KeyManager Store API implementation.""" From 48f3f69d6351ccb37b7b48e96a13e7b80774dba8 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Tue, 9 Sep 2025 03:22:47 +0200 Subject: [PATCH 076/126] Adding ik_message to the login request to have full access to the Web API even on public IP and in HTTP --- synology_api/auth.py | 73 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index 07f6440f..ac1f362c 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -22,7 +22,10 @@ import base64 import hashlib import urllib - +from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey +import base64 +from noise.connection import NoiseConnection, Keypair +import time USE_EXCEPTIONS: bool = True @@ -128,6 +131,51 @@ def __init__(self, self.full_api_list = {} self.app_api_list = {} + + def get_ik_message(self) -> str: + """ + Get the IK message for authentication. + + Returns + ------- + str + The IK message. + """ + + url = self._base_url + 'entry.cgi/SYNO.API.Auth.UIConfig' + data = { + "api": "SYNO.API.Auth.UIConfig", + "method": "get", + "version": "1" + } + response = requests.post(url, data=data, verify=self._verify) + + # Try to get cookie "_SSID" + if response.status_code != 200: + raise Exception("Failed to access the URL for IK message. Status code: {}".format(response.status_code)) + cookies = response.cookies + if "_SSID" not in cookies: + raise Exception("Cookie '_SSID' not found in the response.") + _SSID_encoded = cookies["_SSID"] + _SSID = self.decode_ssid_cookie(_SSID_encoded) + + private_bytes = X25519PrivateKey.generate().private_bytes_raw() + + noise = NoiseConnection.from_name(b"Noise_IK_25519_ChaChaPoly_BLAKE2b") + noise.set_as_initiator() + noise.set_keypair_from_private_bytes(Keypair.STATIC, private_bytes) + noise.set_keypair_from_public_bytes(Keypair.REMOTE_STATIC, _SSID) + + noise.start_handshake() + + payload = json.dumps({ + "time": int(time.time()), + }).encode('utf-8') + + message = noise.write_message(payload) + ik_message = self.encode_ssid_cookie(message) + + return ik_message def verify_cert_enabled(self) -> bool: """ @@ -157,7 +205,7 @@ def login(self) -> None: """ login_api = 'auth.cgi' params = {'api': "SYNO.API.Auth", 'version': self._version, - 'method': 'login', 'enable_syno_token': 'yes', 'client': 'browser'} + 'method': 'login', 'enable_syno_token': 'yes', 'client': 'browser', 'ik_message': self.get_ik_message()} params_enc = { 'account': self._username, @@ -801,6 +849,27 @@ def _get_error_message(code: int, api_name: str) -> str: else: message = "" % api_name return 'Error {} - {}'.format(code, message) + + @staticmethod + def decode_ssid_cookie(ssid: str) -> bytes: + # Replace '-' with '+' and '_' with '/' + ssid_fixed = ssid.replace('-', '+').replace('_', '/') + # Pad with '=' if needed + padding = '=' * (-len(ssid_fixed) % 4) + ssid_fixed += padding + # Decode base64 + return base64.b64decode(ssid_fixed) + + @staticmethod + def encode_ssid_cookie(ssid_bytes: bytes) -> str: + # Encode to base64 + ssid_b64 = base64.b64encode(ssid_bytes).decode('utf-8') + # Replace '+' with '-' and '/' with '_' + ssid_fixed = ssid_b64.replace('+', '-').replace('/', '_') + # Remove padding '=' + ssid_fixed = ssid_fixed.rstrip('=') + return ssid_fixed + @property def sid(self) -> Optional[str]: From 135480f5bffc35572c9ae8c59f89ca0f6a7407d1 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Thu, 11 Sep 2025 17:42:15 +0200 Subject: [PATCH 077/126] Format document and trim whitespaces Add the 'ik_message' only on DSM version 7 or higher --- synology_api/auth.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index ac1f362c..9249e8f1 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -131,7 +131,7 @@ def __init__(self, self.full_api_list = {} self.app_api_list = {} - + def get_ik_message(self) -> str: """ Get the IK message for authentication. @@ -141,7 +141,7 @@ def get_ik_message(self) -> str: str The IK message. """ - + url = self._base_url + 'entry.cgi/SYNO.API.Auth.UIConfig' data = { "api": "SYNO.API.Auth.UIConfig", @@ -152,7 +152,8 @@ def get_ik_message(self) -> str: # Try to get cookie "_SSID" if response.status_code != 200: - raise Exception("Failed to access the URL for IK message. Status code: {}".format(response.status_code)) + raise Exception("Failed to access the URL for IK message. Status code: {}".format( + response.status_code)) cookies = response.cookies if "_SSID" not in cookies: raise Exception("Cookie '_SSID' not found in the response.") @@ -205,7 +206,10 @@ def login(self) -> None: """ login_api = 'auth.cgi' params = {'api': "SYNO.API.Auth", 'version': self._version, - 'method': 'login', 'enable_syno_token': 'yes', 'client': 'browser', 'ik_message': self.get_ik_message()} + 'method': 'login', 'enable_syno_token': 'yes', 'client': 'browser'} + + if self._version >= 7: + params.update({'ik_message': self.get_ik_message()}) params_enc = { 'account': self._username, @@ -849,7 +853,7 @@ def _get_error_message(code: int, api_name: str) -> str: else: message = "" % api_name return 'Error {} - {}'.format(code, message) - + @staticmethod def decode_ssid_cookie(ssid: str) -> bytes: # Replace '-' with '+' and '_' with '/' @@ -870,7 +874,6 @@ def encode_ssid_cookie(ssid_bytes: bytes) -> str: ssid_fixed = ssid_fixed.rstrip('=') return ssid_fixed - @property def sid(self) -> Optional[str]: """ From 1391e3a4c47dddca4a55cade32a8c20e0a4d5564 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Thu, 11 Sep 2025 17:45:14 +0200 Subject: [PATCH 078/126] Missing docstrings --- synology_api/auth.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/synology_api/auth.py b/synology_api/auth.py index 9249e8f1..9d739042 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -856,6 +856,18 @@ def _get_error_message(code: int, api_name: str) -> str: @staticmethod def decode_ssid_cookie(ssid: str) -> bytes: + """Decode the SSID cookie. + + Parameters + ---------- + ssid : str + The SSID cookie string to decode. + + Returns + ------- + bytes + The decoded SSID cookie. + """ # Replace '-' with '+' and '_' with '/' ssid_fixed = ssid.replace('-', '+').replace('_', '/') # Pad with '=' if needed @@ -866,6 +878,18 @@ def decode_ssid_cookie(ssid: str) -> bytes: @staticmethod def encode_ssid_cookie(ssid_bytes: bytes) -> str: + """Encode the SSID cookie. + + Parameters + ---------- + ssid_bytes : bytes + The SSID cookie bytes to encode. + + Returns + ------- + str + The encoded SSID cookie. + """ # Encode to base64 ssid_b64 = base64.b64encode(ssid_bytes).decode('utf-8') # Replace '+' with '-' and '/' with '_' From 88ee08232d2ab902149fdceefa01b08089634f57 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Thu, 11 Sep 2025 17:47:28 +0200 Subject: [PATCH 079/126] Fix docstring summary and trim whitespaces again --- synology_api/auth.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index 9d739042..02a3f6d1 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -856,13 +856,14 @@ def _get_error_message(code: int, api_name: str) -> str: @staticmethod def decode_ssid_cookie(ssid: str) -> bytes: - """Decode the SSID cookie. + """ + Decode the SSID cookie. Parameters ---------- ssid : str The SSID cookie string to decode. - + Returns ------- bytes @@ -878,7 +879,8 @@ def decode_ssid_cookie(ssid: str) -> bytes: @staticmethod def encode_ssid_cookie(ssid_bytes: bytes) -> str: - """Encode the SSID cookie. + """ + Encode the SSID cookie. Parameters ---------- From 9baf0264607a930ee4214511bde17a53e04c2712 Mon Sep 17 00:00:00 2001 From: FBoissadier <94692115+FBoissadier@users.noreply.github.com> Date: Fri, 12 Sep 2025 14:44:55 +0200 Subject: [PATCH 080/126] Update requirements.txt with new packages and versions Updated cryptography version and added new dependencies. --- requirements.txt | Bin 382 -> 245 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/requirements.txt b/requirements.txt index 9f1d11050f77ce9f9da871b74b8e7fda578b8f54..0b9d0efea6eab2f6977e8821444c9dab46428b58 100644 GIT binary patch literal 245 zcmYk0F%H5o3`O@yISN)t3x&Z0J4mdIB^ZblNN`+SAo_dl<9CK-~% z7&79@z#5EJOpk%Gl*B?~q19^O5d5*J!Q%g7R>>m;L7aoBjXX{_#1@tv%(Y5+5FZe` zUwMiy3;X+JMo;11Nn}I=?F2GWanwf>x*rdl-4=0KP^*vt1qdkNvZ$< literal 382 zcmZ`!%MOA-5bN2*Pr(2p>cN9|O}u)PN00;+c_jMtYC9}?GLxO`ZaZz~{c4e;LywyM z#;VX_!& Date: Sat, 13 Sep 2025 13:51:38 +0200 Subject: [PATCH 081/126] Fix docstrings --- .../DSM/ControlPanel/ApplicationPrivileges.py | 442 ++- synology_api/DSM/ControlPanel/DomainLDAP.py | 359 +- .../DSM/ControlPanel/ExternalAccess.py | 1221 +++--- .../DSM/ControlPanel/ExternalDevices.py | 547 +-- synology_api/DSM/ControlPanel/FileServices.py | 1145 +++--- .../DSM/ControlPanel/HardwarePower.py | 1140 +++--- .../DSM/ControlPanel/IndexingService.py | 443 ++- synology_api/DSM/ControlPanel/InfoCenter.py | 1025 ++--- synology_api/DSM/ControlPanel/LoginPortal.py | 9 +- synology_api/DSM/ControlPanel/Network.py | 1140 +++--- .../DSM/ControlPanel/Notifications.py | 9 +- .../DSM/ControlPanel/RegionalOptions.py | 9 +- synology_api/DSM/ControlPanel/Security.py | 9 +- synology_api/DSM/ControlPanel/SharedFolder.py | 1408 +++---- .../DSM/ControlPanel/SynologyAccount.py | 9 +- .../DSM/ControlPanel/TaskScheduler.py | 9 +- synology_api/DSM/ControlPanel/TerminalSNMP.py | 9 +- .../DSM/ControlPanel/UpdateRestore.py | 9 +- synology_api/DSM/ControlPanel/UserGroup.py | 9 +- synology_api/DSM/ControlPanel/__init__.py | 208 +- synology_api/DSM/Package/FileStation.py | 3492 +++++++++-------- synology_api/DSM/Package/PackageCenter.py | 1547 ++++---- synology_api/DSM/Package/__init__.py | 9 +- synology_api/DSM/__init__.py | 57 +- 24 files changed, 7437 insertions(+), 6827 deletions(-) diff --git a/synology_api/DSM/ControlPanel/ApplicationPrivileges.py b/synology_api/DSM/ControlPanel/ApplicationPrivileges.py index 02900291..9224f438 100644 --- a/synology_api/DSM/ControlPanel/ApplicationPrivileges.py +++ b/synology_api/DSM/ControlPanel/ApplicationPrivileges.py @@ -1,62 +1,71 @@ +""" +Manage application privileges. +""" + from synology_api import base_api import json + class ApplicationPrivileges(base_api.BaseApi): - + """ + Manage application privileges. + """ + def list_all(self, offset: int = 0, limit: int = 20) -> dict: - """List applications privileges. - - Parameters - ---------- - offset : int, optional - Offset in the application list. Defaults to `0` - limit : int, optional - Limit the len of the returned list. Defaults to `20` - - Returns - ------- - dict - List of applications privileges. - - Example return - ---------- - ```json - { - "data": { - "applications": [ - { - "app_id": "SYNO.AFP", - "grant_by_default": true, - "grant_type": [ - "local", - "domain", - "ldap" - ], - "isInternal": true, - "name": "AFP", - "service_type": "modules/LegacyApps", - "supportIP": true - }, - { - "app_id": "SYNO.Desktop", - "grant_by_default": true, - "grant_type": [ - "local", - "domain", - "ldap" - ], - "isInternal": true, - "name": "DSM", - "service_type": "modules/LegacyApps", - "supportIP": true - } - ], - "offset": 0, - "total": 2 - }, - "success": true - } - ``` + """ + List applications privileges. + + Parameters + ---------- + offset : int, optional + Offset in the application list. Defaults to `0` + limit : int, optional + Limit the len of the returned list. Defaults to `20` + + Returns + ------- + dict + List of applications privileges. + + Examples + -------- + ```json + { + "data": { + "applications": [ + { + "app_id": "SYNO.AFP", + "grant_by_default": true, + "grant_type": [ + "local", + "domain", + "ldap" + ], + "isInternal": true, + "name": "AFP", + "service_type": "modules/LegacyApps", + "supportIP": true + }, + { + "app_id": "SYNO.Desktop", + "grant_by_default": true, + "grant_type": [ + "local", + "domain", + "ldap" + ], + "isInternal": true, + "name": "DSM", + "service_type": "modules/LegacyApps", + "supportIP": true + } + ], + "offset": 0, + "total": 2 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.AppPriv.App' info = self.gen_list[api_name] @@ -67,58 +76,59 @@ def list_all(self, offset: int = 0, limit: int = 20) -> dict: 'offset': offset, 'limit': limit } - + return self.request_data(api_name, api_path, req_param) - + def list_entities(self, app_id: str, type: str = "local", filter_type: str = "all", rule_type: str = "user", offset: int = 0, limit: int = 50) -> dict: - """List entities of the specify app_id. - - Parameters - ---------- - app_id : str - Application ID - type : str, optional - Type to filter for rule_type. Defaults to `"local"` - Example: for rule_type = "user", type = "local" - All known values are: `["local"]` - filter_type : str, optional - Filter actual rules. Defaults to `"all"` - All known values are: `["all", "allow", "deny", "any", "custom"]` - rule_type : str, optional - Type of the rule. Defaults to `"user"` - All known values are: `["user", "group"]` - offset : int, optional - Offset in entity list. Defaults to `0` - limit : int, optional - Limit the len of the returned list. Defaults to `50` - - Returns - ------- - dict - Return list of entity available - - Example return - ---------- - ```json - { - "data": { - "offset": 0, - "total": 3, - "users": [ - { - "name": "admin" - }, - { - "name": "guest" - }, - { - "name": "test_api" - } - ] - }, - "success": true - } - ``` + """ + List entities of the specify app_id. + + Parameters + ---------- + app_id : str + Application ID + type : str, optional + Type to filter for rule_type. Defaults to `"local"` + Example: for rule_type = "user", type = "local" + All known values are: `["local"]` + filter_type : str, optional + Filter actual rules. Defaults to `"all"` + All known values are: `["all", "allow", "deny", "any", "custom"]` + rule_type : str, optional + Type of the rule. Defaults to `"user"` + All known values are: `["user", "group"]` + offset : int, optional + Offset in entity list. Defaults to `0` + limit : int, optional + Limit the len of the returned list. Defaults to `50` + + Returns + ------- + dict + Return list of entity available. + + Examples + -------- + ```json + { + "data": { + "offset": 0, + "total": 3, + "users": [ + { + "name": "admin" + }, + { + "name": "guest" + }, + { + "name": "test_api" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.AppPriv' info = self.gen_list[api_name] @@ -134,61 +144,62 @@ def list_entities(self, app_id: str, type: str = "local", filter_type: str = "al 'filter_type': filter_type, 'rule_type': rule_type } - + return self.request_data(api_name, api_path, req_param) - + def list_app_rules(self, app_id: str) -> dict: - """Retrieve application rules. - - Parameters - ---------- - app_id : str - Application ID - - Returns - ------- - dict - List of rules - - Example return - ---------- - ```json - "data": { - "rules": [ - { - "allow_ip": [ - "0.0.0.0" - ], - "app_id": "SYNO.AFP", - "deny_ip": [], - "entity_name": "everyone", - "entity_type": "everyone" - }, - { - "allow_ip": [ - "0.0.0.0" - ], - "app_id": "SYNO.AFP", - "deny_ip": [], - "entity_name": "test_api", - "entity_type": "user" - }, - { - "allow_ip": [ - "0.0.0.0" - ], - "app_id": "SYNO.AFP", - "deny_ip": [], - "entity_name": "test_group", - "entity_type": "group" - } - ] - }, - "success": true - } - ``` """ - + Retrieve application rules. + + Parameters + ---------- + app_id : str + Application ID + + Returns + ------- + dict + List of rules. + + Examples + -------- + ```json + "data": { + "rules": [ + { + "allow_ip": [ + "0.0.0.0" + ], + "app_id": "SYNO.AFP", + "deny_ip": [], + "entity_name": "everyone", + "entity_type": "everyone" + }, + { + "allow_ip": [ + "0.0.0.0" + ], + "app_id": "SYNO.AFP", + "deny_ip": [], + "entity_name": "test_api", + "entity_type": "user" + }, + { + "allow_ip": [ + "0.0.0.0" + ], + "app_id": "SYNO.AFP", + "deny_ip": [], + "entity_name": "test_group", + "entity_type": "group" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.AppPriv.Rule' info = self.gen_list[api_name] api_path = info['path'] @@ -197,42 +208,43 @@ def list_app_rules(self, app_id: str) -> dict: 'method': 'list', 'app_id': app_id } - + return self.request_data(api_name, api_path, req_param) - + def set_app_rules(self, app_id: str, rules: list) -> dict: - """Set application rules. - - Parameters - ---------- - app_id : str - Application ID - rules : list - List of rules, a rule is a dict with the following keys: - ```json - { - "entity_type":"user", - "entity_name":"test_api", - "app_id":"SYNO.AFP", - "allow_ip":["0.0.0.0"], - "deny_ip":[] - } - ``` + """ + Set application rules. - Returns - ------- - dict - Success - - Example return - ---------- + Parameters + ---------- + app_id : str + Application ID + rules : list + List of rules, a rule is a dict with the following keys: ```json { - "success": true + "entity_type":"user", + "entity_name":"test_api", + "app_id":"SYNO.AFP", + "allow_ip":["0.0.0.0"], + "deny_ip":[] } ``` + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ - + api_name = 'SYNO.Core.AppPriv.Rule' info = self.gen_list[api_name] api_path = info['path'] @@ -242,42 +254,43 @@ def set_app_rules(self, app_id: str, rules: list) -> dict: 'app_id': app_id, 'rules': json.dumps(rules) } - + return self.request_data(api_name, api_path, req_param) - + def delete_app_rules(self, app_id: str, rules: list) -> dict: - """Delete application rules. - - Parameters - ---------- - app_id : str - Application ID - rules : list - List of rules, a rule is a dict with the following keys: - ```json - { - "entity_type":"user", - "entity_name":"test_api", - "app_id":"SYNO.AFP", - "allow_ip":["0.0.0.0"], - "deny_ip":[] - } - ``` + """ + Delete application rules. - Returns - ------- - dict - Success - - Example return - ---------- + Parameters + ---------- + app_id : str + Application ID + rules : list + List of rules, a rule is a dict with the following keys: ```json { - "success": true + "entity_type":"user", + "entity_name":"test_api", + "app_id":"SYNO.AFP", + "allow_ip":["0.0.0.0"], + "deny_ip":[] } ``` + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ - + api_name = 'SYNO.Core.AppPriv.Rule' info = self.gen_list[api_name] api_path = info['path'] @@ -287,8 +300,5 @@ def delete_app_rules(self, app_id: str, rules: list) -> dict: 'app_id': app_id, 'rules': json.dumps(rules) } - + return self.request_data(api_name, api_path, req_param) - - - \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/DomainLDAP.py b/synology_api/DSM/ControlPanel/DomainLDAP.py index 03d15558..3edf8ffd 100644 --- a/synology_api/DSM/ControlPanel/DomainLDAP.py +++ b/synology_api/DSM/ControlPanel/DomainLDAP.py @@ -1,39 +1,48 @@ +""" +Manage Domain and LDAP settings. +""" + from synology_api import base_api + class DomainLDAP(base_api.BaseApi): - + """ + Manage Domain and LDAP settings. + """ + def get_ldap_info(self) -> dict: - """Get LDAP information - - Returns - ------- - dict - Informations about LDAP settings - - Example return - ---------- - ```json - { - "data": { - "base_dn": "dc=test_api,dc=dev", - "enable_cifs": false, - "enable_cifs_pam": false, - "enable_client": false, - "enable_client_certificate": false, - "enable_idmap": false, - "encryption": "no", - "error": 2703, - "expand_nested_groups": true, - "is_syno_server": false, - "ldap_schema": "rfc2307bis", - "nested_group_level": 5, - "profile": "standard", - "server_address": "127.0.0.1", - "tls_reqcert": false, - "update_min": 60 - }, - "success": true, - ``` + """ + Get LDAP information. + + Returns + ------- + dict + Informations about LDAP settings. + + Examples + -------- + ```json + { + "data": { + "base_dn": "dc=test_api,dc=dev", + "enable_cifs": false, + "enable_cifs_pam": false, + "enable_client": false, + "enable_client_certificate": false, + "enable_idmap": false, + "encryption": "no", + "error": 2703, + "expand_nested_groups": true, + "is_syno_server": false, + "ldap_schema": "rfc2307bis", + "nested_group_level": 5, + "profile": "standard", + "server_address": "127.0.0.1", + "tls_reqcert": false, + "update_min": 60 + }, + "success": true, + ``` """ api_name = 'SYNO.Core.Directory.LDAP' @@ -43,29 +52,30 @@ def get_ldap_info(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) def get_domain_info(self) -> dict: - """Get domain info - - Returns - ------- - dict - Informations about domain - - Example return - ---------- - ```json - { - "data": { - "enable_domain": false - }, - "success": true, - } - ``` """ - + Get domain info. + + Returns + ------- + dict + Informations about domain settings. + + Examples + -------- + ```json + { + "data": { + "enable_domain": false + }, + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.Directory.Domain' info = self.gen_list[api_name] api_path = info['path'] @@ -73,29 +83,30 @@ def get_domain_info(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) def get_sso_login_settings(self) -> dict: - """Get SSO login settings - - Returns - ------- - dict - Informations about SSO login settings - - Example return - ---------- - ```json - { - "data": { - "sso_default_login": false - }, - "success": true, - } - ``` """ - + Get SSO login settings. + + Returns + ------- + dict + Informations about SSO login settings. + + Examples + -------- + ```json + { + "data": { + "sso_default_login": false + }, + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.Directory.SSO.Setting' info = self.gen_list[api_name] api_path = info['path'] @@ -103,35 +114,36 @@ def get_sso_login_settings(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) - + def get_synology_sso_settings(self) -> dict: - """Get Synology SSO service settings - - Returns - ------- - dict - Informations about Synology SSO service settings - - Example return - ---------- - ```json - { - "data": { - "allow_local_user": true, - "appid": "", - "enable_sso": false, - "host": "", - "name": "Synology SSO", - "pingpong": null, - "sso_default_login": false - }, - "success": true - } - ``` """ - + Get Synology SSO service settings. + + Returns + ------- + dict + Informations about Synology SSO service settings. + + Examples + -------- + ```json + { + "data": { + "allow_local_user": true, + "appid": "", + "enable_sso": false, + "host": "", + "name": "Synology SSO", + "pingpong": null, + "sso_default_login": false + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Directory.SSO' info = self.gen_list[api_name] api_path = info['path'] @@ -139,30 +151,31 @@ def get_synology_sso_settings(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) - + def get_sso_profile(self) -> dict: - """Get SSO profile - - Returns - ------- - dict - Informations about SSO profile - - Example return - ---------- - ```json - { - "data": { - "sso_enable": false, - "sso_profile": "" - }, - "success": true - } - ``` """ - + Get SSO profile. + + Returns + ------- + dict + Informations about SSO profile. + + Examples + -------- + ```json + { + "data": { + "sso_enable": false, + "sso_profile": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Directory.SSO.Profile' info = self.gen_list[api_name] api_path = info['path'] @@ -170,37 +183,38 @@ def get_sso_profile(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) - + def get_sam_sso_settings(self) -> dict: - """Get SAM SSO settings - - Returns - ------- - dict - Informations about SAM SSO settings - - Example return - ---------- - ```json - { - "data": { - "saml_allow_local_user": false, - "saml_cert_detail": "", - "saml_idp_entity_id": "", - "saml_idp_signin_url": "", - "saml_name": "SAML", - "saml_response_signature": "response", - "saml_system_date": "", - "saml_valid_date": "", - "sso_saml_enable": "" - }, - "success": true - } - ``` """ - + Get SAM SSO settings. + + Returns + ------- + dict + Informations about SAM SSO settings. + + Examples + -------- + ```json + { + "data": { + "saml_allow_local_user": false, + "saml_cert_detail": "", + "saml_idp_entity_id": "", + "saml_idp_signin_url": "", + "saml_name": "SAML", + "saml_response_signature": "response", + "saml_system_date": "", + "saml_valid_date": "", + "sso_saml_enable": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Directory.SSO.SAM' info = self.gen_list[api_name] api_path = info['path'] @@ -208,34 +222,35 @@ def get_sam_sso_settings(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) - + def get_cas_sso_settings(self) -> dict: - """Get CAS SSO settings - - Returns - ------- - dict - Informations about CAS SSO settings - - Example return - ---------- - ```json - { - "data": { - "cas_allow_local_user": true, - "cas_auth_url": "", - "cas_name": "CAS", - "cas_service_ids": "", - "cas_validate_url": "", - "sso_cas_enable": "" - }, - "success": true - } - ``` """ - + Get CAS SSO settings. + + Returns + ------- + dict + Informations about CAS SSO settings. + + Examples + -------- + ```json + { + "data": { + "cas_allow_local_user": true, + "cas_auth_url": "", + "cas_name": "CAS", + "cas_service_ids": "", + "cas_validate_url": "", + "sso_cas_enable": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Directory.SSO.CAS' info = self.gen_list[api_name] api_path = info['path'] @@ -243,7 +258,5 @@ def get_cas_sso_settings(self) -> dict: 'version': info['maxVersion'], 'method': 'get' } - + return self.request_data(api_name, api_path, req_param) - - \ No newline at end of file diff --git a/synology_api/DSM/ControlPanel/ExternalAccess.py b/synology_api/DSM/ControlPanel/ExternalAccess.py index 95d61d3a..c3aa6c6a 100644 --- a/synology_api/DSM/ControlPanel/ExternalAccess.py +++ b/synology_api/DSM/ControlPanel/ExternalAccess.py @@ -1,9 +1,13 @@ +""" +External access class for Synology DSM. +""" from synology_api import base_api + class ExternalAccess(base_api.BaseApi): """ External access class for interacting with Synology DSM External Access settings. - + Supported methods: - Getters: - get_ddns_provider_list @@ -29,39 +33,39 @@ class ExternalAccess(base_api.BaseApi): - set_quickconnect_enable - set_router_config - set_advanced_external_access - """ - + def get_ddns_provider_list(self) -> dict: - """Get the list of DDNS providers. - - Returns - ------- - dict - List of ddns provider. - - Example return - ---------- - ```json - { - "data": { - "providers": - [ - { - "id": "Synology", - "provider": "Synology", - "website": "https://account.synology.com" - }, - { - "id": "Oray.com", - "provider": "Oray.com", - "website": "" - } - ] - } - }, - "success": true - ``` + """ + Get the list of DDNS providers. + + Returns + ------- + dict + List of ddns provider. + + Examples + -------- + ```json + { + "data": { + "providers": + [ + { + "id": "Synology", + "provider": "Synology", + "website": "https://account.synology.com" + }, + { + "id": "Oray.com", + "provider": "Oray.com", + "website": "" + } + ] + } + }, + "success": true + ``` """ api_name = 'SYNO.Core.DDNS.Provider' info = self.gen_list[api_name] @@ -71,26 +75,27 @@ def get_ddns_provider_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_ddns_record_list(self) -> dict: - """Get the list of DDNS records. - - Returns - ------- - dict - List of ddns record. - - Example return - ---------- - ```json - { - "data": { - "next_update_time": "", - "records": [] - }, - "success": true - } - ``` + """ + Get the list of DDNS records. + + Returns + ------- + dict + List of ddns record. + + Examples + -------- + ```json + { + "data": { + "next_update_time": "", + "records": [] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.DDNS.Record' info = self.gen_list[api_name] @@ -100,29 +105,30 @@ def get_ddns_record_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_external_ip_list(self) -> dict: - """Get the list of external IP addresses. - - Returns - ------- - dict - List of external IP addresses. - - Example return - ---------- - ```json - { - "data": [ - { - "ip": "XXX.XXX.XXX.XXX", - "ipv6": "cf92:1469:123f:219f:73af:319a:1c77:181e", - "type": "WAN" - } - ], - "success": true - } - ``` + """ + Get the list of external IP addresses. + + Returns + ------- + dict + List of external IP addresses. + + Examples + -------- + ```json + { + "data": [ + { + "ip": "XXX.XXX.XXX.XXX", + "ipv6": "cf92:1469:123f:219f:73af:319a:1c77:181e", + "type": "WAN" + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.DDNS.ExtIP' info = self.gen_list[api_name] @@ -132,25 +138,26 @@ def get_external_ip_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_ddns_synology_account(self) -> dict: - """Get the Synology DDNS account email. - - Returns - ------- - dict - Synology DDNS account email. - - Example return - ---------- - ```json - { - "data": { - "email": "YOUR_EMAIL", - }, - "success": true - } - ``` + """ + Get the Synology DDNS account email. + + Returns + ------- + dict + Synology DDNS account email. + + Examples + -------- + ```json + { + "data": { + "email": "YOUR_EMAIL", + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.DDNS.Synology' info = self.gen_list[api_name] @@ -160,69 +167,70 @@ def get_ddns_synology_account(self) -> dict: 'method': 'get_myds_account' } return self.request_data(api_name, api_path, req_param) - + def get_certificate_list(self) -> dict: - """Get the list of certificates. - - Returns - ------- - dict - List of certificates. - - Example return - ---------- - ```json - { - "data": { - "certificates": [ - { - "desc": "", - "id": "C6meKD", - "is_broken": false, - "is_default": false, + """ + Get the list of certificates. + + Returns + ------- + dict + List of certificates. + + Examples + -------- + ```json + { + "data": { + "certificates": [ + { + "desc": "", + "id": "C6meKD", + "is_broken": false, + "is_default": false, + "issuer": { + "city": "Taipel", + "common_name": "Synology Inc. CA", + "country": "TW", + "organization": "Synology Inc." + }, + "key_types": "", + "renewable": false, + "self_signed_cacrt_info": { "issuer": { - "city": "Taipel", - "common_name": "Synology Inc. CA", - "country": "TW", - "organization": "Synology Inc." - }, - "key_types": "", - "renewable": false, - "self_signed_cacrt_info": { - "issuer": { - "city": "Taipel", - "common_name": "Synology Inc. CA", - "country": "TW", - "organization": "Synology Inc." - }, - "subject": { - "city": "Taipel", - "common_name": "Synology Inc. CA", - "country": "TW", - "organization": "Synology Inc." - } + "city": "Taipel", + "common_name": "Synology Inc. CA", + "country": "TW", + "organization": "Synology Inc." }, - "services": [], - "signature_algorithm": "sha256WithRSAEncryption", "subject": { - "city": "Taipel", - "common_name": "synology", - "country": "TW", - "organization": "Synology Inc.", - "sub_alt_name": [ - "synology" - ] - }, - "user_deletable": true, - "valid_from": "Nov 4 12:33:40 2024 GMT", - "valid_till": "Nov 5 12:33:40 2025 GMT" + "city": "Taipel", + "common_name": "Synology Inc. CA", + "country": "TW", + "organization": "Synology Inc." } + }, + "services": [], + "signature_algorithm": "sha256WithRSAEncryption", + "subject": { + "city": "Taipel", + "common_name": "synology", + "country": "TW", + "organization": "Synology Inc.", + "sub_alt_name": [ + "synology" + ] + }, + "user_deletable": true, + "valid_from": "Nov 4 12:33:40 2024 GMT", + "valid_till": "Nov 5 12:33:40 2025 GMT" } - ] - }, - "success": true - } - ``` + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Certificate.CRT' info = self.gen_list[api_name] @@ -232,36 +240,37 @@ def get_certificate_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_ethernet_port_list(self) -> dict: - """Get the list of ethernet ports. - - Returns - ------- - dict - List of ethernet ports. - - Example return - ---------- - ```json - { - "data": [ - { - "ifname": "ovs_eth0", - "ip": "XXX.XXX.XXX.XXX", - "ipv6": [ - "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX" - ] - }, - { - "ifname": "ovs_eth1", - "ip": "XXX.XXX.XXX.XXX", - "ipv6": [] - } - ], - "success": true - } - ``` + """ + Get the list of ethernet ports. + + Returns + ------- + dict + List of ethernet ports. + + Examples + -------- + ```json + { + "data": [ + { + "ifname": "ovs_eth0", + "ip": "XXX.XXX.XXX.XXX", + "ipv6": [ + "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX" + ] + }, + { + "ifname": "ovs_eth1", + "ip": "XXX.XXX.XXX.XXX", + "ipv6": [] + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.DDNS.Ethernet' info = self.gen_list[api_name] @@ -271,31 +280,32 @@ def get_ethernet_port_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_quickconnect_info(self) -> dict: - """Get the QuickConnect information. - - Returns - ------- - dict - QuickConnect information. - - Example return - ---------- - ```json - { - "data": { - "ddns_domain": "direct.quickconnect.to", - "domain": "quickconnect.to", - "enabled": false, - "myds_account": "YOUR_MYDS_ACCOUNT", - "region": "fr", - "server_alias": "YOUR_SERVER_ALIAS", - "server_id": "" - }, - "success": true - } - ``` + """ + Get the QuickConnect information. + + Returns + ------- + dict + QuickConnect information. + + Examples + -------- + ```json + { + "data": { + "ddns_domain": "direct.quickconnect.to", + "domain": "quickconnect.to", + "enabled": false, + "myds_account": "YOUR_MYDS_ACCOUNT", + "region": "fr", + "server_alias": "YOUR_SERVER_ALIAS", + "server_id": "" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.QuickConnect' info = self.gen_list[api_name] @@ -305,26 +315,27 @@ def get_quickconnect_info(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_quickconnect_status(self) -> dict: - """Get the QuickConnect status. - - Returns - ------- - dict - QuickConnect status. - - Example return - ---------- - ```json - { - "data": { - "alias_status": "success", - "status": "not_running" - }, - "success": true - } - ``` + """ + Get the QuickConnect status. + + Returns + ------- + dict + QuickConnect status. + + Examples + -------- + ```json + { + "data": { + "alias_status": "success", + "status": "not_running" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.QuickConnect' info = self.gen_list[api_name] @@ -334,42 +345,43 @@ def get_quickconnect_status(self) -> dict: 'method': 'status' } return self.request_data(api_name, api_path, req_param) - + def get_quickconnect_permission(self) -> dict: - """Get the QuickConnect permission. - - Returns - ------- - dict - QuickConnect permission. - - Example return - ---------- - ```json - { - "data": { - "services": [ - { - "enabled": true, - "id": "mobile_apps" - }, - { - "enabled": true, - "id": "cloudstation" - }, - { - "enabled": true, - "id": "file_sharing" - }, - { - "enabled": true, - "id": "dsm_portal" - } - ] - }, - "success": true - } - ``` + """ + Get the QuickConnect permission. + + Returns + ------- + dict + QuickConnect permission. + + Examples + -------- + ```json + { + "data": { + "services": [ + { + "enabled": true, + "id": "mobile_apps" + }, + { + "enabled": true, + "id": "cloudstation" + }, + { + "enabled": true, + "id": "file_sharing" + }, + { + "enabled": true, + "id": "dsm_portal" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.QuickConnect.Permission' info = self.gen_list[api_name] @@ -379,27 +391,28 @@ def get_quickconnect_permission(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def check_quickconnect_availability(self) -> dict: - """Check the availability of QuickConnect. - - Returns - ------- - dict - Availability status of QuickConnect. - - Example return - ---------- - ```json - { - "data": { - "available": true, - "code": 2908, - "country": "FR" - }, - "success": true - } - ``` + """ + Check the availability of QuickConnect. + + Returns + ------- + dict + Availability status of QuickConnect. + + Examples + -------- + ```json + { + "data": { + "available": true, + "code": 2908, + "country": "FR" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.QuickConnect' info = self.gen_list[api_name] @@ -409,25 +422,26 @@ def check_quickconnect_availability(self) -> dict: 'method': 'check_availability' } return self.request_data(api_name, api_path, req_param) - + def get_quickconnect_misc_config(self) -> dict: - """Get the QuickConnect miscellaneous configuration. - - Returns - ------- - dict - QuickConnect miscellaneous configuration. - - Example return - ---------- - ```json - { - "data": { - "relay_enabled": true - }, - "success": true - } - ``` + """ + Get the QuickConnect miscellaneous configuration. + + Returns + ------- + dict + QuickConnect miscellaneous configuration. + + Examples + -------- + ```json + { + "data": { + "relay_enabled": true + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.QuickConnect' info = self.gen_list[api_name] @@ -437,27 +451,28 @@ def get_quickconnect_misc_config(self) -> dict: 'method': 'get_misc_config' } return self.request_data(api_name, api_path, req_param) - + def set_quickconnect_server_alias(self, server_alias: str) -> dict: - """Set the QuickConnect server alias. - - Parameters - ---------- - server_alias : str - The server alias to set. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true, - } - ``` + """ + Set the QuickConnect server alias. + + Parameters + ---------- + server_alias : str + The server alias to set. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true, + } + ``` """ api_name = 'SYNO.Core.QuickConnect' info = self.gen_list[api_name] @@ -468,27 +483,28 @@ def set_quickconnect_server_alias(self, server_alias: str) -> dict: 'server_alias': server_alias } return self.request_data(api_name, api_path, req_param) - + def set_quickconnect_enable(self, enable: bool) -> dict: - """Enable or disable QuickConnect. - - Parameters - ---------- - enable : bool - True to enable, False to disable. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true, - } - ``` + """ + Enable or disable QuickConnect. + + Parameters + ---------- + enable : bool + True to enable, False to disable. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true, + } + ``` """ api_name = 'SYNO.Core.QuickConnect' info = self.gen_list[api_name] @@ -499,25 +515,26 @@ def set_quickconnect_enable(self, enable: bool) -> dict: 'enable': enable } return self.request_data(api_name, api_path, req_param) - + def get_detect_router_information_task(self) -> dict: - """Get the task information for detecting router. - - Returns - ------- - dict - Task information for detecting router. - - Example return - ---------- - ```json - { - "data": { - "task_id": "@administrators/SYNO.Core.PortForwarding.detect174570013646DCEDAC" - }, - "success": true - } - ``` + """ + Get the task information for detecting router. + + Returns + ------- + dict + Task information for detecting router. + + Examples + -------- + ```json + { + "data": { + "task_id": "@administrators/SYNO.Core.PortForwarding.detect174570013646DCEDAC" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.PortForwarding' info = self.gen_list[api_name] @@ -527,57 +544,58 @@ def get_detect_router_information_task(self) -> dict: 'method': 'detect' } return self.request_data(api_name, api_path, req_param) - + def get_detect_router_information_status(self, task_id: str) -> dict: - """Get the status of the task for detecting router. - - Parameters - ---------- - task_id : str - The task ID to check the status of. - - Returns - ------- - dict - Status of the task for detecting router. - - Example return - ---------- - ```json - { - "data": { - "percentage": 30, - "progress": { - "check_connect_wan_step": { - "check_id": 3, - "status": "initial" - }, - "check_dns_setting_step": { - "check_id": 5, - "status": "initial" - }, - "check_gateway_setting_step": { - "check_id": 2, - "status": "processing" - }, - "check_hops_lan2wan_step": { - "check_id": 4, - "status": "initial" - }, - "check_interface_enable_step": { - "check_id": 1, - "network_interface": "ovs_eth0", - "status": "success" - }, - "detect_router_step": { - "check_id": 6, - "status": "initial" - } + """ + Get the status of the task for detecting router. + + Parameters + ---------- + task_id : str + The task ID to check the status of. + + Returns + ------- + dict + Status of the task for detecting router. + + Examples + -------- + ```json + { + "data": { + "percentage": 30, + "progress": { + "check_connect_wan_step": { + "check_id": 3, + "status": "initial" + }, + "check_dns_setting_step": { + "check_id": 5, + "status": "initial" + }, + "check_gateway_setting_step": { + "check_id": 2, + "status": "processing" + }, + "check_hops_lan2wan_step": { + "check_id": 4, + "status": "initial" + }, + "check_interface_enable_step": { + "check_id": 1, + "network_interface": "ovs_eth0", + "status": "success" + }, + "detect_router_step": { + "check_id": 6, + "status": "initial" } - }, - "success": true - } - ``` + } + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.PortForwarding' info = self.gen_list[api_name] @@ -588,38 +606,39 @@ def get_detect_router_information_status(self, task_id: str) -> dict: 'task_id': task_id } return self.request_data(api_name, api_path, req_param) - + def get_router_list(self) -> dict: - """Get the list of routers. - - Returns - ------- - dict - List of routers. - - Example return - ---------- - ```json - { - "data": { - "routers":[ - { - "generic": false, - "router_brand": "3rd Party", - "router_model": "DD-WRT", - "router_version": "v24-sp1 micro" - }, - { - "generic": false, - "router_brand": "3rd Party", - "router_model": "DD-WRT", - "router_version": "v24-sp2 std - build 14896" - } - ] - }, - "success": true - } - ``` + """ + Get the list of routers. + + Returns + ------- + dict + List of routers. + + Examples + -------- + ```json + { + "data": { + "routers":[ + { + "generic": false, + "router_brand": "3rd Party", + "router_model": "DD-WRT", + "router_version": "v24-sp1 micro" + }, + { + "generic": false, + "router_brand": "3rd Party", + "router_model": "DD-WRT", + "router_version": "v24-sp2 std - build 14896" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.PortForwarding.RouterList' info = self.gen_list[api_name] @@ -629,42 +648,43 @@ def get_router_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - - def set_router_config(self, - router_brand: str, router_model: str, router_version: str, router_protocol: str, router_port: int, - support_upnp: bool = False, support_natpmp: bool = False - ) -> dict: - """Set the router configuration. - - Parameters - ---------- - router_brand : str - The brand of the router. - router_model : str - The model of the router. - router_version : str - The version of the router. - router_protocol : str - The protocol used by the router. - router_port : int - The port used by the router. - support_upnp : bool, optional - Whether UPnP is supported (default is False). - support_natpmp : bool, optional - Whether NAT-PMP is supported (default is False). - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true, - } - ``` + + def set_router_config(self, + router_brand: str, router_model: str, router_version: str, router_protocol: str, router_port: int, + support_upnp: bool = False, support_natpmp: bool = False + ) -> dict: + """ + Set the router configuration. + + Parameters + ---------- + router_brand : str + The brand of the router. + router_model : str + The model of the router. + router_version : str + The version of the router. + router_protocol : str + The protocol used by the router. + router_port : int + The port used by the router. + support_upnp : bool, optional + Whether UPnP is supported (default is False). + support_natpmp : bool, optional + Whether NAT-PMP is supported (default is False). + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true, + } + ``` """ api_name = 'SYNO.Core.PortForwarding.RouterConf' info = self.gen_list[api_name] @@ -681,33 +701,34 @@ def set_router_config(self, 'support_natpmp': "yes" if support_natpmp else "no" } return self.request_data(api_name, api_path, req_param) - + def get_port_forwarding_rule_list(self) -> dict: - """Get the list of port forwarding rules. - - Returns - ------- - dict - List of port forwarding rules. - - Example return - ---------- - ```json - { - "data": [ - { - "ds_port": "873", - "enable": true, - "router_port": "873", - "router_protocol": "tcp", - "rule_id": "1", - "service_name": "", - "serviceid": "netbkp" - } - ], - "success": true - } - ``` + """ + Get the list of port forwarding rules. + + Returns + ------- + dict + List of port forwarding rules. + + Examples + -------- + ```json + { + "data": [ + { + "ds_port": "873", + "enable": true, + "router_port": "873", + "router_protocol": "tcp", + "rule_id": "1", + "service_name": "", + "serviceid": "netbkp" + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.PortForwarding.Rules' info = self.gen_list[api_name] @@ -717,64 +738,65 @@ def get_port_forwarding_rule_list(self) -> dict: 'method': 'load' } return self.request_data(api_name, api_path, req_param) - + def get_services_port_info(self) -> dict: - """Get the port information of services. - - Returns - ------- - dict - Port information of services. - - Example return - ---------- - ```json - { - "data": { - "service": [ - { - "additional": { - "port_info": [ - { - "desc": "Share files with Mac", - "dst_port": [ - "548" - ], - "name": "AFP", - "port_id": "afp", - "protocol": "tcp", - "src_port": null - } - ] - }, - "display_name": "AFP", - "enable_status": "disabled", - "service_id": "atalk" + """ + Get the port information of services. + + Returns + ------- + dict + Port information of services. + + Examples + -------- + ```json + { + "data": { + "service": [ + { + "additional": { + "port_info": [ + { + "desc": "Share files with Mac", + "dst_port": [ + "548" + ], + "name": "AFP", + "port_id": "afp", + "protocol": "tcp", + "src_port": null + } + ] }, - { - "additional": { - "port_info": [ - { - "desc": "Bonjour", - "dst_port": [ - "5353" - ], - "name": "Bonjour Service", - "port_id": "bonjour", - "protocol": "udp", - "src_port": null - } - ] - }, - "display_name": "Bonjour Printer Broadcast", - "enable_status": "disabled", - "service_id": "bonjour" - } - ] - }, - "success": true - } - ``` + "display_name": "AFP", + "enable_status": "disabled", + "service_id": "atalk" + }, + { + "additional": { + "port_info": [ + { + "desc": "Bonjour", + "dst_port": [ + "5353" + ], + "name": "Bonjour Service", + "port_id": "bonjour", + "protocol": "udp", + "src_port": null + } + ] + }, + "display_name": "Bonjour Printer Broadcast", + "enable_status": "disabled", + "service_id": "bonjour" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Service' info = self.gen_list[api_name] @@ -785,30 +807,31 @@ def get_services_port_info(self) -> dict: 'additional': ["port_info"] } return self.request_data(api_name, api_path, req_param) - + def get_advanced_external_access(self) -> dict: - """Get the advanced external access settings. - - Returns - ------- - dict - Advanced external access settings: - - `hostname`: The hostname of the DSM. - - `http_port`: The HTTP port of the DSM. - - `https_port`: The HTTPS port of the DSM. - - Example return - ---------- - ```json - { - "data": { - "hostname": "HOSTNAME", - "http_port": 5000, - "https_port": 5001 - }, - "success": true - } - ``` + """ + Get the advanced external access settings. + + Returns + ------- + dict + Advanced external access settings: + - `hostname`: The hostname of the DSM. + - `http_port`: The HTTP port of the DSM. + - `https_port`: The HTTPS port of the DSM. + + Examples + -------- + ```json + { + "data": { + "hostname": "HOSTNAME", + "http_port": 5000, + "https_port": 5001 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Web.DSM.External' info = self.gen_list[api_name] @@ -818,31 +841,32 @@ def get_advanced_external_access(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_advanced_external_access(self, hostname: str, http_port: int, https_port: int) -> dict: - """Set the advanced external access settings. - - Parameters - ---------- - hostname : str - The hostname of the DSM. - http_port : int - The HTTP port of the DSM. - https_port : int - The HTTPS port of the DSM. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true, - } - ``` + """ + Set the advanced external access settings. + + Parameters + ---------- + hostname : str + The hostname of the DSM. + http_port : int + The HTTP port of the DSM. + https_port : int + The HTTPS port of the DSM. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true, + } + ``` """ api_name = 'SYNO.Core.Web.DSM.External' info = self.gen_list[api_name] @@ -855,6 +879,5 @@ def set_advanced_external_access(self, hostname: str, http_port: int, https_port 'https_port': https_port } return self.request_data(api_name, api_path, req_param) - - - pass \ No newline at end of file + + pass diff --git a/synology_api/DSM/ControlPanel/ExternalDevices.py b/synology_api/DSM/ControlPanel/ExternalDevices.py index cbcf775f..fda878c7 100644 --- a/synology_api/DSM/ControlPanel/ExternalDevices.py +++ b/synology_api/DSM/ControlPanel/ExternalDevices.py @@ -1,9 +1,15 @@ +""" +External devices class for Synology DSM. +""" + from synology_api import base_api from typing import List + + class ExternalDevices(base_api.BaseApi): """ External devices class for interacting with Synology DSM External devices settings. - + Supported methods: - Getters: - get_printer_driver_list() @@ -16,76 +22,76 @@ class ExternalDevices(base_api.BaseApi): - Setters: - set_printer_bonjour_enabled() - set_permissions() - """ - + def get_printer_driver_list(self) -> dict: - """Get the list of printer driver. - - Returns - ------- - dict - List of printer driver. - - Example return - ---------- - ```json - { - "data": { - "Apollo": [ - [ - "Apollo P-2100", - "stp-pcl-apollo-p2100.5.2.ppd.tgz", - "", - "" - ], - [ - "Apollo P-2150", - "stp-pcl-apollo-p2150.5.2.ppd.tgz", - "", - "" - ], - [ - "Apollo P-2200", - "stp-pcl-apollo-p2200.5.2.ppd.tgz", - "EPSON", - "Stylus DX4800" - ], - [ - "Apollo P-2250", - "stp-pcl-apollo-p2250.5.2.ppd.tgz", - "", - "" - ], - [ - "Apollo P-2500", - "stp-pcl-apollo-p2500.5.2.ppd.tgz", - "", - "" - ], - [ - "Apollo P-2550", - "stp-pcl-apollo-p2550.5.2.ppd.tgz", - "", - "" - ], - [ - "Apollo P-2600", - "stp-pcl-apollo-p2600.5.2.ppd.tgz", - "", - "" - ], - [ - "Apollo P-2650", - "stp-pcl-apollo-p2650.5.2.ppd.tgz", - "", - "" - ] + """ + Get the list of printer driver. + + Returns + ------- + dict + List of printer driver. + + Examples + -------- + ```json + { + "data": { + "Apollo": [ + [ + "Apollo P-2100", + "stp-pcl-apollo-p2100.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2150", + "stp-pcl-apollo-p2150.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2200", + "stp-pcl-apollo-p2200.5.2.ppd.tgz", + "EPSON", + "Stylus DX4800" + ], + [ + "Apollo P-2250", + "stp-pcl-apollo-p2250.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2500", + "stp-pcl-apollo-p2500.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2550", + "stp-pcl-apollo-p2550.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2600", + "stp-pcl-apollo-p2600.5.2.ppd.tgz", + "", + "" + ], + [ + "Apollo P-2650", + "stp-pcl-apollo-p2650.5.2.ppd.tgz", + "", + "" ] - }, - "success": true - } - ``` + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Printer.Driver' info = self.gen_list[api_name] @@ -95,25 +101,26 @@ def get_printer_driver_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_printer_bonjour_enabled(self) -> dict: - """Get the printer bonjour enabled status. - - Returns - ------- - dict - Printer bonjour enabled status. - - Example return - ---------- - ```json - { - "data": { - "enable_bonjour_support": false - }, - "success": true - } - ``` + """ + Get the printer bonjour enabled status. + + Returns + ------- + dict + Printer bonjour enabled status. + + Examples + -------- + ```json + { + "data": { + "enable_bonjour_support": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Printer.BonjourSharing' info = self.gen_list[api_name] @@ -123,27 +130,28 @@ def get_printer_bonjour_enabled(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_printer_bonjour_enabled(self, enable: bool) -> dict: - """Set the printer bonjour enabled status. - - Parameters - ---------- - enable : bool - Printer bonjour enabled status. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set the printer bonjour enabled status. + + Parameters + ---------- + enable : bool + Printer bonjour enabled status. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Printer.BonjourSharing' info = self.gen_list[api_name] @@ -154,31 +162,31 @@ def set_printer_bonjour_enabled(self, enable: bool) -> dict: 'enable_bonjour_support': enable } return self.request_data(api_name, api_path, req_param) - - + def get_storage_settings(self) -> dict: - """Get the external devices storage settings. - - Returns - ------- - dict - External devices storage settings. - - Example return - ---------- - ```json - { - "data": { - "delalloc": false, - "forbid_usb": false, - "needReboot": false, - "non_admin_eject": false, - "setting": false, - "support_exfat_mkfs": false - }, - "success": true - } - ``` + """ + Get the external devices storage settings. + + Returns + ------- + dict + External devices storage settings. + + Examples + -------- + ```json + { + "data": { + "delalloc": false, + "forbid_usb": false, + "needReboot": false, + "non_admin_eject": false, + "setting": false, + "support_exfat_mkfs": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Storage.Setting' info = self.gen_list[api_name] @@ -188,25 +196,26 @@ def get_storage_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_list_usb_devices(self) -> dict: - """Get the list of USB devices. - - Returns - ------- - dict - List of USB devices. - - Example return - ---------- - ```json - { - "data": { - "devices": [] - }, - "success": true - } - ``` + """ + Get the list of USB devices. + + Returns + ------- + dict + List of USB devices. + + Examples + -------- + ```json + { + "data": { + "devices": [] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Storage.USB' info = self.gen_list[api_name] @@ -217,25 +226,26 @@ def get_list_usb_devices(self) -> dict: 'additional': ["all"], } return self.request_data(api_name, api_path, req_param) - + def get_list_esata_devices(self) -> dict: - """Get the list of eSATA devices. - - Returns - ------- - dict - List of eSATA devices. - - Example return - ---------- - ```json - { - "data": { - "devices": [] - }, - "success": true - } - ``` + """ + Get the list of eSATA devices. + + Returns + ------- + dict + List of eSATA devices. + + Examples + -------- + ```json + { + "data": { + "devices": [] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Storage.eSATA' info = self.gen_list[api_name] @@ -246,25 +256,26 @@ def get_list_esata_devices(self) -> dict: 'additional': ["all"], } return self.request_data(api_name, api_path, req_param) - + def get_list_of_printer(self) -> dict: - """Get the list of printers. - - Returns - ------- - dict - List of printers. - - Example return - ---------- - ```json - { - "data": { - "printers": [] - }, - "success": true - } - ``` + """ + Get the list of printers. + + Returns + ------- + dict + List of printers. + + Examples + -------- + ```json + { + "data": { + "printers": [] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.Printer' info = self.gen_list[api_name] @@ -275,54 +286,55 @@ def get_list_of_printer(self) -> dict: 'additional': ["all"], } return self.request_data(api_name, api_path, req_param) - - def get_permissions(self, - offset: int = 0, limit: int = 50, - user_group_type: str = "local_user" - ) -> dict: - """Get the permissions of the external devices - - Parameters - ---------- - offset : int, optional - The offset for pagination. Defaults to `0`. - limit : int, optional - The limit for pagination. Defaults to `50`. - user_group_type : str, optional - The type of user group to list permissions for. Defaults to `"local_user"`. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - Returns - ------- - dict - Permissions of the external devices. - - Example return - ---------- - ```json - { - "data": { - "items": [ - { - "is_admin": true, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "admin" - }, - { - "is_admin": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "guest" - } - ], - "total": 2 - }, - "success": true - } - ``` + + def get_permissions(self, + offset: int = 0, limit: int = 50, + user_group_type: str = "local_user" + ) -> dict: + """ + Get the permissions of the external devices. + + Parameters + ---------- + offset : int, optional + The offset for pagination. Defaults to `0`. + limit : int, optional + The limit for pagination. Defaults to `50`. + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + Permissions of the external devices. + + Examples + -------- + ```json + { + "data": { + "items": [ + { + "is_admin": true, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "admin" + }, + { + "is_admin": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + } + ], + "total": 2 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.DefaultPermission' info = self.gen_list[api_name] @@ -336,41 +348,42 @@ def get_permissions(self, 'user_group_type': user_group_type } return self.request_data(api_name, api_path, req_param) - + def set_permissions(self, user_group_type: str, permissions: List[dict[str, object]]) -> dict: - """Set the permissions of the external devices. - - Parameters - ---------- - user_group_type : str - The type of user group to set permissions for. All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - permissions : List[dict[str, object]] - List of permissions to set. Each permission is a dictionary. - Example: - ```json - [ - { - "name":"guest", - "is_readonly":false, - "is_writable":true, - "is_deny":false, - "is_custom":false - } - ] - ``` - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- + """ + Set the permissions of the external devices. + + Parameters + ---------- + user_group_type : str + The type of user group to set permissions for. All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + permissions : List[dict[str, object]] + List of permissions to set. Each permission is a dictionary. + Example: ```json - { - "success": true - } + [ + { + "name":"guest", + "is_readonly":false, + "is_writable":true, + "is_deny":false, + "is_custom":false + } + ] ``` + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.DefaultPermission' info = self.gen_list[api_name] @@ -382,7 +395,5 @@ def set_permissions(self, user_group_type: str, permissions: List[dict[str, obje 'permissions': permissions } return self.request_data(api_name, api_path, req_param) - - - - pass \ No newline at end of file + + pass diff --git a/synology_api/DSM/ControlPanel/FileServices.py b/synology_api/DSM/ControlPanel/FileServices.py index 94e84710..4d93b21c 100644 --- a/synology_api/DSM/ControlPanel/FileServices.py +++ b/synology_api/DSM/ControlPanel/FileServices.py @@ -1,70 +1,73 @@ + +""" +File services class for interacting with Synology DSM File services settings. +""" + from synology_api import base_api + class FileServices(base_api.BaseApi): """ File services class for interacting with Synology DSM File services settings. - - Supported methods: - - Getters: - - - Setters: + Provides methods to get and set SMB, AFP, NFS, FTP, SFTP, and other file service settings. """ - + def get_smb_settings(self): - """Get SMB settings - - Returns - ------- - dict - SMB settings data. - - Example return - ---------- - ```json - { - "data": { - "disable_shadow_copy": false, - "disable_strict_allocate": false, - "enable_access_based_share_enum": false, - "enable_adserver": null, - "enable_aio_read": false, - "enable_delete_vetofiles": false, - "enable_dirsort": false, - "enable_durable_handles": false, - "enable_enhance_log": false, - "enable_fruit_locking": false, - "enable_local_master_browser": false, - "enable_mask": false, - "enable_msdfs": false, - "enable_multichannel": false, - "enable_ntlmv1_auth": false, - "enable_op_lock": true, - "enable_perf_chart": false, - "enable_reset_on_zero_vc": false, - "enable_samba": true, - "enable_server_signing": 0, - "enable_smb2_leases": true, - "enable_smb3_directory_leasing": true, - "enable_strict_sync": false, - "enable_symlink": true, - "enable_syno_catia": true, - "enable_synotify": true, - "enable_vetofile": false, - "enable_widelink": false, - "offline_files_support": false, - "smb3_directory_leasing_scope": "home_only", - "smb_encrypt_transport": 1, - "smb_max_protocol": 3, - "smb_min_protocol": 1, - "syno_wildcard_search": false, - "vetofile": "", - "wins": "", - "workgroup": "WORKGROUP" - } - "success": true - } - ``` + """ + Get SMB settings. + + Returns + ------- + dict + SMB settings data. + + Examples + -------- + ```json + { + "data": { + "disable_shadow_copy": false, + "disable_strict_allocate": false, + "enable_access_based_share_enum": false, + "enable_adserver": null, + "enable_aio_read": false, + "enable_delete_vetofiles": false, + "enable_dirsort": false, + "enable_durable_handles": false, + "enable_enhance_log": false, + "enable_fruit_locking": false, + "enable_local_master_browser": false, + "enable_mask": false, + "enable_msdfs": false, + "enable_multichannel": false, + "enable_ntlmv1_auth": false, + "enable_op_lock": true, + "enable_perf_chart": false, + "enable_reset_on_zero_vc": false, + "enable_samba": true, + "enable_server_signing": 0, + "enable_smb2_leases": true, + "enable_smb3_directory_leasing": true, + "enable_strict_sync": false, + "enable_symlink": true, + "enable_syno_catia": true, + "enable_synotify": true, + "enable_vetofile": false, + "enable_widelink": false, + "offline_files_support": false, + "smb3_directory_leasing_scope": "home_only", + "smb_encrypt_transport": 1, + "smb_max_protocol": 3, + "smb_min_protocol": 1, + "syno_wildcard_search": false, + "vetofile": "", + "wins": "", + "workgroup": "WORKGROUP" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.SMB' info = self.gen_list[api_name] @@ -74,28 +77,29 @@ def get_smb_settings(self): 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_afp_settings(self) -> dict: - """Get AFP settings - - Returns - ------- - dict - AFP settings data. - - Example return - ---------- - ```json - { - "data": { - "enable_afp": false, - "enable_disconnect_quick": false, - "enable_umask": false, - "time_machine": "" - }, - "success": true - } - ``` + """ + Get AFP settings. + + Returns + ------- + dict + AFP settings data. + + Examples + -------- + ```json + { + "data": { + "enable_afp": false, + "enable_disconnect_quick": false, + "enable_umask": false, + "time_machine": "" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.AFP' info = self.gen_list[api_name] @@ -105,34 +109,35 @@ def get_afp_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_nfs_settings(self) -> dict: - """Get NFS settings - - Returns - ------- - dict - NFS settings data. - - Example return - ---------- - ```json - { - "data": { - "enable_nfs": false, - "enable_nfs_v4": false, - "enabled_minor_ver": 0, - "nfs_v4_domain": "", - "read_size": 8192, - "support_encrypt_share": 1, - "support_major_ver": 4, - "support_minor_ver": 1, - "unix_pri_enable": true, - "write_size": 8192 - }, - "success": true - } - ``` + """ + Get NFS settings. + + Returns + ------- + dict + NFS settings data. + + Examples + -------- + ```json + { + "data": { + "enable_nfs": false, + "enable_nfs_v4": false, + "enabled_minor_ver": 0, + "nfs_v4_domain": "", + "read_size": 8192, + "support_encrypt_share": 1, + "support_major_ver": 4, + "support_minor_ver": 1, + "unix_pri_enable": true, + "write_size": 8192 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.NFS' info = self.gen_list[api_name] @@ -142,41 +147,42 @@ def get_nfs_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_ftp_settings(self) -> dict: - """Get FTP settings - - Returns - ------- - dict - FTP settings data. - - Example return - ---------- - ```json - { - "data": { - "custom_port": "55536:55899", - "custom_port_range": false, - "enable_ascii": false, - "enable_fips": false, - "enable_flow_ctrl": false, - "enable_ftp": false, - "enable_ftps": false, - "enable_fxp": false, - "ext_ip": "", - "max_conn_per_ip": 0, - "maxdownloadrate": 0, - "maxuploadrate": 0, - "modify_time_std": "utc", - "portnum": 21, - "timeout": 300, - "use_ext_ip": false, - "utf8_mode": 1, - }, - "success": true - } - ``` + """ + Get FTP settings. + + Returns + ------- + dict + FTP settings data. + + Examples + -------- + ```json + { + "data": { + "custom_port": "55536:55899", + "custom_port_range": false, + "enable_ascii": false, + "enable_fips": false, + "enable_flow_ctrl": false, + "enable_ftp": false, + "enable_ftps": false, + "enable_fxp": false, + "ext_ip": "", + "max_conn_per_ip": 0, + "maxdownloadrate": 0, + "maxuploadrate": 0, + "modify_time_std": "utc", + "portnum": 21, + "timeout": 300, + "use_ext_ip": false, + "utf8_mode": 1 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.FTP' info = self.gen_list[api_name] @@ -186,26 +192,27 @@ def get_ftp_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_sftp_settings(self) -> dict: - """Get SFTP settings - - Returns - ------- - dict - SFTP settings data. - - Example return - ---------- - ```json - { - "data": { - "enable": false, - "portnum": 22, - }, - "success": true - } - ``` + """ + Get SFTP settings. + + Returns + ------- + dict + SFTP settings data. + + Examples + -------- + ```json + { + "data": { + "enable": false, + "portnum": 22 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.FTP.SFTP' info = self.gen_list[api_name] @@ -215,37 +222,35 @@ def get_sftp_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_bandwidth_control_protocol_settings(self, protocol: str, schedule_plan: str) -> dict: - """Get bandwidth control protocol settings - - Parameters - ---------- - protocol : str - Protocol name, here are the known protocols: - - "FTP" - - "NetworkBackup" - - schedule_plan : str - Schedule plan, a 128-bit binary string. - - Returns - ------- - dict - Bandwidth control protocol settings data. - - Example return - ---------- - ```json - { - "data": { - "policy": "disabled", - "protocol": "FTP", - "schedule_plan": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" - }, - "success": true - } - ``` + """ + Get bandwidth control protocol settings. + + Parameters + ---------- + protocol : str + Protocol name (e.g. "FTP", "NetworkBackup"). + schedule_plan : str + Schedule plan, a 128-bit binary string. + + Returns + ------- + dict + Bandwidth control protocol settings data. + + Examples + -------- + ```json + { + "data": { + "policy": "disabled", + "protocol": "FTP", + "schedule_plan": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.BandwidthControl.Protocol' info = self.gen_list[api_name] @@ -256,28 +261,29 @@ def get_bandwidth_control_protocol_settings(self, protocol: str, schedule_plan: 'protocol': protocol } return self.request_data(api_name, api_path, req_param) - + def get_network_backup_settings(self) -> dict: - """Get network backup settings - - Returns - ------- - dict - Network backup settings data. - - Example return - ---------- - ```json - { - "data": { - "enable": false, - "enable_custom_config": false, - "enable_rsync_account": false, - "rsync_sshd_port": "22" - }, - "success": true - } - ``` + """ + Get network backup settings. + + Returns + ------- + dict + Network backup settings data. + + Examples + -------- + ```json + { + "data": { + "enable": false, + "enable_custom_config": false, + "enable_rsync_account": false, + "rsync_sshd_port": "22" + }, + "success": true + } + ``` """ api_name = 'SYNO.Backup.Service.NetworkBackup' info = self.gen_list[api_name] @@ -287,25 +293,26 @@ def get_network_backup_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_domain_settings(self) -> dict: - """Get domain settings - - Returns - ------- - dict - Domain settings data. - - Example return - ---------- - ```json - { - "data": { - "enable_domain": false - }, - "success": true - } - ``` + """ + Get domain settings. + + Returns + ------- + dict + Domain settings data. + + Examples + -------- + ```json + { + "data": { + "enable_domain": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Directory.Domain' info = self.gen_list[api_name] @@ -315,28 +322,29 @@ def get_domain_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_service_discovery_settings(self) -> dict: - """Get service discovery settings - - Returns - ------- - dict - Service discovery settings data. - - Example return - ---------- - ```json - { - "data": { - "enable_afp_time_machine": false, - "enable_smb_time_machine": false, - "time_machine_disable_shares": [], - "time_machine_shares": [] - }, - "success": true - } - ``` + """ + Get service discovery settings. + + Returns + ------- + dict + Service discovery settings data. + + Examples + -------- + ```json + { + "data": { + "enable_afp_time_machine": false, + "enable_smb_time_machine": false, + "time_machine_disable_shares": [], + "time_machine_shares": [] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.ServiceDiscovery' info = self.gen_list[api_name] @@ -346,25 +354,26 @@ def get_service_discovery_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_wstransfer_settings(self) -> dict: - """Get WSTransfer settings - - Returns - ------- - dict - WSTransfer settings data. - - Example return - ---------- - ```json - { - "data": { - "enable_wstransfer": true - }, - "success": true - } - ``` + """ + Get WSTransfer settings. + + Returns + ------- + dict + WSTransfer settings data. + + Examples + -------- + ```json + { + "data": { + "enable_wstransfer": true + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.ServiceDiscovery.WSTransfer' info = self.gen_list[api_name] @@ -374,25 +383,26 @@ def get_wstransfer_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_reflink_copy_settings(self) -> dict: - """Get reflink copy settings - - Returns - ------- - dict - Reflink copy settings data. - - Example return - ---------- - ```json - { - "data": { - "reflink_copy_enable": false, - }, - "success": true - } - ``` + """ + Get reflink copy settings. + + Returns + ------- + dict + Reflink copy settings data. + + Examples + -------- + ```json + { + "data": { + "reflink_copy_enable": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.ReflinkCopy' info = self.gen_list[api_name] @@ -402,31 +412,32 @@ def get_reflink_copy_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_tftp_settings(self) -> dict: - """Get TFTP settings - - Returns - ------- - dict - TFTP settings data. - - Example return - ---------- - ```json - { - "data": { - "enable": false, - "enable_log": false, - "endip": "255.255.255.255", - "permission": "r", - "root_path": "", - "startip": "0.0.0.0", - "timeout": 3 - }, - "success": true - } - ``` + """ + Get TFTP settings. + + Returns + ------- + dict + TFTP settings data. + + Examples + -------- + ```json + { + "data": { + "enable": false, + "enable_log": false, + "endip": "255.255.255.255", + "permission": "r", + "root_path": "", + "startip": "0.0.0.0", + "timeout": 3 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.TFTP' info = self.gen_list[api_name] @@ -436,22 +447,23 @@ def get_tftp_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def clean_smb_cache(self) -> dict: - """Clean SMB cache - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Clean SMB cache. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.SMB' info = self.gen_list[api_name] @@ -461,36 +473,34 @@ def clean_smb_cache(self) -> dict: 'method': 'clean_cache' } return self.request_data(api_name, api_path, req_param) - + def set_afp_settings(self, enable: bool, enable_transfer_log: bool, enable_umask: bool, enable_disconnect_quick: bool) -> dict: - """Set AFP settings - - Parameters - ---------- - enable : bool - Enable or disable AFP. - - enable_transfer_log : bool - Enable or disable transfer log. - - enable_umask : bool - Enable or disable umask. - - enable_disconnect_quick : bool - Enable or disable quick disconnect. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set AFP settings. + + Parameters + ---------- + enable : bool + Enable or disable AFP. + enable_transfer_log : bool + Enable or disable transfer log. + enable_umask : bool + Enable or disable umask. + enable_disconnect_quick : bool + Enable or disable quick disconnect. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.AFP' info = self.gen_list[api_name] @@ -504,32 +514,34 @@ def set_afp_settings(self, enable: bool, enable_transfer_log: bool, enable_umask 'enable_disconnect_quick': enable_disconnect_quick } return self.request_data(api_name, api_path, req_param) - + def set_nfs_settings(self, enable: bool, max_protocol: int, enable_v4: bool, enabled_minor_ver: int) -> dict: - """Set NFS settings - - Parameters - ---------- - enable : bool - Enable or disable NFS. - - max_protocol : int - Maximum NFS protocol version. - - enalbe_v4 : bool - Enable or disable NFSv4. - - enabled_minor_ver : int - Enabled minor version. - - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set NFS settings. + + Parameters + ---------- + enable : bool + Enable or disable NFS. + max_protocol : int + Maximum NFS protocol version. + enable_v4 : bool + Enable or disable NFSv4. + enabled_minor_ver : int + Enabled minor version. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.NFS' info = self.gen_list[api_name] @@ -543,29 +555,30 @@ def set_nfs_settings(self, enable: bool, max_protocol: int, enable_v4: bool, ena 'enabled_minor_ver': enabled_minor_ver } return self.request_data(api_name, api_path, req_param) - + def get_ftp_security_settings(self) -> dict: - """Get FTP security settings - - Returns - ------- - dict - FTP security settings data. - - Example return - ---------- - ```json - { - "data": { - "anonymous": false, - "anonymous_chroot": false, - "anonymous_chroot_share": "", - "enable_umask": false, - "user_chroot": false - }, - "success": true - } - ``` + """ + Get FTP security settings. + + Returns + ------- + dict + FTP security settings data. + + Examples + -------- + ```json + { + "data": { + "anonymous": false, + "anonymous_chroot": false, + "anonymous_chroot_share": "", + "enable_umask": false, + "user_chroot": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.FTP.Security' info = self.gen_list[api_name] @@ -575,27 +588,28 @@ def get_ftp_security_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_ftp_security_share_list(self) -> dict: - """Get FTP security share list - - Returns - ------- - dict - FTP security share list data. - - Example return - ---------- - ```json - { - "data":{ - "share": [ - "docker" - ] - }, - "success": true - } - ``` + """ + Get FTP security share list. + + Returns + ------- + dict + FTP security share list data. + + Examples + -------- + ```json + { + "data":{ + "share": [ + "docker" + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.FTP.Security.ShareList' info = self.gen_list[api_name] @@ -605,65 +619,55 @@ def get_ftp_security_share_list(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_ftp_settings(self, enable_ftp: bool, enable_ftps: bool, - timeout: int = 300, portnum: int = 21, custom_port_range: bool = False, - use_ext_ip: bool = False, enable_fxp: bool = True, enable_ascii: bool = True, - utf8_mode: int = 1, modify_time_std: str = "utc", custom_port: str = "55536:55899", - external_ip: str = "default" - ) -> dict: - """Set FTP settings - - Parameters - ---------- - enable_ftp : bool - Enable or disable FTP. - - enable_ftps : bool - Enable or disable FTPS. - - timeout : int - Timeout in seconds. Default to `300`. - - portnum : int - Port number. Default to `21`. - - custom_port_range : bool - Enable or disable custom port range. Default to `False`. - - use_ext_ip : bool - Enable or disable external IP. Default to `False`. - - enable_fxp : bool - Enable or disable FXP. Default to `True`. - - enable_ascii : bool - Enable or disable ASCII mode. Default to `True`. - - utf8_mode : int - UTF-8 mode (0: disable, 1: Auto, 2: Force). Default to `1`. - - modify_time_std : str - Modify time standard ("utc", "local"). Default to `"utc"`. - - custom_port : str - Custom port range. Default to `"55536:55899"`. - - external_ip : str - External IP address. Default to `"default"`. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + timeout: int = 300, portnum: int = 21, custom_port_range: bool = False, + use_ext_ip: bool = False, enable_fxp: bool = True, enable_ascii: bool = True, + utf8_mode: int = 1, modify_time_std: str = "utc", custom_port: str = "55536:55899", + external_ip: str = "default" + ) -> dict: + """ + Set FTP settings. + + Parameters + ---------- + enable_ftp : bool + Enable or disable FTP. + enable_ftps : bool + Enable or disable FTPS. + timeout : int, optional + Timeout in seconds. Default is 300. + portnum : int, optional + Port number. Default is 21. + custom_port_range : bool, optional + Enable or disable custom port range. Default is False. + use_ext_ip : bool, optional + Enable or disable external IP. Default is False. + enable_fxp : bool, optional + Enable or disable FXP. Default is True. + enable_ascii : bool, optional + Enable or disable ASCII mode. Default is True. + utf8_mode : int, optional + UTF-8 mode (0: disable, 1: Auto, 2: Force). Default is 1. + modify_time_std : str, optional + Modify time standard ("utc", "local"). Default is "utc". + custom_port : str, optional + Custom port range. Default is "55536:55899". + external_ip : str, optional + External IP address. Default is "default". + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.FTP' info = self.gen_list[api_name] @@ -685,30 +689,30 @@ def set_ftp_settings(self, enable_ftp: bool, enable_ftps: bool, 'external_ip': external_ip } return self.request_data(api_name, api_path, req_param) - + def set_sftp_settings(self, enable: bool, portnum: int = 22) -> dict: - """Set SFTP settings - - Parameters - ---------- - enable : bool - Enable or disable SFTP. - - portnum : int - Port number. Default to `22`. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set SFTP settings. + + Parameters + ---------- + enable : bool + Enable or disable SFTP. + portnum : int, optional + Port number. Default is 22. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.FTP.SFTP' info = self.gen_list[api_name] @@ -721,30 +725,30 @@ def set_sftp_settings(self, enable: bool, portnum: int = 22) -> dict: 'sftp_portnum': portnum } return self.request_data(api_name, api_path, req_param) - + def set_rsync_settings(self, enable: bool, port: int = 22) -> dict: - """Set rsync settings - - Parameters - ---------- - enable : bool - Enable or disable rsync. - - port : int - Rsync SSHD port. Default to `22`. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set rsync settings. + + Parameters + ---------- + enable : bool + Enable or disable rsync. + port : int, optional + Rsync SSHD port. Default is 22. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Backup.Service.NetworkBackup' info = self.gen_list[api_name] @@ -756,27 +760,28 @@ def set_rsync_settings(self, enable: bool, port: int = 22) -> dict: 'rsync_sshd_port': port } return self.request_data(api_name, api_path, req_param) - + def set_reflink_copy_settings(self, reflink_copy_enable: bool) -> dict: - """Set reflink copy settings - - Parameters - ---------- - reflink_copy_enable : bool - Enable or disable reflink copy. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set reflink copy settings. + + Parameters + ---------- + reflink_copy_enable : bool + Enable or disable reflink copy. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.FileServ.ReflinkCopy' info = self.gen_list[api_name] @@ -787,30 +792,30 @@ def set_reflink_copy_settings(self, reflink_copy_enable: bool) -> dict: 'reflink_copy_enable': reflink_copy_enable } return self.request_data(api_name, api_path, req_param) - + def set_tftp_settings(self, enable: bool, root_path: str) -> dict: - """Set TFTP settings - - Parameters - ---------- - enable : bool - Enable or disable TFTP. - - root_path : str - Root path for TFTP. Path must be a valid directory. - - Returns - ------- - dict - Result of the operation. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Set TFTP settings. + + Parameters + ---------- + enable : bool + Enable or disable TFTP. + root_path : str + Root path for TFTP. Path must be a valid directory. + + Returns + ------- + dict + Result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.TFTP' info = self.gen_list[api_name] @@ -822,5 +827,5 @@ def set_tftp_settings(self, enable: bool, root_path: str) -> dict: 'root_path': root_path } return self.request_data(api_name, api_path, req_param) - - pass \ No newline at end of file + + pass diff --git a/synology_api/DSM/ControlPanel/HardwarePower.py b/synology_api/DSM/ControlPanel/HardwarePower.py index dae0510a..19346030 100644 --- a/synology_api/DSM/ControlPanel/HardwarePower.py +++ b/synology_api/DSM/ControlPanel/HardwarePower.py @@ -1,35 +1,41 @@ +""" +Hardware power class for Synology DSM. +""" + from synology_api import base_api import json from typing import List + + class HardwarePower(base_api.BaseApi): """ Hardware power class for interacting with Synology DSM Hardware & Power settings. - + Supported methods: - Getters: - - - Setters: + - Setters: """ - + def need_reboot(self) -> dict: - """TODO: Determine usage of this method. - - Returns - ------- - dict - Return boolean value indicating if a reboot is needed. - - Example return - ---------- - ```json - { - "data": { - "need_reboot": false - }, - "success": true - } - ``` + """ + TODO: Determine usage of this method. + + Returns + ------- + dict + Return boolean value indicating if a reboot is needed. + + Examples + -------- + ```json + { + "data": { + "need_reboot": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.NeedReboot' info = self.gen_list[api_name] @@ -39,25 +45,26 @@ def need_reboot(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_need_reboot(self) -> dict: - """TODO: Determine usage of this method. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + """ + TODO: Determine usage of this method. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.NeedReboot' info = self.gen_list[api_name] @@ -67,27 +74,28 @@ def set_need_reboot(self) -> dict: 'method': 'set' } return self.request_data(api_name, api_path, req_param) - + def get_led_brightness_stats(self) -> dict: - """Get LED brightness stats. - - Returns - ------- - dict - Return LED brightness default settigns and min / max. - - Example return - ---------- - ```json - { - "data": { - "default": 3, - "max": 3, - "min": 0 - }, - "success": true - } - ``` + """ + Get LED brightness stats. + + Returns + ------- + dict + Return LED brightness default settigns and min / max. + + Examples + -------- + ```json + { + "data": { + "default": 3, + "max": 3, + "min": 0 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.Led.Brightness' info = self.gen_list[api_name] @@ -97,25 +105,26 @@ def get_led_brightness_stats(self) -> dict: 'method': 'get_static_data' } return self.request_data(api_name, api_path, req_param) - + def get_zram_settings(self) -> dict: - """Get ZRAM settings. - - Returns - ------- - dict - Return ZRAM settings. - - Example return - ---------- - ```json - { - "data": { - "enable_zram": true - }, - "success": true - } - ``` + """ + Get ZRAM settings. + + Returns + ------- + dict + Return ZRAM settings. + + Examples + -------- + ```json + { + "data": { + "enable_zram": true + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.ZRAM' info = self.gen_list[api_name] @@ -125,38 +134,39 @@ def get_zram_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_power_recovery_settings(self) -> dict: - """Get power recovery settings. - - Returns - ------- - dict - Return power recovery settings. - - Example return - ---------- - ```json - { - "data": { - "internal_lan_num": 2, - "rc_power_config": true, - "wol": [ - { - "enable": false, - "idx": 1 - }, - { - "enable": false, - "idx": 2 - } - ], - "wol1": false, - "wol2": false - }, - "success": true - } - ``` + """ + Get power recovery settings. + + Returns + ------- + dict + Return power recovery settings. + + Examples + -------- + ```json + { + "data": { + "internal_lan_num": 2, + "rc_power_config": true, + "wol": [ + { + "enable": false, + "idx": 1 + }, + { + "enable": false, + "idx": 2 + } + ], + "wol1": false, + "wol2": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.PowerRecovery' info = self.gen_list[api_name] @@ -166,39 +176,40 @@ def get_power_recovery_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_beep_control_settings(self) -> dict: - """Get beep control settings. - - Returns - ------- - dict - Return beep control settings. - - Example return - ---------- - ```json - { - "data": { - "enc_module_fail": true, - "eunit_redundant_power_fail": true, - "fan_fail": true, - "poweroff_beep": true, - "poweron_beep": true, - "redundant_power_fail": true, - "reset_beep": true, - "sas_link_fail": true, - "support_fan_fail": true, - "support_poweroff_beep": true, - "support_poweron_beep": true, - "support_redundant_power_fail": false, - "support_reset_beep": false, - "support_volume_or_cache_crash": true, - "volume_or_cache_crash": true - }, - "success": true - } - ``` + """ + Get beep control settings. + + Returns + ------- + dict + Return beep control settings. + + Examples + -------- + ```json + { + "data": { + "enc_module_fail": true, + "eunit_redundant_power_fail": true, + "fan_fail": true, + "poweroff_beep": true, + "poweron_beep": true, + "redundant_power_fail": true, + "reset_beep": true, + "sas_link_fail": true, + "support_fan_fail": true, + "support_poweroff_beep": true, + "support_poweron_beep": true, + "support_redundant_power_fail": false, + "support_reset_beep": false, + "support_volume_or_cache_crash": true, + "volume_or_cache_crash": true + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.BeepControl' info = self.gen_list[api_name] @@ -208,39 +219,40 @@ def get_beep_control_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_fan_speed_settings(self) -> dict: - """Get fan speed settings. - - Returns - ------- - dict - Return fan speed settings. - - Example return - ---------- - ```json - { - "data": { - "enc_module_fail": true, - "eunit_redundant_power_fail": true, - "fan_fail": true, - "poweroff_beep": true, - "poweron_beep": true, - "redundant_power_fail": true, - "reset_beep": true, - "sas_link_fail": true, - "support_fan_fail": true, - "support_poweroff_beep": true, - "support_poweron_beep": true, - "support_redundant_power_fail": false, - "support_reset_beep": false, - "support_volume_or_cache_crash": true, - "volume_or_cache_crash": true - }, - "success": true - } - ``` + """ + Get fan speed settings. + + Returns + ------- + dict + Return fan speed settings. + + Examples + -------- + ```json + { + "data": { + "enc_module_fail": true, + "eunit_redundant_power_fail": true, + "fan_fail": true, + "poweroff_beep": true, + "poweron_beep": true, + "redundant_power_fail": true, + "reset_beep": true, + "sas_link_fail": true, + "support_fan_fail": true, + "support_poweroff_beep": true, + "support_poweron_beep": true, + "support_redundant_power_fail": false, + "support_reset_beep": false, + "support_volume_or_cache_crash": true, + "volume_or_cache_crash": true + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.FanSpeed' info = self.gen_list[api_name] @@ -250,28 +262,29 @@ def get_fan_speed_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_led_brightness_schedule(self) -> dict: - """Get LED brightness settings. - - Returns - ------- - dict - Return LED brightness settings. Schedule is a 144 character string. - 1 character = 1 hour. Start from Sunday 00:00 to Saturday 23:00. - 0 = Default, 1= Ajusted, 2 = Off - - Example return - ---------- - ```json - { - "data": { - "led_brightness": 3, - "schedule": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" - }, - "success": true - } - ``` + """ + Get LED brightness settings. + + Returns + ------- + dict + Return LED brightness settings. Schedule is a 144 character string. + 1 character = 1 hour. Start from Sunday 00:00 to Saturday 23:00. + 0 = Default, 1= Ajusted, 2 = Off. + + Examples + -------- + ```json + { + "data": { + "led_brightness": 3, + "schedule": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.Led.Brightness' info = self.gen_list[api_name] @@ -281,26 +294,27 @@ def get_led_brightness_schedule(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_power_schedule_settings(self) -> dict: - """Get power schedule settings. - - Returns - ------- - dict - Return power schedule settings. - - Example return - ---------- - ```json - { - "data": { - "poweroff_tasks": [], - "poweron_tasks": [] - }, - "success": true - } - ``` + """ + Get power schedule settings. + + Returns + ------- + dict + Return power schedule settings. + + Examples + -------- + ```json + { + "data": { + "poweroff_tasks": [], + "poweron_tasks": [] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.PowerSchedule' info = self.gen_list[api_name] @@ -310,37 +324,38 @@ def get_power_schedule_settings(self) -> dict: 'method': 'load' } return self.request_data(api_name, api_path, req_param) - + def get_hibernation_settings(self) -> dict: - """Get hibernation settings. - - Returns - ------- - dict - Return hibernation settings. - - Example return - ---------- - ```json - { - "data": { - "auto_poweroff_enable": false, - "enable_log": false, - "eunit_deep_sleep": 0, - "eunit_dsleep_blacklist": "none", - "hibernation_blacklist": "none", - "ignore_netbios_broadcast": false, - "internal_hd_idletime": 20, - "sata_deep_sleep": 1, - "sata_dsleep_blacklist": "none", - "support_esata": "yes", - "support_eunit_deep_sleep": false, - "support_eunit_switch_mode": true, - "usb_idletime": 0 - }, - "success": true - } - ``` + """ + Get hibernation settings. + + Returns + ------- + dict + Return hibernation settings. + + Examples + -------- + ```json + { + "data": { + "auto_poweroff_enable": false, + "enable_log": false, + "eunit_deep_sleep": 0, + "eunit_dsleep_blacklist": "none", + "hibernation_blacklist": "none", + "ignore_netbios_broadcast": false, + "internal_hd_idletime": 20, + "sata_deep_sleep": 1, + "sata_dsleep_blacklist": "none", + "support_esata": "yes", + "support_eunit_deep_sleep": false, + "support_eunit_switch_mode": true, + "usb_idletime": 0 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.Hibernation' info = self.gen_list[api_name] @@ -350,48 +365,49 @@ def get_hibernation_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_ups_settings(self) -> dict: - """Get UPS settings. - - Returns - ------- - dict - Return UPS settings. - - Example return - ---------- - ```json - { - "data": { - "ACL_enable": false, - "ACL_list": [], - "charge": 0, - "delay_time": -1, - "enable": false, - "manufacture": "", - "mode": "SLAVE", - "model": "", - "net_server_ip": "", - "runtime": 0, - "shutdown_device": false, - "snmp_auth": false, - "snmp_auth_key": false, - "snmp_auth_type": "", - "snmp_community": "", - "snmp_mib": "", - "snmp_privacy": false, - "snmp_privacy_key": false, - "snmp_privacy_type": "", - "snmp_server_ip": "", - "snmp_user": "", - "snmp_version": "", - "status": "usb_ups_status_unknown", - "usb_ups_connect": false - }, - "success": true - } - ``` + """ + Get UPS settings. + + Returns + ------- + dict + Return UPS settings. + + Examples + -------- + ```json + { + "data": { + "ACL_enable": false, + "ACL_list": [], + "charge": 0, + "delay_time": -1, + "enable": false, + "manufacture": "", + "mode": "SLAVE", + "model": "", + "net_server_ip": "", + "runtime": 0, + "shutdown_device": false, + "snmp_auth": false, + "snmp_auth_key": false, + "snmp_auth_type": "", + "snmp_community": "", + "snmp_mib": "", + "snmp_privacy": false, + "snmp_privacy_key": false, + "snmp_privacy_type": "", + "snmp_server_ip": "", + "snmp_user": "", + "snmp_version": "", + "status": "usb_ups_status_unknown", + "usb_ups_connect": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.UPS' info = self.gen_list[api_name] @@ -401,30 +417,31 @@ def get_ups_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_led_brightness(self, brightness: int = 3) -> dict: - """Set LED brightness. - - Parameters - ---------- - brightness : int - LED brightness level (0-3). Default is `3`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + """ + Set LED brightness. + + Parameters + ---------- + brightness : int + LED brightness level (0-3). Default is `3`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.Led.Brightness' info = self.gen_list[api_name] @@ -435,31 +452,32 @@ def set_led_brightness(self, brightness: int = 3) -> dict: 'brightness': brightness } return self.request_data(api_name, api_path, req_param) - + def set_zram_settings(self, enable_zram: bool = False) -> dict: - """Set ZRAM settings. - - Parameters - ---------- - enable_zram : bool - Enable or disable ZRAM. Default is `False`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + """ + Set ZRAM settings. + + Parameters + ---------- + enable_zram : bool + Enable or disable ZRAM. Default is `False`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` - """ + }, + "success": true + } + ``` + """ api_name = 'SYNO.Core.Hardware.ZRAM' info = self.gen_list[api_name] api_path = info['path'] @@ -469,38 +487,39 @@ def set_zram_settings(self, enable_zram: bool = False) -> dict: 'enable_zram': enable_zram } return self.request_data(api_name, api_path, req_param) - + def set_power_recovery_settings(self, - enable: bool = False, wol1: bool = False, wol2: bool = False, wol3: bool = False - ) -> dict: - """Set power recovery settings. Note if a wol option is enabled, the enable option will be forced to `True`. - - Parameters - ---------- - enable : bool - Enable or disable power recovery configuration. Default is `False`. - wol1 : bool - Enable or disable Wake on LAN for port 1. Default is `False`. - wol2 : bool - Enable or disable Wake on LAN for port 2. Default is `False`. - wol3 : bool - Enable or disable Wake on LAN for port 3. Default is `False`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + enable: bool = False, wol1: bool = False, wol2: bool = False, wol3: bool = False + ) -> dict: + """ + Set power recovery settings. Note if a wol option is enabled, the enable option will be forced to `True`. + + Parameters + ---------- + enable : bool + Enable or disable power recovery configuration. Default is `False`. + wol1 : bool + Enable or disable Wake on LAN for port 1. Default is `False`. + wol2 : bool + Enable or disable Wake on LAN for port 2. Default is `False`. + wol3 : bool + Enable or disable Wake on LAN for port 3. Default is `False`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.PowerRecovery' info = self.gen_list[api_name] @@ -514,39 +533,40 @@ def set_power_recovery_settings(self, 'wol3': wol3 } return self.request_data(api_name, api_path, req_param) - + def set_beep_control_settings(self, - fan_fail: bool = True, volume_or_cache_crash: bool = True, - poweroff_beep: bool = True, poweron_beep: bool = True - ) -> dict: - """Set beep control settings. - - Parameters - ---------- - fan_fail : bool - Enable or disable fan failure beep. Default is `True`. - volume_or_cache_crash : bool - Enable or disable volume or cache crash beep. Default is `True`. - poweroff_beep : bool - Enable or disable power off beep. Default is `True`. - poweron_beep : bool - Enable or disable power on beep. Default is `True`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + fan_fail: bool = True, volume_or_cache_crash: bool = True, + poweroff_beep: bool = True, poweron_beep: bool = True + ) -> dict: + """ + Set beep control settings. + + Parameters + ---------- + fan_fail : bool + Enable or disable fan failure beep. Default is `True`. + volume_or_cache_crash : bool + Enable or disable volume or cache crash beep. Default is `True`. + poweroff_beep : bool + Enable or disable power off beep. Default is `True`. + poweron_beep : bool + Enable or disable power on beep. Default is `True`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.BeepControl' info = self.gen_list[api_name] @@ -560,31 +580,32 @@ def set_beep_control_settings(self, 'poweron_beep': poweron_beep } return self.request_data(api_name, api_path, req_param) - + def set_fan_speed_settings(self, fan_speed: str = "coolfan") -> dict: - """Set fan speed settings. - - Parameters - ---------- - fan_speed : str - Fan speed level (0-2). Default is `quietfan`. - Known values are `quietfan`, `coolfan`, and `fullspeed`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + """ + Set fan speed settings. + + Parameters + ---------- + fan_speed : str + Fan speed level (0-2). Default is `quietfan`. + Known values are `quietfan`, `coolfan`, and `fullspeed`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.FanSpeed' info = self.gen_list[api_name] @@ -595,35 +616,36 @@ def set_fan_speed_settings(self, fan_speed: str = "coolfan") -> dict: 'dual_fan_speed': fan_speed } return self.request_data(api_name, api_path, req_param) - + def set_led_brightness_schedule(self, - led_brightness: int = 3, schedule: str = "1"*144 - ) -> dict: - """Set LED brightness schedule. - - Parameters - ---------- - led_brightness : int - LED brightness level (0-3). Default is `3`. - schedule : str - Schedule string for LED brightness. 1 character = 1 hour. Start from Sunday 00:00 to Saturday 23:00. - Default is `1` for all hours. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + led_brightness: int = 3, schedule: str = "1"*144 + ) -> dict: + """ + Set LED brightness schedule. + + Parameters + ---------- + led_brightness : int + LED brightness level (0-3). Default is `3`. + schedule : str + Schedule string for LED brightness. 1 character = 1 hour. Start from Sunday 00:00 to Saturday 23:00. + Default is `1` for all hours. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.Led.Brightness' info = self.gen_list[api_name] @@ -635,42 +657,43 @@ def set_led_brightness_schedule(self, 'schedule': schedule } return self.request_data(api_name, api_path, req_param) - + def set_hibernation_settings(self, - internal_hd_idletime: int = 20, stat_deep_sleep: bool = True, - ignore_netbios_broadcast: bool = False, usb_idletime: int = 0, - enable_log: bool = False - ) -> dict: - """Set hibernation settings. - - Parameters - ---------- - internal_hd_idletime : int - Internal hard drive idle time in minutes. Default is `20`. - stat_deep_sleep : bool - Enable or disable SATA deep sleep. Default is `True`. - ignore_netbios_broadcast : bool - Enable or disable ignoring NetBIOS broadcast. Default is `False`. - usb_idletime : int - USB idle time in minutes. Default is `0`. - enable_log : bool - Enable or disable logging. Default is `False`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + internal_hd_idletime: int = 20, stat_deep_sleep: bool = True, + ignore_netbios_broadcast: bool = False, usb_idletime: int = 0, + enable_log: bool = False + ) -> dict: + """ + Set hibernation settings. + + Parameters + ---------- + internal_hd_idletime : int + Internal hard drive idle time in minutes. Default is `20`. + stat_deep_sleep : bool + Enable or disable SATA deep sleep. Default is `True`. + ignore_netbios_broadcast : bool + Enable or disable ignoring NetBIOS broadcast. Default is `False`. + usb_idletime : int + USB idle time in minutes. Default is `0`. + enable_log : bool + Enable or disable logging. Default is `False`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Hardware.Hibernation' info = self.gen_list[api_name] @@ -685,43 +708,44 @@ def set_hibernation_settings(self, 'enable_log': enable_log } return self.request_data(api_name, api_path, req_param) - + def set_ups_settings(self, - enable: bool = False, mode: str = "SLAVE", delay_time: str = "-1", - snmp_auth_key_dirty: bool = False, snmp_privacy_key_dirty: bool = False, - ) -> dict: - """Set UPS settings. - - Parameters - ---------- - enable : bool - Enable or disable UPS. Default is `False`. - mode : str - UPS mode. Default is `SLAVE`. - TODO: Determine valid values for this parameter. - delay_time : str - Delay time in seconds. Default is `-1`. - TODO: Determine valid values for this parameter. - snmp_auth_key_dirty : bool - SNMP authentication key dirty flag. Default is `False`. - snmp_privacy_key_dirty : bool - SNMP privacy key dirty flag. Default is `False`. - - Returns - ------- - dict - Return success status. - - Example return - ---------- - ```json - { - "data": { - "success": true - }, + enable: bool = False, mode: str = "SLAVE", delay_time: str = "-1", + snmp_auth_key_dirty: bool = False, snmp_privacy_key_dirty: bool = False, + ) -> dict: + """ + Set UPS settings. + + Parameters + ---------- + enable : bool + Enable or disable UPS. Default is `False`. + mode : str + UPS mode. Default is `SLAVE`. + TODO: Determine valid values for this parameter. + delay_time : str + Delay time in seconds. Default is `-1`. + TODO: Determine valid values for this parameter. + snmp_auth_key_dirty : bool + SNMP authentication key dirty flag. Default is `False`. + snmp_privacy_key_dirty : bool + SNMP privacy key dirty flag. Default is `False`. + + Returns + ------- + dict + Return success status. + + Examples + -------- + ```json + { + "data": { "success": true - } - ``` + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.ExternalDevice.UPS' info = self.gen_list[api_name] @@ -736,59 +760,61 @@ def set_ups_settings(self, 'snmp_privacy_key_dirty': snmp_privacy_key_dirty } return self.request_data(api_name, api_path, req_param) - + def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: List[dict] = []) -> dict: - """Set the power schedule, poweron tasks and poweroff tasks - - Parameters - ---------- - poweron_tasks : List[dict], optional - List of tasks for power on. Defaults to `[]` - Example of a task: - ```python - { - "enabled": True, # Enable or not the task - "hour": 13, # Hour 0-23 - "min": 59, # Minutes 0-59 - "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) - } - ``` - poweroff_tasks : List[dict], optional - List of tasks for power off. Defaults to `[]` - Example of a task: - ```python - { - "enabled": True, # Enable or not the task - "hour": 13, # Hour 0-23 - "min": 59, # Minutes 0-59 - "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) - } - ``` - Returns - ------- - dict - List of tasks in power schedule - - Example return - ---------- - ```json + """ + Set the power schedule, poweron tasks and poweroff tasks. + + Parameters + ---------- + poweron_tasks : List[dict], optional + List of tasks for power on. Defaults to `[]` + Example of a task: + ```python { - "data": { - "poweroff_tasks": [], - "poweron_tasks": [ - { - "enabled": true, - "hour": 0, - "min": 0, - "weekdays": "1,2,3,4,5" - } - ] - }, - "success": true + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) + } + ``` + poweroff_tasks : List[dict], optional + List of tasks for power off. Defaults to `[]` + Example of a task: + ```python + { + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thrusday, Friday, Saturday) } ``` + + Returns + ------- + dict + List of tasks in power schedule. + + Examples + -------- + ```json + { + "data": { + "poweroff_tasks": [], + "poweron_tasks": [ + { + "enabled": true, + "hour": 0, + "min": 0, + "weekdays": "1,2,3,4,5" + } + ] + }, + "success": true + } + ``` """ - + api_name = 'SYNO.Core.Hardware.PowerSchedule' info = self.core_list[api_name] api_path = info["path"] @@ -800,5 +826,5 @@ def set_power_schedule(self, poweron_tasks: List[dict] = [], poweroff_tasks: Lis } return self.request_data(api_name, api_path, req_param) - - pass \ No newline at end of file + + pass diff --git a/synology_api/DSM/ControlPanel/IndexingService.py b/synology_api/DSM/ControlPanel/IndexingService.py index 1ef88ba5..ae80b1f5 100644 --- a/synology_api/DSM/ControlPanel/IndexingService.py +++ b/synology_api/DSM/ControlPanel/IndexingService.py @@ -1,53 +1,58 @@ +""" +Indexing service class for Synology DSM. +""" + from synology_api import base_api + class IndexingService(base_api.BaseApi): """ Indexing service class for interacting with Synology DSM Indexing service settings. - + Supported methods: - Getters: - - - Setters: + - Setters: """ - + def get_indexed_folders(self) -> dict: - """Get indexed folders. - - Returns - ------- - dict - Return list of folders indexed by the indexing service. - - Example return - ---------- - ```json - { - "data": { - "folders": [ - { - "default": false, - "exist": true, - "name": "Films", - "path": "/Films", - "types": [ - "video" - ] - }, - { - "default": false, - "exist": true, - "name": "Series", - "path": "/Series", - "types": [ - "video" - ] - } - ] - }, - "success": true - } - ``` + """ + Get indexed folders. + + Returns + ------- + dict + Return list of folders indexed by the indexing service. + + Examples + -------- + ```json + { + "data": { + "folders": [ + { + "default": false, + "exist": true, + "name": "Films", + "path": "/Films", + "types": [ + "video" + ] + }, + { + "default": false, + "exist": true, + "name": "Series", + "path": "/Series", + "types": [ + "video" + ] + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.MediaIndexing.IndexFolder' info = self.gen_list[api_name] @@ -57,25 +62,26 @@ def get_indexed_folders(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_media_indexing_status(self) -> dict: - """Get media indexing status. - - Returns - ------- - dict - Return the status of the media indexing service. - - Example return - ---------- - ```json - { - "data": { - "reindexing": false - }, - "success": true - } - ``` + """ + Get media indexing status. + + Returns + ------- + dict + Return the status of the media indexing service. + + Examples + -------- + ```json + { + "data": { + "reindexing": false + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.MediaIndexing' info = self.gen_list[api_name] @@ -85,26 +91,27 @@ def get_media_indexing_status(self) -> dict: 'method': 'status' } return self.request_data(api_name, api_path, req_param) - + def get_thumbnail_quality_settings(self) -> dict: - """Get thumbnail quality settings. - - Returns - ------- - dict - Return the thumbnail quality settings. - - Example return - ---------- - ```json - { - "data": { - "packages": [], - "thumbnail_quality": "normal" - }, - "success": true - } - ``` + """ + Get thumbnail quality settings. + + Returns + ------- + dict + Return the thumbnail quality settings. + + Examples + -------- + ```json + { + "data": { + "packages": [], + "thumbnail_quality": "normal" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.MediaIndexing.ThumbnailQuality' info = self.gen_list[api_name] @@ -114,38 +121,39 @@ def get_thumbnail_quality_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - - def get_shuduler_settings(self) -> dict: - """Get scheduler settings. - - Returns - ------- - dict - Return the scheduler settings of the indexing service. - - Example return - ---------- - ```json - { - "data": { - "duration": 1, - "manual_action_by_user": "none", - "mode": "schedule", - "start": { - "hour": 0 - }, - "week": [ - true, - true, - true, - true, - true, - true, - true - ] + + def get_scheduler_settings(self) -> dict: + """ + Get scheduler settings. + + Returns + ------- + dict + Return the scheduler settings of the indexing service. + + Examples + -------- + ```json + { + "data": { + "duration": 1, + "manual_action_by_user": "none", + "mode": "schedule", + "start": { + "hour": 0 }, - "success": true, - ``` + "week": [ + true, + true, + true, + true, + true, + true, + true + ] + }, + "success": true, + ``` """ api_name = 'SYNO.Core.MediaIndexing.Scheduler' info = self.gen_list[api_name] @@ -155,49 +163,49 @@ def get_shuduler_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_indexed_folders(self, folders: list) -> dict: - """Set indexed folders. - - Parameters - ---------- - folders : list - A list of dictionaries representing the folders to be indexed. Each dictionary should contain: - - `path`: The path of the folder to be indexed. - - `name`: The name of the folder. - - `default`: A boolean indicating if this is a default folder. Should be `False` - - `types`: A list of media types to index in the folder (e.g., `["video"]`). Fiels are `photo`, `video`, `music`. - - example: - ```json - [ - { - "path": "/Films", - "name": "Films", - "default": false, - "types": ["video"] - }, - { - "path": "/Series", - "name": "Series", - "default": false, - "types": ["video"] - } - ] - ``` - - Returns - ------- - dict - Return the result of the operation. - - Example return - ---------- + """ + Set indexed folders. + + Parameters + ---------- + folders : list + A list of dictionaries representing the folders to be indexed. Each dictionary should contain: + - `path`: The path of the folder to be indexed. + - `name`: The name of the folder. + - `default`: A boolean indicating if this is a default folder. Should be `False` + - `types`: A list of media types to index in the folder (e.g., `["video"]`). Fields are `photo`, `video`, `music`. + example: ```json - { - "success": true - } + [ + { + "path": "/Films", + "name": "Films", + "default": false, + "types": ["video"] + }, + { + "path": "/Series", + "name": "Series", + "default": false, + "types": ["video"] + } + ] ``` + + Returns + ------- + dict + Return the result of the operation. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.Core.MediaIndexing.IndexFolder' info = self.gen_list[api_name] @@ -208,30 +216,31 @@ def set_indexed_folders(self, folders: list) -> dict: 'folders': folders } return self.request_data(api_name, api_path, req_param) - + def set_thumbnail_quality_settings(self, quality: str = "normal") -> dict: - """Set thumbnail quality settings. - - Parameters - ---------- - quality : str - The desired thumbnail quality setting. Options are `normal`, `high`. Default to `normal`. - - Returns - ------- - dict - Return the result of the operation. - - Example return - ---------- - ```json - { - "data": { - "thumbnail_quality": "normal" - }, - "success": true - } - ``` + """ + Set thumbnail quality settings. + + Parameters + ---------- + quality : str + The desired thumbnail quality setting. Options are `normal`, `high`. Default to `normal`. + + Returns + ------- + dict + Return the result of the operation. + + Examples + -------- + ```json + { + "data": { + "thumbnail_quality": "normal" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.MediaIndexing.ThumbnailQuality' info = self.gen_list[api_name] @@ -242,54 +251,55 @@ def set_thumbnail_quality_settings(self, quality: str = "normal") -> dict: 'quality': quality } return self.request_data(api_name, api_path, req_param) - + def set_shudler_settings(self, mode: str = "always", start_hour: int = 0, duration: int = 1, week: list = [True, True, True, True, True, True, True]) -> dict: - """Set scheduler settings. - - Parameters - ---------- - mode : str - The scheduling mode. Options are `schedule`, `always`. Default to `always`. - start_hour : int - The hour to start the indexing service. Default to `0`. Not used if `mode` is set to `always`. - duration : int - The duration in hours for the indexing service. Default to `1`. Not used if `mode` is set to `always`. - week : list - A list of booleans indicating which days of the week the service should run. Default to `[True, True, True, True, True, True, True]`. Not used if `mode` is set to `always`. - - Returns - ------- - dict - Return the result of the operation. - - Example return - ---------- - ```json - { - "data": { - "duration": 1, - "manual_action_by_user": "none", - "mode": "schedule", - "start": { - "hour": 0 - }, - "week": [ - true, - true, - true, - true, - true, - true, - true - ] + """ + Set scheduler settings. + + Parameters + ---------- + mode : str + The scheduling mode. Options are `schedule`, `always`. Default to `always`. + start_hour : int + The hour to start the indexing service. Default to `0`. Not used if `mode` is set to `always`. + duration : int + The duration in hours for the indexing service. Default to `1`. Not used if `mode` is set to `always`. + week : list + A list of booleans indicating which days of the week the service should run. Default to `[True, True, True, True, True, True, True]`. Not used if `mode` is set to `always`. + + Returns + ------- + dict + Return the result of the operation. + + Examples + -------- + ```json + { + "data": { + "duration": 1, + "manual_action_by_user": "none", + "mode": "schedule", + "start": { + "hour": 0 }, - "success": true - } - ``` + "week": [ + true, + true, + true, + true, + true, + true, + true + ] + }, + "success": true + } + ``` """ if week is None: week = [True] * 7 - + api_name = 'SYNO.Core.MediaIndexing.Scheduler' info = self.gen_list[api_name] api_path = info['path'] @@ -302,6 +312,5 @@ def set_shudler_settings(self, mode: str = "always", start_hour: int = 0, durati 'week': week } return self.request_data(api_name, api_path, req_param) - - - pass \ No newline at end of file + + pass diff --git a/synology_api/DSM/ControlPanel/InfoCenter.py b/synology_api/DSM/ControlPanel/InfoCenter.py index 38fc2cf8..1fea0059 100644 --- a/synology_api/DSM/ControlPanel/InfoCenter.py +++ b/synology_api/DSM/ControlPanel/InfoCenter.py @@ -1,64 +1,69 @@ +""" +Info center class for Synology DSM Info center settings. +""" + from synology_api import base_api + class InfoCenter(base_api.BaseApi): """ Info center class for interacting with Synology DSM Info center settings. - + Supported methods: - Getters: - - - Setters: + - Setters: """ - + def get_system_info(self) -> dict: - """Get system information. - - Returns - ------- - dict - Return system information including CPU, memory, and disk usage. - - Example return - ---------- - ```json - { - "data": { - "cpu_clock_speed": 2600, - "cpu_cores": "2", - "cpu_family": "Ryzen", - "cpu_series": "R1600", - "cpu_vendor": "AMD", - "enabled_ntp": true, - "external_pci_slot_info": [ - { - "Occupied": "no", - "Recognized": "no", - "cardName": "-", - "slot": "1" - } - ], - "firmware_date": "2025/01/20", - "firmware_ver": "DSM 7.2.2-72806 Update 3", - "model": "DS723+", - "ntp_server": "time.google.com", - "ram_size": 2048, - "sata_dev": [], - "serial": "YOUR-SERIAL-NUMBER", - "support_esata": "yes", - "sys_temp": 47, - "sys_tempwarn": false, - "systempwarn": false, - "temperature_warning": false, - "time": "2025-07-06 00:23:44", - "time_zone": "Amsterdam", - "time_zone_desc": "(GMT+01:00) Amsterdam, Berlin, Rome, Stockholm, Vienna", - "up_time": "49:46:21", - "usb_dev": [] - }, - "success": true, - } - ``` + """ + Get system information. + + Returns + ------- + dict + Return system information including CPU, memory, and disk usage. + + Examples + -------- + ```json + { + "data": { + "cpu_clock_speed": 2600, + "cpu_cores": "2", + "cpu_family": "Ryzen", + "cpu_series": "R1600", + "cpu_vendor": "AMD", + "enabled_ntp": true, + "external_pci_slot_info": [ + { + "Occupied": "no", + "Recognized": "no", + "cardName": "-", + "slot": "1" + } + ], + "firmware_date": "2025/01/20", + "firmware_ver": "DSM 7.2.2-72806 Update 3", + "model": "DS723+", + "ntp_server": "time.google.com", + "ram_size": 2048, + "sata_dev": [], + "serial": "YOUR-SERIAL-NUMBER", + "support_esata": "yes", + "sys_temp": 47, + "sys_tempwarn": false, + "systempwarn": false, + "temperature_warning": false, + "time": "2025-07-06 00:23:44", + "time_zone": "Amsterdam", + "time_zone_desc": "(GMT+01:00) Amsterdam, Berlin, Rome, Stockholm, Vienna", + "up_time": "49:46:21", + "usb_dev": [] + }, + "success": true, + } + ``` """ api_name = 'SYNO.Core.System' info = self.gen_list[api_name] @@ -68,69 +73,70 @@ def get_system_info(self) -> dict: 'method': 'info' } return self.request_data(api_name, api_path, req_param) - + def get_network_info(self) -> dict: - """Get network information. - - Returns - ------- - dict - Return network information including interfaces, IP addresses, and DNS settings. - - Example return - ---------- - ```json - { - "data": { - "dns": "YOUR-DNS", - "enabled_domain": false, - "enabled_samba": true, - "gateway": "YOUR-GATEWAY", - "hostname": "YOUR-HOSTNAME", - "nif": [ - { - "addr": "YOUR-IP-ADDRESS", - "duplex": true, - "id": "ovs_eth0", - "ipv6": [ - { - "addr": "YOUR-IPv6-ADDRESS", - "prefix_len": 64, - "scope": "global" - }, - { - "addr": "YOUR-IPv6-ADDRESS", - "prefix_len": 64, - "scope": "link" - } - ], - "mac": "YOUR-MAC-ADDRESS", - "mask": "255.255.255.0", - "mtu": 1500, - "speed": 1000, - "status": "connected", - "type": "ovseth", - "use_dhcp": true - }, - { - "addr": "YOUR-SECOND-IP-ADDRESS", - "duplex": true, - "id": "ovs_eth1", - "mac": "YOUR-SECOND-MAC-ADDRESS", - "mask": "255.255.0.0", - "mtu": 1500, - "speed": -1, - "status": "disconnected", - "type": "ovseth", - "use_dhcp": true - } - ], - "wins": "", - "workgroup": "WORKGROUP" - }, - "success": true - } - ``` + """ + Get network information. + + Returns + ------- + dict + Return network information including interfaces, IP addresses, and DNS settings. + + Examples + -------- + ```json + { + "data": { + "dns": "YOUR-DNS", + "enabled_domain": false, + "enabled_samba": true, + "gateway": "YOUR-GATEWAY", + "hostname": "YOUR-HOSTNAME", + "nif": [ + { + "addr": "YOUR-IP-ADDRESS", + "duplex": true, + "id": "ovs_eth0", + "ipv6": [ + { + "addr": "YOUR-IPv6-ADDRESS", + "prefix_len": 64, + "scope": "global" + }, + { + "addr": "YOUR-IPv6-ADDRESS", + "prefix_len": 64, + "scope": "link" + } + ], + "mac": "YOUR-MAC-ADDRESS", + "mask": "255.255.255.0", + "mtu": 1500, + "speed": 1000, + "status": "connected", + "type": "ovseth", + "use_dhcp": true + }, + { + "addr": "YOUR-SECOND-IP-ADDRESS", + "duplex": true, + "id": "ovs_eth1", + "mac": "YOUR-SECOND-MAC-ADDRESS", + "mask": "255.255.0.0", + "mtu": 1500, + "speed": -1, + "status": "disconnected", + "type": "ovseth", + "use_dhcp": true + } + ], + "wins": "", + "workgroup": "WORKGROUP" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.System' info = self.gen_list[api_name] @@ -141,242 +147,243 @@ def get_network_info(self) -> dict: 'type': 'network' } return self.request_data(api_name, api_path, req_param) - + def get_storage_info(self) -> dict: - """Get storage information. - - Returns - ------- - dict - Return storage information including volumes, disks, and RAID status. - - Example return - ---------- - ```json - { - "data": { - "hdd_info": [ - { - "action": { - "alert": false, - "notification": false, - "selectable": true, - "show_lifetime_chart": true - }, - "action_status": { - "action_name": "idle", - "action_progress": "" - }, - "action_status_category": "processing", - "action_status_key": "idle", - "adv_progress": "", - "adv_status": "not_support", - "allocation_role": "reuse_1", - "below_remain_life_mail_notify_thr": false, - "below_remain_life_show_thr": false, - "below_remain_life_thr": false, - "compatibility": "support", - "container": { - "order": 0, - "str": "DS723+", - "supportPwrBtnDisable": false, - "type": "internal" - }, - "container_id": 0, - "device": "/dev/sata1", - "disable_secera": false, - "diskType": "SATA", - "disk_code": "", - "disk_location": "Main", - "drive_status_category": "health", - "drive_status_key": "normal", - "erase_time": 450, - "firm": "SC60", - "firmware_status": "-", - "has_system": true, - "hide_info": [], - "i18nNamingInfo": "[\"dsm:volume:volume_disk\",\" \",\"1\"]", - "id": "sata1", - "ihm_testing": false, - "is4Kn": false, - "isSsd": false, - "isSynoDrive": false, - "isSynoPartition": true, - "is_bundle_ssd": false, - "is_erasing": false, - "longName": "Drive 1", - "m2_pool_support": false, - "model": "ST4000VN006-3CW104", - "name": "Drive 1", - "num_id": 1, - "order": 1, - "overview_status": "normal", - "pciSlot": -1, - "perf_testing": false, - "portType": "normal", - "remain_life": { - "trustable": true, - "value": -1 - }, - "remain_life_danger": false, - "remote_info": { - "compatibility": "disabled", - "unc": 0 - }, - "sb_days_left": 0, - "sb_days_left_below_show_thres": false, - "sb_days_left_critical": false, - "sb_days_left_warning": false, - "serial": "YOUR-FIRST-SERIAL-NUMBER", - "size_total": "4000787030016", - "slot_id": 1, - "smart_progress": "", - "smart_status": "normal", - "smart_test_limit": 0, - "smart_test_support": true, - "smart_testing": false, - "ssd_unhealth_reason": "none", - "status": "normal", - "summary_status_category": "health", - "summary_status_key": "normal", - "temp": 35, - "testing_progress": "", - "testing_type": "idle", - "tray_status": "join", - "ui_serial": "YOUR-FIRST-SERIAL-NUMBER", - "unc": 0, - "used_by": "reuse_1", - "vendor": "Seagate", - "wcache_force_off": false, - "wcache_force_on": false, - "wdda_support": false + """ + Get storage information. + + Returns + ------- + dict + Return storage information including volumes, disks, and RAID status. + + Examples + -------- + ```json + { + "data": { + "hdd_info": [ + { + "action": { + "alert": false, + "notification": false, + "selectable": true, + "show_lifetime_chart": true }, - { - "action": { - "alert": false, - "notification": false, - "selectable": true, - "show_lifetime_chart": true - }, - "action_status": { - "action_name": "idle", - "action_progress": "" - }, - "action_status_category": "processing", - "action_status_key": "idle", - "adv_progress": "", - "adv_status": "not_support", - "allocation_role": "reuse_1", - "below_remain_life_mail_notify_thr": false, - "below_remain_life_show_thr": false, - "below_remain_life_thr": false, - "compatibility": "support", - "container": { - "order": 0, - "str": "DS723+", - "supportPwrBtnDisable": false, - "type": "internal" - }, - "container_id": 0, - "device": "/dev/sata2", - "disable_secera": false, - "diskType": "SATA", - "disk_code": "", - "disk_location": "Main", - "drive_status_category": "health", - "drive_status_key": "normal", - "erase_time": 462, - "firm": "SC60", - "firmware_status": "-", - "has_system": true, - "hide_info": [], - "i18nNamingInfo": "[\"dsm:volume:volume_disk\",\" \",\"2\"]", - "id": "sata2", - "ihm_testing": false, - "is4Kn": false, - "isSsd": false, - "isSynoDrive": false, - "isSynoPartition": true, - "is_bundle_ssd": false, - "is_erasing": false, - "longName": "Drive 2", - "m2_pool_support": false, - "model": "ST4000VN006-3CW104", - "name": "Drive 2", - "num_id": 2, - "order": 2, - "overview_status": "normal", - "pciSlot": -1, - "perf_testing": false, - "portType": "normal", - "remain_life": { - "trustable": true, - "value": -1 - }, - "remain_life_danger": false, - "remote_info": { - "compatibility": "disabled", - "unc": 0 - }, - "sb_days_left": 0, - "sb_days_left_below_show_thres": false, - "sb_days_left_critical": false, - "sb_days_left_warning": false, - "serial": "YOUR-SECOND-SERIAL-NUMBER", - "size_total": "4000787030016", - "slot_id": 2, - "smart_progress": "", - "smart_status": "normal", - "smart_test_limit": 0, - "smart_test_support": true, - "smart_testing": false, - "ssd_unhealth_reason": "none", - "status": "normal", - "summary_status_category": "health", - "summary_status_key": "normal", - "temp": 37, - "testing_progress": "", - "testing_type": "idle", - "tray_status": "join", - "ui_serial": "YOUR-SECOND-SERIAL-NUMBER", - "unc": 0, - "used_by": "reuse_1", - "vendor": "Seagate", - "wcache_force_off": false, - "wcache_force_on": false, - "wdda_support": false - } - ], - "vol_info": [ - { - "desc": "", - "inode_free": "0", - "inode_total": "0", - "is_encrypted": false, - "name": "volume_1", - "status": "normal", - "total_size": "206158430208", - "used_size": "16905019392", - "vol_desc": "Apps", - "volume": "volume_1" + "action_status": { + "action_name": "idle", + "action_progress": "" + }, + "action_status_category": "processing", + "action_status_key": "idle", + "adv_progress": "", + "adv_status": "not_support", + "allocation_role": "reuse_1", + "below_remain_life_mail_notify_thr": false, + "below_remain_life_show_thr": false, + "below_remain_life_thr": false, + "compatibility": "support", + "container": { + "order": 0, + "str": "DS723+", + "supportPwrBtnDisable": false, + "type": "internal" + }, + "container_id": 0, + "device": "/dev/sata1", + "disable_secera": false, + "diskType": "SATA", + "disk_code": "", + "disk_location": "Main", + "drive_status_category": "health", + "drive_status_key": "normal", + "erase_time": 450, + "firm": "SC60", + "firmware_status": "-", + "has_system": true, + "hide_info": [], + "i18nNamingInfo": "[\"dsm:volume:volume_disk\",\" \",\"1\"]", + "id": "sata1", + "ihm_testing": false, + "is4Kn": false, + "isSsd": false, + "isSynoDrive": false, + "isSynoPartition": true, + "is_bundle_ssd": false, + "is_erasing": false, + "longName": "Drive 1", + "m2_pool_support": false, + "model": "ST4000VN006-3CW104", + "name": "Drive 1", + "num_id": 1, + "order": 1, + "overview_status": "normal", + "pciSlot": -1, + "perf_testing": false, + "portType": "normal", + "remain_life": { + "trustable": true, + "value": -1 + }, + "remain_life_danger": false, + "remote_info": { + "compatibility": "disabled", + "unc": 0 }, - { - "desc": "", - "inode_free": "0", - "inode_total": "0", - "is_encrypted": false, - "name": "volume_2", - "status": "normal", - "total_size": "3623234412544", - "used_size": "1154716925952", - "vol_desc": "Stockage", - "volume": "volume_2" - } - ] - }, - "success": true - } - ``` + "sb_days_left": 0, + "sb_days_left_below_show_thres": false, + "sb_days_left_critical": false, + "sb_days_left_warning": false, + "serial": "YOUR-FIRST-SERIAL-NUMBER", + "size_total": "4000787030016", + "slot_id": 1, + "smart_progress": "", + "smart_status": "normal", + "smart_test_limit": 0, + "smart_test_support": true, + "smart_testing": false, + "ssd_unhealth_reason": "none", + "status": "normal", + "summary_status_category": "health", + "summary_status_key": "normal", + "temp": 35, + "testing_progress": "", + "testing_type": "idle", + "tray_status": "join", + "ui_serial": "YOUR-FIRST-SERIAL-NUMBER", + "unc": 0, + "used_by": "reuse_1", + "vendor": "Seagate", + "wcache_force_off": false, + "wcache_force_on": false, + "wdda_support": false + }, + { + "action": { + "alert": false, + "notification": false, + "selectable": true, + "show_lifetime_chart": true + }, + "action_status": { + "action_name": "idle", + "action_progress": "" + }, + "action_status_category": "processing", + "action_status_key": "idle", + "adv_progress": "", + "adv_status": "not_support", + "allocation_role": "reuse_1", + "below_remain_life_mail_notify_thr": false, + "below_remain_life_show_thr": false, + "below_remain_life_thr": false, + "compatibility": "support", + "container": { + "order": 0, + "str": "DS723+", + "supportPwrBtnDisable": false, + "type": "internal" + }, + "container_id": 0, + "device": "/dev/sata2", + "disable_secera": false, + "diskType": "SATA", + "disk_code": "", + "disk_location": "Main", + "drive_status_category": "health", + "drive_status_key": "normal", + "erase_time": 462, + "firm": "SC60", + "firmware_status": "-", + "has_system": true, + "hide_info": [], + "i18nNamingInfo": "[\"dsm:volume:volume_disk\",\" \",\"2\"]", + "id": "sata2", + "ihm_testing": false, + "is4Kn": false, + "isSsd": false, + "isSynoDrive": false, + "isSynoPartition": true, + "is_bundle_ssd": false, + "is_erasing": false, + "longName": "Drive 2", + "m2_pool_support": false, + "model": "ST4000VN006-3CW104", + "name": "Drive 2", + "num_id": 2, + "order": 2, + "overview_status": "normal", + "pciSlot": -1, + "perf_testing": false, + "portType": "normal", + "remain_life": { + "trustable": true, + "value": -1 + }, + "remain_life_danger": false, + "remote_info": { + "compatibility": "disabled", + "unc": 0 + }, + "sb_days_left": 0, + "sb_days_left_below_show_thres": false, + "sb_days_left_critical": false, + "sb_days_left_warning": false, + "serial": "YOUR-SECOND-SERIAL-NUMBER", + "size_total": "4000787030016", + "slot_id": 2, + "smart_progress": "", + "smart_status": "normal", + "smart_test_limit": 0, + "smart_test_support": true, + "smart_testing": false, + "ssd_unhealth_reason": "none", + "status": "normal", + "summary_status_category": "health", + "summary_status_key": "normal", + "temp": 37, + "testing_progress": "", + "testing_type": "idle", + "tray_status": "join", + "ui_serial": "YOUR-SECOND-SERIAL-NUMBER", + "unc": 0, + "used_by": "reuse_1", + "vendor": "Seagate", + "wcache_force_off": false, + "wcache_force_on": false, + "wdda_support": false + } + ], + "vol_info": [ + { + "desc": "", + "inode_free": "0", + "inode_total": "0", + "is_encrypted": false, + "name": "volume_1", + "status": "normal", + "total_size": "206158430208", + "used_size": "16905019392", + "vol_desc": "Apps", + "volume": "volume_1" + }, + { + "desc": "", + "inode_free": "0", + "inode_total": "0", + "is_encrypted": false, + "name": "volume_2", + "status": "normal", + "total_size": "3623234412544", + "used_size": "1154716925952", + "vol_desc": "Stockage", + "volume": "volume_2" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Storage' info = self.gen_list[api_name] @@ -387,186 +394,187 @@ def get_storage_info(self) -> dict: 'type': 'storage_v2' } return self.request_data(api_name, api_path, req_param) - + def get_services_status(self) -> dict: - """Get services status. - - Returns - ------- - dict - Return the status of various services running on the Synology DSM. - - Example return - ---------- - ```json - { - "data": { - "service": [ - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "helptoc:winmacnfs_mac", - "enable_status": "disabled", - "service_id": "atalk" + """ + Get services status. + + Returns + ------- + dict + Return the status of various services running on the Synology DSM. + + Examples + -------- + ```json + { + "data": { + "service": [ + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "network:bonjourPrinter_subject", - "enable_status": "enabled", - "service_id": "bonjour" + "display_name_section_key": "helptoc:winmacnfs_mac", + "enable_status": "disabled", + "service_id": "atalk" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "helptoc:ntp_service", - "enable_status": "enabled", - "service_id": "chronyd" + "display_name_section_key": "network:bonjourPrinter_subject", + "enable_status": "enabled", + "service_id": "bonjour" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "service:cups_printer_daemon", - "enable_status": "static", - "service_id": "cupsd" + "display_name_section_key": "helptoc:ntp_service", + "enable_status": "enabled", + "service_id": "chronyd" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "tree:leaf_ftp", - "enable_status": "disabled", - "service_id": "ftp-pure" + "display_name_section_key": "service:cups_printer_daemon", + "enable_status": "static", + "service_id": "cupsd" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "tree:leaf_ftpes", - "enable_status": "disabled", - "service_id": "ftp-ssl" + "display_name_section_key": "tree:leaf_ftp", + "enable_status": "disabled", + "service_id": "ftp-pure" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "remote_key:kmip_tab_title", - "enable_status": "disabled", - "service_id": "kmip-server" + "display_name_section_key": "tree:leaf_ftpes", + "enable_status": "disabled", + "service_id": "ftp-ssl" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "nfs:nfs_title", - "enable_status": "disabled", - "service_id": "nfs-server" + "display_name_section_key": "remote_key:kmip_tab_title", + "enable_status": "disabled", + "service_id": "kmip-server" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "tree:leaf_iscsi", - "enable_status": "static", - "service_id": "pkg-iscsi" + "display_name_section_key": "nfs:nfs_title", + "enable_status": "disabled", + "service_id": "nfs-server" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "helptoc:winmacnfs_win", - "enable_status": "enabled", - "service_id": "pkg-synosamba-smbd" + "display_name_section_key": "tree:leaf_iscsi", + "enable_status": "static", + "service_id": "pkg-iscsi" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "service:wstransfer_title", - "enable_status": "enabled", - "service_id": "pkg-synosamba-wstransfer-genconf" + "display_name_section_key": "helptoc:winmacnfs_win", + "enable_status": "enabled", + "service_id": "pkg-synosamba-smbd" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "service:service_rsync", - "enable_status": "enabled", - "service_id": "rsyncd" + "display_name_section_key": "service:wstransfer_title", + "enable_status": "enabled", + "service_id": "pkg-synosamba-wstransfer-genconf" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "tree:leaf_sftp", - "enable_status": "disabled", - "service_id": "sftp" + "display_name_section_key": "service:service_rsync", + "enable_status": "enabled", + "service_id": "rsyncd" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "SNMP", - "enable_status": "static", - "service_id": "snmpd" + "display_name_section_key": "tree:leaf_sftp", + "enable_status": "disabled", + "service_id": "sftp" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "firewall:firewall_service_opt_ssh", - "enable_status": "enabled", - "service_id": "ssh-shell" + "display_name_section_key": "SNMP", + "enable_status": "static", + "service_id": "snmpd" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "active" - }, - "display_name_section_key": "about:dsm", - "enable_status": "static", - "service_id": "synoscgi" + "display_name_section_key": "firewall:firewall_service_opt_ssh", + "enable_status": "enabled", + "service_id": "ssh-shell" + }, + { + "additional": { + "active_status": "active" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "firewall:firewall_service_opt_telnet", - "enable_status": "disabled", - "service_id": "telnetd" + "display_name_section_key": "about:dsm", + "enable_status": "static", + "service_id": "synoscgi" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "ftp:tftp_title", - "enable_status": "disabled", - "service_id": "tftp" + "display_name_section_key": "firewall:firewall_service_opt_telnet", + "enable_status": "disabled", + "service_id": "telnetd" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "helptoc:power_ups", - "enable_status": "disabled", - "service_id": "ups-net" + "display_name_section_key": "ftp:tftp_title", + "enable_status": "disabled", + "service_id": "tftp" + }, + { + "additional": { + "active_status": "inactive" }, - { - "additional": { - "active_status": "inactive" - }, - "display_name_section_key": "helptoc:power_ups", - "enable_status": "static", - "service_id": "ups-usb" - } - ] - }, - "success": true, - } - ``` + "display_name_section_key": "helptoc:power_ups", + "enable_status": "disabled", + "service_id": "ups-net" + }, + { + "additional": { + "active_status": "inactive" + }, + "display_name_section_key": "helptoc:power_ups", + "enable_status": "static", + "service_id": "ups-usb" + } + ] + }, + "success": true, + } + ``` """ api_name = 'SYNO.Core.Service' info = self.gen_list[api_name] @@ -577,6 +585,5 @@ def get_services_status(self) -> dict: 'additional': ['active_status'] } return self.request_data(api_name, api_path, req_param) - - - pass \ No newline at end of file + + pass diff --git a/synology_api/DSM/ControlPanel/LoginPortal.py b/synology_api/DSM/ControlPanel/LoginPortal.py index 6c29bc1f..935a3d86 100644 --- a/synology_api/DSM/ControlPanel/LoginPortal.py +++ b/synology_api/DSM/ControlPanel/LoginPortal.py @@ -1,4 +1,11 @@ +""" +Login portal class for Synology DSM. +""" from synology_api import base_api + class LoginPortal(base_api.BaseApi): - pass \ No newline at end of file + """ + Login portal class for Synology DSM. + """ + pass diff --git a/synology_api/DSM/ControlPanel/Network.py b/synology_api/DSM/ControlPanel/Network.py index 338685fa..9a221ad6 100644 --- a/synology_api/DSM/ControlPanel/Network.py +++ b/synology_api/DSM/ControlPanel/Network.py @@ -1,6 +1,11 @@ +""" +Network class for Synology DSM network settings. +""" + from synology_api import base_api import json + class Network(base_api.BaseApi): """ Network class for interacting with Synology DSM network settings. @@ -27,44 +32,45 @@ class Network(base_api.BaseApi): - Set proxy settings - Set ethernet interfaces """ - + def get_general_settings(self) -> dict: - """Get general network settings. - - Returns - ------- - dict - General network settings. - - Example return - ---------- - ```json - { - "data": { - "arp_ignore": true, - "dns_manual": true, - "dns_primary": "103.86.96.100", - "dns_secondary": "192.168.1.1", - "enable_ip_conflict_detect": true, - "enable_windomain": false, - "gateway": "192.168.1.1", - "gateway_info": { - "ifname": "ovs_eth0", - "ip": "192.168.1.14", - "mask": "255.255.255.0", - "status": "connected", - "type": "ovseth", - "use_dhcp": true - }, - "ipv4_first": false, - "multi_gateway": false, - "server_name": "SERVER-NAME", - "use_dhcp_domain": true, - "v6gateway": "fe80::670:56ff:fe48:1f94" + """ + Get general network settings. + + Returns + ------- + dict + General network settings. + + Examples + -------- + ```json + { + "data": { + "arp_ignore": true, + "dns_manual": true, + "dns_primary": "103.86.96.100", + "dns_secondary": "192.168.1.1", + "enable_ip_conflict_detect": true, + "enable_windomain": false, + "gateway": "192.168.1.1", + "gateway_info": { + "ifname": "ovs_eth0", + "ip": "192.168.1.14", + "mask": "255.255.255.0", + "status": "connected", + "type": "ovseth", + "use_dhcp": true }, - "success": true - } - ``` + "ipv4_first": false, + "multi_gateway": false, + "server_name": "SERVER-NAME", + "use_dhcp_domain": true, + "v6gateway": "fe80::670:56ff:fe48:1f94" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Network' info = self.gen_list[api_name] @@ -74,14 +80,15 @@ def get_general_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_general_settings( - self, server_name: str, dns_manual: bool, dns_primary: str, - dns_secondary: str, arp_ignore: bool, multi_gateway: bool, - ipv4_first: bool, enable_ip_conflict_detect: bool, use_dhcp_domain: bool - ) -> dict: - """Set general network settings. - + self, server_name: str, dns_manual: bool, dns_primary: str, + dns_secondary: str, arp_ignore: bool, multi_gateway: bool, + ipv4_first: bool, enable_ip_conflict_detect: bool, use_dhcp_domain: bool + ) -> dict: + """ + Set general network settings. + Parameters ---------- server_name : str @@ -102,14 +109,14 @@ def set_general_settings( Whether to enable IP conflict detection. use_dhcp_domain : bool Whether to use DHCP domain. - + Returns ------- dict Result of setting general network settings. - - Example return - ---------- + + Examples + -------- ```json { "data": { @@ -130,7 +137,7 @@ def set_general_settings( } ``` """ - + api_name = 'SYNO.Core.Network' info = self.gen_list[api_name] compound = [ @@ -150,34 +157,35 @@ def set_general_settings( } ] return self.batch_request(compound=compound) - + def get_proxy_settings(self) -> dict: - """Get proxy settings. - - Returns - ------- - dict - Proxy settings. - - Example return - ---------- - ```json - { - "data": { - "enable": false, - "enable_auth": false, - "enable_bypass": true, - "enable_different_host": false, - "http_host": "", - "http_port": "80", - "https_host": "", - "https_port": "80", - "password": "\t\t\t\t\t\t\t\t", - "username": "" - }, - "success": true - } - ``` + """ + Get proxy settings. + + Returns + ------- + dict + Proxy settings. + + Examples + -------- + ```json + { + "data": { + "enable": false, + "enable_auth": false, + "enable_bypass": true, + "enable_different_host": false, + "http_host": "", + "http_port": "80", + "https_host": "", + "https_port": "80", + "password": "\t\t\t\t\t\t\t\t", + "username": "" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.Proxy' info = self.gen_list[api_name] @@ -187,14 +195,15 @@ def get_proxy_settings(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def set_proxy_settings( self, enable: bool, enable_auth: bool, enable_bypass: bool, enable_different_host: bool, http_host: str, http_port: str, https_host: str, https_port: str, username: str = None, password: str = None - ) -> dict: - """Set proxy settings. - + ) -> dict: + """ + Set proxy settings. + Parameters ---------- enable : bool @@ -217,14 +226,14 @@ def set_proxy_settings( Username for authentication. Default is None. password : str, optional Password for authentication. Default is None. - + Returns ------- dict Result of setting proxy settings. - - Example return - ---------- + + Examples + -------- ```json { "data": { @@ -242,7 +251,7 @@ def set_proxy_settings( } ``` """ - + api_name = 'SYNO.Core.Network.Proxy' info = self.gen_list[api_name] compound = [ @@ -260,7 +269,7 @@ def set_proxy_settings( 'https_port': https_port } ] - + if username and password: if self.session._secure: compound[0]['username'] = username @@ -271,37 +280,37 @@ def set_proxy_settings( 'password': password } compound[0].update(self.session.encrypt_params(params_enc)) - - + return self.batch_request(compound=compound) - + def get_gateway_list(self) -> dict: - """Get list of gateways. - - Returns - ------- - dict - List of gateways. - - Example return - ---------- - ```json - { - "data": { - "configs": [ - { - "class": "ethernet", - "dns": "192.168.1.1", - "gateway": "192.168.1.1", - "ifname": "ovs_eth0", - "priority": 0, - "slave": false - } - ] - }, - "success": true - } - ``` + """ + Get list of gateways. + + Returns + ------- + dict + List of gateways. + + Examples + -------- + ```json + { + "data": { + "configs": [ + { + "class": "ethernet", + "dns": "192.168.1.1", + "gateway": "192.168.1.1", + "ifname": "ovs_eth0", + "priority": 0, + "slave": false + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.Gateway.List' info = self.gen_list[api_name] @@ -311,51 +320,52 @@ def get_gateway_list(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_interfaces_list(self) -> dict: - """Get list of network interfaces. - - Returns - ------- - dict - List of network interfaces. - - Example return - ---------- - ```json - { - "data": [ - { - "ifname": "ovs_eth0", - "ip": "192.168.1.14", - "mask": "255.255.255.0", - "speed": 1000, - "status": "connected", - "type": "ovseth", - "use_dhcp": true - }, - { - "ifname": "ovs_eth1", - "ip": "169.254.183.6", - "mask": "255.255.0.0", - "speed": -1, - "status": "disconnected", - "type": "ovseth", - "use_dhcp": true - }, - { - "ifname": "pppoe", - "ip": "", - "mask": "", - "speed": 0, - "status": "disconnected", - "type": "pppoe", - "use_dhcp": true - } - ], - "success": true - } - ``` + """ + Get list of network interfaces. + + Returns + ------- + dict + List of network interfaces. + + Examples + -------- + ```json + { + "data": [ + { + "ifname": "ovs_eth0", + "ip": "192.168.1.14", + "mask": "255.255.255.0", + "speed": 1000, + "status": "connected", + "type": "ovseth", + "use_dhcp": true + }, + { + "ifname": "ovs_eth1", + "ip": "169.254.183.6", + "mask": "255.255.0.0", + "speed": -1, + "status": "disconnected", + "type": "ovseth", + "use_dhcp": true + }, + { + "ifname": "pppoe", + "ip": "", + "mask": "", + "speed": 0, + "status": "disconnected", + "type": "pppoe", + "use_dhcp": true + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.Interface' info = self.gen_list[api_name] @@ -365,25 +375,26 @@ def get_interfaces_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_ovs_status(self) -> dict: - """Get infos if ovs is enabled or not. - - Returns - ------- - dict - Infos about ovs status. - - Example return - ---------- - ```json - { - "data": { - "enable_ovs": true - }, - "success": true - } - ``` + """ + Get infos if ovs is enabled or not. + + Returns + ------- + dict + Infos about ovs status. + + Examples + -------- + ```json + { + "data": { + "enable_ovs": true + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.OVS' info = self.gen_list[api_name] @@ -393,107 +404,108 @@ def get_ovs_status(self) -> dict: 'method': 'get' } return self.request_data(api_name, api_path, req_param) - + def get_bond_list(self) -> dict: - """Get list of bond interfaces. - - Returns - ------- - dict - List of bond interfaces. - - Example return - ---------- - ```json - { - "data": [ - { - "block": 0, - "dns": "192.168.1.1", - "duplex": true, - "enable_ha_ip": false, - "enable_vlan": false, - "enabled": true, - "error": false, - "gateway": "192.168.1.1", - "ha_local_ip": "", - "ha_local_mask": "", - "ifname": "ovs_bond0", - "ip": "192.168.1.14", - "ipv6": [ - "2a01:cb05:814e:7d00:9209:d0ff:fe25:7371/64", - "fe80::9209:d0ff:fe25:7371/64" - ], - "is_default_gateway": false, - "is_main_ha_ip": false, - "mask": "255.255.255.0", - "max_supported_speed": -1, - "mode": "balance-slb", - "mtu": 1500, - "mtu_config": 1500, - "nat": false, - "slaves": [ - { - "block": 0, - "dns": "", - "duplex": true, - "enable_ha_ip": false, - "enable_vlan": false, - "gateway": "", - "ha_local_ip": "", - "ha_local_mask": "", - "ifname": "eth0", - "ip": "", - "ipv6": [], - "is_default_gateway": false, - "is_main_ha_ip": false, - "mask": "", - "max_supported_speed": 1000, - "mtu": 1500, - "mtu_config": 1500, - "nat": false, - "speed": 1000, - "status": "connected", - "type": "lan", - "use_dhcp": true, - "vlan_id": 0 - }, - { - "block": 0, - "dns": "", - "duplex": true, - "enable_ha_ip": false, - "enable_vlan": false, - "gateway": "", - "ha_local_ip": "", - "ha_local_mask": "", - "ifname": "eth1", - "ip": "", - "ipv6": [], - "is_default_gateway": false, - "is_main_ha_ip": false, - "mask": "", - "max_supported_speed": 1000, - "mtu": 1500, - "mtu_config": 1500, - "nat": false, - "speed": -1, - "status": "disconnected", - "type": "lan", - "use_dhcp": true, - "vlan_id": 0 - } - ], - "speed": 1000, - "status": "connected", - "type": "ovsbond", - "use_dhcp": true, - "vlan_id": 0 - } - ], - "success": true - } - ``` + """ + Get list of bond interfaces. + + Returns + ------- + dict + List of bond interfaces. + + Examples + -------- + ```json + { + "data": [ + { + "block": 0, + "dns": "192.168.1.1", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "enabled": true, + "error": false, + "gateway": "192.168.1.1", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "ovs_bond0", + "ip": "192.168.1.14", + "ipv6": [ + "2a01:cb05:814e:7d00:9209:d0ff:fe25:7371/64", + "fe80::9209:d0ff:fe25:7371/64" + ], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "255.255.255.0", + "max_supported_speed": -1, + "mode": "balance-slb", + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "slaves": [ + { + "block": 0, + "dns": "", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "eth0", + "ip": "", + "ipv6": [], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": 1000, + "status": "connected", + "type": "lan", + "use_dhcp": true, + "vlan_id": 0 + }, + { + "block": 0, + "dns": "", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "eth1", + "ip": "", + "ipv6": [], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": -1, + "status": "disconnected", + "type": "lan", + "use_dhcp": true, + "vlan_id": 0 + } + ], + "speed": 1000, + "status": "connected", + "type": "ovsbond", + "use_dhcp": true, + "vlan_id": 0 + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.Bond' info = self.gen_list[api_name] @@ -503,77 +515,78 @@ def get_bond_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_ethernet_interface_list(self) -> dict: - """Get list of ethernet interfaces. - - Returns - ------- - dict - List of ethernet interfaces. - - Example return - ---------- - ```json - { - "data": [ - { - "block": 0, - "dns": "192.168.1.1", - "duplex": true, - "enable_ha_ip": false, - "enable_vlan": false, - "gateway": "192.168.1.1", - "ha_local_ip": "", - "ha_local_mask": "", - "ifname": "ovs_eth0", - "ip": "192.168.1.14", - "ipv6": [ - "2a01:cb05:814e:7d00:9209:d0ff:fe25:7371/64", - "fe80::9209:d0ff:fe25:7371/64" - ], - "is_default_gateway": false, - "is_main_ha_ip": false, - "mask": "255.255.255.0", - "max_supported_speed": 1000, - "mtu": 1500, - "mtu_config": 1500, - "nat": false, - "speed": 1000, - "status": "connected", - "type": "ovseth", - "use_dhcp": true, - "vlan_id": 0 - }, - { - "block": 0, - "dns": "", - "duplex": true, - "enable_ha_ip": false, - "enable_vlan": false, - "gateway": "", - "ha_local_ip": "", - "ha_local_mask": "", - "ifname": "ovs_eth1", - "ip": "169.254.183.6", - "ipv6": [], - "is_default_gateway": false, - "is_main_ha_ip": false, - "mask": "255.255.0.0", - "max_supported_speed": 1000, - "mtu": 1500, - "mtu_config": 1500, - "nat": false, - "speed": -1, - "status": "disconnected", - "type": "ovseth", - "use_dhcp": true, - "vlan_id": 0 - } - ], - "success": true - } - ``` + """ + Get list of ethernet interfaces. + + Returns + ------- + dict + List of ethernet interfaces. + + Examples + -------- + ```json + { + "data": [ + { + "block": 0, + "dns": "192.168.1.1", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "192.168.1.1", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "ovs_eth0", + "ip": "192.168.1.14", + "ipv6": [ + "2a01:cb05:814e:7d00:9209:d0ff:fe25:7371/64", + "fe80::9209:d0ff:fe25:7371/64" + ], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "255.255.255.0", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": 1000, + "status": "connected", + "type": "ovseth", + "use_dhcp": true, + "vlan_id": 0 + }, + { + "block": 0, + "dns": "", + "duplex": true, + "enable_ha_ip": false, + "enable_vlan": false, + "gateway": "", + "ha_local_ip": "", + "ha_local_mask": "", + "ifname": "ovs_eth1", + "ip": "169.254.183.6", + "ipv6": [], + "is_default_gateway": false, + "is_main_ha_ip": false, + "mask": "255.255.0.0", + "max_supported_speed": 1000, + "mtu": 1500, + "mtu_config": 1500, + "nat": false, + "speed": -1, + "status": "disconnected", + "type": "ovseth", + "use_dhcp": true, + "vlan_id": 0 + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.Ethernet' info = self.gen_list[api_name] @@ -583,58 +596,59 @@ def get_ethernet_interface_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def set_ethernet_interfaces(self, configs: list) -> dict: - """Set ethernet interfaces. - - Parameters - ---------- - configs : list - List of configurations for ethernet interfaces. Each configuration is a dictionary with the following keys: - - ifname : str - Interface name. - - use_dhcp : bool - Whether to use DHCP. - - enable_ha_ip : bool, optional - Whether to enable HA IP. - - is_default_gateway : bool, optional - Whether this interface is the default gateway. - - mtu : int, optional - MTU size. - - enable_vlan : bool, optional - Whether to enable VLAN. - - ip : str, optional - IP address. - - mask : str, optional - Subnet mask. - - gateway : str, optional - Gateway address. - - dns : str, optional - DNS server address. - - Returns - ------- - dict - Result of setting ethernet interfaces. - - Example return - ---------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.Core.Network.Ethernet", - "method": "set", - "success": true, - "version": 2 - } - ] - }, - "success": true - } - ``` + """ + Set ethernet interfaces. + + Parameters + ---------- + configs : list + List of configurations for ethernet interfaces. Each configuration is a dictionary with the following keys: + - ifname : str + Interface name. + - use_dhcp : bool + Whether to use DHCP. + - enable_ha_ip : bool, optional + Whether to enable HA IP. + - is_default_gateway : bool, optional + Whether this interface is the default gateway. + - mtu : int, optional + MTU size. + - enable_vlan : bool, optional + Whether to enable VLAN. + - ip : str, optional + IP address. + - mask : str, optional + Subnet mask. + - gateway : str, optional + Gateway address. + - dns : str, optional + DNS server address. + + Returns + ------- + dict + Result of setting ethernet interfaces. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Network.Ethernet", + "method": "set", + "success": true, + "version": 2 + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.Ethernet' info = self.gen_list[api_name] @@ -647,42 +661,43 @@ def set_ethernet_interfaces(self, configs: list) -> dict: } ] return self.batch_request(compound=compound) - + def get_pppoe_interface_list(self) -> dict: - """Get list of pppoe interfaces. - - Returns - ------- - dict - List of pppoe interfaces. - - Example return - ---------- - ```json - { - "data": [ - { - "devs": [ - "ovs_eth0", - "ovs_eth1" - ], - "guest_enabled": false, - "ifname": "pppoe", - "ip": "", - "is_default_gateway": 1, - "mask": "", - "mtu_config": "1492", - "password": "", - "real_ifname": "ovs_eth0", - "status": "disconnected", - "type": "pppoe", - "use_dhcp": true, - "username": "" - } - ], - "success": true - } - ``` + """ + Get list of pppoe interfaces. + + Returns + ------- + dict + List of pppoe interfaces. + + Examples + -------- + ```json + { + "data": [ + { + "devs": [ + "ovs_eth0", + "ovs_eth1" + ], + "guest_enabled": false, + "ifname": "pppoe", + "ip": "", + "is_default_gateway": 1, + "mask": "", + "mtu_config": "1492", + "password": "", + "real_ifname": "ovs_eth0", + "status": "disconnected", + "type": "pppoe", + "use_dhcp": true, + "username": "" + } + ], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.PPPoE' info = self.gen_list[api_name] @@ -692,23 +707,24 @@ def get_pppoe_interface_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_vpn_pptp_list(self) -> dict: - """Get list of pptp vpn interfaces. - - Returns - ------- - dict - List of pptp vpn interfaces. - - Example return - ---------- - ```json - { - "data": [], - "success": true - } - ``` + """ + Get list of pptp vpn interfaces. + + Returns + ------- + dict + List of pptp vpn interfaces. + + Examples + -------- + ```json + { + "data": [], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.VPN.PPTP' info = self.gen_list[api_name] @@ -718,23 +734,24 @@ def get_vpn_pptp_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_vpn_openvpn_with_conf_list(self) -> dict: - """Get list of openvpn with conf file vpn interfaces. - - Returns - ------- - dict - List of openvpn with conf file vpn interfaces. - - Example return - ---------- - ```json - { - "data": [], - "success": true - } - ``` + """ + Get list of openvpn with conf file vpn interfaces. + + Returns + ------- + dict + List of openvpn with conf file vpn interfaces. + + Examples + -------- + ```json + { + "data": [], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.VPN.OpenVPNWithConf' info = self.gen_list[api_name] @@ -744,23 +761,24 @@ def get_vpn_openvpn_with_conf_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_vpn_openvpn_list(self) -> dict: - """Get list of openvpn vpn interfaces. - - Returns - ------- - dict - List of openvpn vpn interfaces. - - Example return - ---------- - ```json - { - "data": [], - "success": true - } - ``` + """ + Get list of openvpn vpn interfaces. + + Returns + ------- + dict + List of openvpn vpn interfaces. + + Examples + -------- + ```json + { + "data": [], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.VPN.OpenVPN' info = self.gen_list[api_name] @@ -770,23 +788,24 @@ def get_vpn_openvpn_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_vpn_l2tp_list(self) -> dict: - """Get list of l2tp vpn interfaces. - - Returns - ------- - dict - List of l2tp vpn interfaces. - - Example return - ---------- - ```json - { - "data": [], - "success": true - } - ``` + """ + Get list of l2tp vpn interfaces. + + Returns + ------- + dict + List of l2tp vpn interfaces. + + Examples + -------- + ```json + { + "data": [], + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.VPN.L2TP' info = self.gen_list[api_name] @@ -796,31 +815,32 @@ def get_vpn_l2tp_list(self) -> dict: 'method': 'list' } return self.request_data(api_name, api_path, req_param) - + def get_traffic_control_rules(self, adapter: str) -> dict: - """Get traffic control rules. - - Parameters - ---------- - adapter : str - Adapter name, e.g. 'ovs_eth0'. - - Returns - ------- - dict - _description_ - - Example return - ---------- - ```json - { - "data": { - "rules": [], - "total": 0 - }, - "success": true - } - ``` + """ + Get traffic control rules. + + Parameters + ---------- + adapter : str + Adapter name, e.g. 'ovs_eth0'. + + Returns + ------- + dict + A dictionary containing the traffic control rules for the specified adapter. + + Examples + -------- + ```json + { + "data": { + "rules": [], + "total": 0 + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Network.TrafficControl.Rules' info = self.gen_list[api_name] @@ -833,44 +853,45 @@ def get_traffic_control_rules(self, adapter: str) -> dict: return self.request_data(api_name, api_path, req_param) def get_port_list_per_service(self) -> dict: - """Get port list per service. - - Returns - ------- - dict - Port list per service. - - Example return - ---------- - ```json - { - "data": { - "port_info": [ - { - "desc": "rsync", - "dst_port": [ - "873" - ], - "name": "rsync", - "port_id": "netbkp", - "protocol": "tcp", - "src_port": null - }, - { - "desc": "Network MFP", - "dst_port": [ - "3240-3259" - ], - "name": "Network MFP", - "port_id": "mfp", - "protocol": "tcp", - "src_port": null - } - ] - }, - "success": true - } - ``` + """ + Get port list per service. + + Returns + ------- + dict + Port list per service. + + Examples + -------- + ```json + { + "data": { + "port_info": [ + { + "desc": "rsync", + "dst_port": [ + "873" + ], + "name": "rsync", + "port_id": "netbkp", + "protocol": "tcp", + "src_port": null + }, + { + "desc": "Network MFP", + "dst_port": [ + "3240-3259" + ], + "name": "Network MFP", + "port_id": "mfp", + "protocol": "tcp", + "src_port": null + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Service.PortInfo' info = self.gen_list[api_name] @@ -882,5 +903,4 @@ def get_port_list_per_service(self) -> dict: } return self.request_data(api_name, api_path, req_param) - - pass \ No newline at end of file + pass diff --git a/synology_api/DSM/ControlPanel/Notifications.py b/synology_api/DSM/ControlPanel/Notifications.py index 66074329..f3eaf040 100644 --- a/synology_api/DSM/ControlPanel/Notifications.py +++ b/synology_api/DSM/ControlPanel/Notifications.py @@ -1,4 +1,11 @@ +""" +Notifications API endpoint. +""" from synology_api import base_api + class Notifications(base_api.BaseApi): - pass \ No newline at end of file + """ + Notifications API endpoint. + """ + pass diff --git a/synology_api/DSM/ControlPanel/RegionalOptions.py b/synology_api/DSM/ControlPanel/RegionalOptions.py index d6202b2b..9f5e24b4 100644 --- a/synology_api/DSM/ControlPanel/RegionalOptions.py +++ b/synology_api/DSM/ControlPanel/RegionalOptions.py @@ -1,4 +1,11 @@ +""" +Regional options class for Synology DSM. +""" from synology_api import base_api + class RegionalOptions(base_api.BaseApi): - pass \ No newline at end of file + """ + Regional options class for Synology DSM. + """ + pass diff --git a/synology_api/DSM/ControlPanel/Security.py b/synology_api/DSM/ControlPanel/Security.py index ec0aa035..23c38dbd 100644 --- a/synology_api/DSM/ControlPanel/Security.py +++ b/synology_api/DSM/ControlPanel/Security.py @@ -1,4 +1,11 @@ +""" +Security class for Synology DSM. +""" from synology_api import base_api + class Security(base_api.BaseApi): - pass \ No newline at end of file + """ + Security class for Synology DSM. + """ + pass diff --git a/synology_api/DSM/ControlPanel/SharedFolder.py b/synology_api/DSM/ControlPanel/SharedFolder.py index 7bda91c3..74b6b195 100644 --- a/synology_api/DSM/ControlPanel/SharedFolder.py +++ b/synology_api/DSM/ControlPanel/SharedFolder.py @@ -1,66 +1,68 @@ +""" +Core Share API implementation. +""" + from synology_api import base_api import json from typing import List, Any + class SharedFolder(base_api.BaseApi): - """Core Share API implementation. - - Supported methods: - - Getters: - - Validate set of parameters for a new/modified shared folder - - List all folders information - - Get a folder by name - - Retrieve share permissions for a given folder filtered by permission name (sub string) - - Retrieve share permissions for a given folder - - Retrieve share permissions for a given group - - - Setters: - - Create a new shared folder - - Set folder permissions for a given folder - - Set group permissions for a given share - - - Actions: - - Delete folder(s) by name(s) - - Clone existing shared folder """ - + Core Share API implementation. + + Supported methods: + - Getters: + - Validate set of parameters for a new/modified shared folder + - List all folders information + - Get a folder by name + - Retrieve share permissions for a given folder filtered by permission name (sub string) + - Retrieve share permissions for a given folder + - Retrieve share permissions for a given group + + - Setters: + - Create a new shared folder + - Set folder permissions for a given folder + - Set group permissions for a given share + + - Actions: + - Delete folder(s) by name(s) + - Clone existing shared folder + """ + def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_compress: bool = False, enable_share_cow: bool = False, enc_passwd: str = "", encryption: bool = False) -> dict: - """Validate set of parameter for a new / modified shared folder - Parameters - ---------- - name : str - Share name. - - vol_path : str - Volume path. - - desc : str, optional - Share description. Defaults to `""`. - - enable_share_compress : bool, optional - Enable share compress. Defaults to `False`. - - enable_share_cow : bool, optional - Enable share cow. Defaults to `False`. - - enc_passwd : str, optional - Encrypted password. Defaults to `""`. - - encryption : bool, optional - Enable encryption. Defaults to `False`. - - Returns - ------- - dict - Success. - - Example return - -------------- - ```json - { - "success": true, - } - ``` + """ + Validate set of parameter for a new / modified shared folder. + + Parameters + ---------- + name : str + Share name. + vol_path : str + Volume path. + desc : str, optional + Share description. Defaults to `""`. + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + enc_passwd : str, optional + Encrypted password. Defaults to `""`. + encryption : bool, optional + Enable encryption. Defaults to `False`. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true, + } + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -70,7 +72,7 @@ def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_co "version": info['maxVersion'], "name": name, } - + req_param_encrypted = { "shareinfo": json.dumps({ "name": name, @@ -82,58 +84,58 @@ def validate_set(self, name: str, vol_path: str, desc: str = "", enable_share_co "encryption": encryption, }) } - + # If using https don't use encryption if self.session._secure: req_param.update(req_param_encrypted) else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - - + return self.request_data(api_name, api_path, req_param, method="post") - + def list_folders(self, share_type: str = "all", additional: list = []) -> dict: - """List all folders informations - Parameters - ---------- - share_type : str, optional - Share type. Defaults to `all`. - - additional : list[str], optional - Additional fields to retrieve. Defaults to `[]`. - All fields known are: `[ - "hidden","encryption","is_aclmode","unite_permission","is_support_acl","is_sync_share","is_force_readonly","force_readonly_reason", - "recyclebin","is_share_moving","is_cluster_share","is_exfat_share","is_c2_share","is_cold_storage_share","is_missing_share", - "is_offline_share","support_snapshot","share_quota","enable_share_compress","enable_share_cow","enable_share_tiering", - "load_worm_attr","include_cold_storage_share","is_cold_storage_share","include_missing_share","is_missing_share", - "include_offline_share","is_offline_share","include_worm_share" - ]`. - - Returns - ------- - dict - A dictionary containing the shared folders information. - - Example return - -------------- - ```json - { - "data": { - "shares": [ - { - "desc": "", - "is_usb_share": false, - "name": "test_shared_folder", - "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", - "vol_path": "/volume1" - } - ], - "total": 1 - }, - "success": true - } - ``` + """ + List all folders informations. + + Parameters + ---------- + share_type : str, optional + Share type. Defaults to `all`. + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `[ + "hidden","encryption","is_aclmode","unite_permission","is_support_acl","is_sync_share","is_force_readonly","force_readonly_reason", + "recyclebin","is_share_moving","is_cluster_share","is_exfat_share","is_c2_share","is_cold_storage_share","is_missing_share", + "is_offline_share","support_snapshot","share_quota","enable_share_compress","enable_share_cow","enable_share_tiering", + "load_worm_attr","include_cold_storage_share","is_cold_storage_share","include_missing_share","is_missing_share", + "include_offline_share","is_offline_share","include_worm_share" + ]`. + + Returns + ------- + dict + A dictionary containing the shared folders information. + + Examples + -------- + ```json + { + "data": { + "shares": [ + { + "desc": "", + "is_usb_share": false, + "name": "test_shared_folder", + "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", + "vol_path": "/volume1" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -144,43 +146,44 @@ def list_folders(self, share_type: str = "all", additional: list = []) -> dict: "shareType": share_type, "additional": json.dumps(additional) } - + return self.request_data(api_name, api_path, req_param) - + def get_folder(self, name: str, additional: list = []) -> dict: - """Get a folder by name - Parameters - ---------- - name : str - Share name. - - additional : list, optional - Additional fields to retrieve. Defaults to `[]`. - All fields known are: `["disable_list","disable_modify","disable_download","unite_permission","is_aclmode"]`. - - Returns - ------- - dict - A dictionary containing the shared folder information. - - Example return - -------------- - ```json - { - "data": { - "desc": "", - "disable_download": false, - "disable_list": false, - "disable_modify": false, - "is_aclmode": true, - "is_usb_share": false, - "name": "test_shared_folder", - "unite_permission": false, - "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", - "vol_path": "/volume1" - }, - "success": true, - ``` + """ + Get a folder by name. + + Parameters + ---------- + name : str + Share name. + additional : list, optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: `["disable_list","disable_modify","disable_download","unite_permission","is_aclmode"]`. + + Returns + ------- + dict + A dictionary containing the shared folder information. + + Examples + -------- + ```json + { + "data": { + "desc": "", + "disable_download": false, + "disable_list": false, + "disable_modify": false, + "is_aclmode": true, + "is_usb_share": false, + "name": "test_shared_folder", + "unite_permission": false, + "uuid": "18585c8d-4d74-41a1-b561-21906a7f6f14", + "vol_path": "/volume1" + }, + "success": true, + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -191,74 +194,64 @@ def get_folder(self, name: str, additional: list = []) -> dict: "name": name, "additional": json.dumps(additional) } - + return self.request_data(api_name, api_path, req_param) - + def create_folder(self, - name: str, vol_path: str, desc: str = "", hidden: bool = False, - enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, - hide_unreadable: bool = False, enable_share_cow: bool = False, - enable_share_compress: bool = False, share_quota: int = 0, name_org: str = "", - encryption: bool = False, enc_passwd: str = "" - ) -> dict: - """Create a new shared folder - Parameters - ---------- - name : str - Share name. - - vol_path : str - Volume path. - - desc : str, optional - Share description. Defaults to `""`. - - hidden : bool, optional - Hide share. Defaults to `False`. - - enable_recycle_bin : bool, optional - Enable recycle bin. Defaults to `True`. - - recycle_bin_admin_only : bool, optional - Recycle bin admin only. Defaults to `True`. - - hide_unreadable : bool, optional - Hide unreadable. Defaults to `False`. - - enable_share_cow : bool, optional - Enable share cow. Defaults to `False`. - - enable_share_compress : bool, optional - Enable share compress. Defaults to `False`. - - share_quota : int, optional - Share quota. Defaults to `0`. - - name_org : str, optional - Defaults to `""`. - - encryption : bool, optional - Enable encryption. Defaults to `False`. - - enc_passwd : str, optional - Encrypted password. Defaults to `""`. - - Returns - ------- - dict - Name of the created shared folder - - Example return - --------------- - ```json - { - "data": { - "name": "test_shared_folder" - }, - "success": true, - ``` + name: str, vol_path: str, desc: str = "", hidden: bool = False, + enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, + hide_unreadable: bool = False, enable_share_cow: bool = False, + enable_share_compress: bool = False, share_quota: int = 0, name_org: str = "", + encryption: bool = False, enc_passwd: str = "" + ) -> dict: + """ + Create a new shared folder. + + Parameters + ---------- + name : str + Share name. + vol_path : str + Volume path. + desc : str, optional + Share description. Defaults to `""`. + hidden : bool, optional + Hide share. Defaults to `False`. + enable_recycle_bin : bool, optional + Enable recycle bin. Defaults to `True`. + recycle_bin_admin_only : bool, optional + Recycle bin admin only. Defaults to `True`. + hide_unreadable : bool, optional + Hide unreadable. Defaults to `False`. + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + share_quota : int, optional + Share quota. Defaults to `0`. + name_org : str, optional + Defaults to `""`. + encryption : bool, optional + Enable encryption. Defaults to `False`. + enc_passwd : str, optional + Encrypted password. Defaults to `""`. + + Returns + ------- + dict + Name of the created shared folder. + + Examples + -------- + ```json + { + "data": { + "name": "test_shared_folder" + }, + "success": true, + ``` """ - + api_name = "SYNO.Core.Share" info = self.core_list[api_name] api_path = info["path"] @@ -290,28 +283,30 @@ def create_folder(self, else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - + return self.request_data(api_name, api_path, req_param, method="post") - + def delete_folders(self, name: List[str]) -> dict: - """Delete folder(s) by name(s) - Parameters - ---------- - name List[str] - Share names. - - Returns - ------- - dict - Success. - - Example return - -------------- - ```json - { - "success": true - } - ``` + """ + Delete folder(s) by name(s). + + Parameters + ---------- + name : List[str] + Share names. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -321,65 +316,57 @@ def delete_folders(self, name: List[str]) -> dict: "version": info['minVersion'], "name": name } - + return self.request_data(api_name, api_path, req_param) - + def clone(self, - name: str, name_org: str, vol_path: str, desc: str = "", hidden: bool = False, - enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, - hide_unreadable: bool = False, enable_share_cow: bool = False, - enable_share_compress: bool = False, share_quota: int = 0 - ) -> dict: - """Clone existing shared folder. - Parameters - ---------- - name : str - New shared folder name. - - name_org : str - Original shared folder name. - - vol_path : str - Volume path. - - desc : str, optional - Shared folder description. Defaults to `""`. - - hidden : bool, optional - Hide shared folder. Defaults to `False`. - - enable_recycle_bin : bool, optional - Enable recycle bin. Defaults to `True`. - - recycle_bin_admin_only : bool, optional - Recycle bin admin only. Defaults to `True`. - - hide_unreadable : bool, optional - Hide unreadable. Defaults to `False`. - - enable_share_cow : bool, optional - Enable share cow. Defaults to `False`. - - enable_share_compress : bool, optional - Enable share compress. Defaults to `False`. - - share_quota : int, optional - Share quota. Defaults to `0`. - - Returns - ------- - dict - Name of the created shared folder - - Example return - -------------- - ```json - { - "data": { - "name": "test_shared_folder" - }, - "success": true, - ``` + name: str, name_org: str, vol_path: str, desc: str = "", hidden: bool = False, + enable_recycle_bin: bool = True, recycle_bin_admin_only: bool = True, + hide_unreadable: bool = False, enable_share_cow: bool = False, + enable_share_compress: bool = False, share_quota: int = 0 + ) -> dict: + """ + Clone existing shared folder. + + Parameters + ---------- + name : str + New shared folder name. + name_org : str + Original shared folder name. + vol_path : str + Volume path. + desc : str, optional + Shared folder description. Defaults to `""`. + hidden : bool, optional + Hide shared folder. Defaults to `False`. + enable_recycle_bin : bool, optional + Enable recycle bin. Defaults to `True`. + recycle_bin_admin_only : bool, optional + Recycle bin admin only. Defaults to `True`. + hide_unreadable : bool, optional + Hide unreadable. Defaults to `False`. + enable_share_cow : bool, optional + Enable share cow. Defaults to `False`. + enable_share_compress : bool, optional + Enable share compress. Defaults to `False`. + share_quota : int, optional + Share quota. Defaults to `0`. + + Returns + ------- + dict + Name of the created shared folder. + + Examples + -------- + ```json + { + "data": { + "name": "test_shared_folder" + }, + "success": true, + ``` """ api_name = "SYNO.Core.Share" info = self.core_list[api_name] @@ -389,7 +376,7 @@ def clone(self, "version": info['maxVersion'], "name": name, } - + req_param_encrypted = { "shareinfo": json.dumps({ "desc": desc, @@ -405,73 +392,69 @@ def clone(self, "share_quota": share_quota, }) } - + # If using https don't use encryption if self.session._secure: req_param.update(req_param_encrypted) else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - + return self.request_data(api_name, api_path, req_param, method="post") - - def get_folder_permission_by_name(self, - name: str, permission_substr: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, - user_group_type: str = "local_user" - ) -> dict: - """Retrieve share permissions for a given folder filtered by permission name (sub string) - Parameters - ---------- - name : str - The folder name to list permissions for. - - permission_substr : str - The substring to search for in the permissions. - - offset : int, optional - The offset to start at. Defaults to `0`. - - limit : int, optional - The maximum number of results to return. Defaults to `50`. - - is_unite_permission : bool, optional - Whether to return unified permissions. Defaults to `False`. - - with_inherit : bool, optional - Whether to include inherited permissions. Defaults to `False`. - - user_group_type : str, optional - The type of user group to list permissions for. Defaults to `"local_user"`. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - Returns - ------- - dict - List of permission(s) on the folder - - Example return - -------------- - ```json - { - "data": { - "items": [ - { - "inherit": "-", - "is_admin": false, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "guest" - } - ], - "total": 1 - }, - "success": true - } - ``` + + def get_folder_permission_by_name(self, + name: str, permission_substr: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, + user_group_type: str = "local_user" + ) -> dict: + """ + Retrieve share permissions for a given folder filtered by permission name (sub string). + + Parameters + ---------- + name : str + The folder name to list permissions for. + permission_substr : str + The substring to search for in the permissions. + offset : int, optional + The offset to start at. Defaults to `0`. + limit : int, optional + The maximum number of results to return. Defaults to `50`. + is_unite_permission : bool, optional + Whether to return unified permissions. Defaults to `False`. + with_inherit : bool, optional + Whether to include inherited permissions. Defaults to `False`. + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + List of permission(s) on the folder. + + Examples + -------- + ```json + { + "data": { + "items": [ + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + } + ], + "total": 1 + }, + "success": true + } + ``` """ - + api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] api_path = info["path"] @@ -488,86 +471,83 @@ def get_folder_permission_by_name(self, "user_group_type": user_group_type, } return self.request_data(api_name, api_path, req_param, method="get") - - def get_folder_permissions(self, - name: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, - user_group_type: str = "local_user" - ) -> dict: - """Retrieve share permissions for a given folder. - Parameters - ---------- - name : str - The folder name to list permissions for. - - offset : int, optional - The offset to start at. Defaults to `0`. - - limit : int, optional - The maximum number of results to return. Defaults to `50`. - - is_unite_permission : bool, optional - Whether to return unified permissions. Defaults to `False`. - - with_inherit : bool, optional - Whether to include inherited permissions. Defaults to `False`. - - user_group_type : str, optional - The type of user group to list permissions for. Defaults to `"local_user"`. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - Returns - ------- - dict - All permissions on the folder - - Example return - ---------- - ```json - { - "data": { - "items": [ - { - "inherit": "rw", - "is_admin": true, - "is_custom": false, - "is_deny": true, - "is_readonly": false, - "is_writable": false, - "name": "admin" - }, - { - "inherit": "-", - "is_admin": false, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "guest" - }, - { - "inherit": "rw", - "is_admin": true, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": true, - "name": "test_api" - }, - { - "inherit": "-", - "is_admin": false, - "is_custom": false, - "is_deny": false, - "is_readonly": false, - "is_writable": false, - "name": "test_test" - } - ], - "total": 5 - }, - "success": true - } - ``` + + def get_folder_permissions(self, + name: str, offset: int = 0, limit: int = 50, is_unite_permission: bool = False, with_inherit: bool = False, + user_group_type: str = "local_user" + ) -> dict: + """ + Retrieve share permissions for a given folder. + + Parameters + ---------- + name : str + The folder name to list permissions for. + offset : int, optional + The offset to start at. Defaults to `0`. + limit : int, optional + The maximum number of results to return. Defaults to `50`. + is_unite_permission : bool, optional + Whether to return unified permissions. Defaults to `False`. + with_inherit : bool, optional + Whether to include inherited permissions. Defaults to `False`. + user_group_type : str, optional + The type of user group to list permissions for. Defaults to `"local_user"`. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + + Returns + ------- + dict + All permissions on the folder. + + Examples + -------- + ```json + { + "data": { + "items": [ + { + "inherit": "rw", + "is_admin": true, + "is_custom": false, + "is_deny": true, + "is_readonly": false, + "is_writable": false, + "name": "admin" + }, + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "guest" + }, + { + "inherit": "rw", + "is_admin": true, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": true, + "name": "test_api" + }, + { + "inherit": "-", + "is_admin": false, + "is_custom": false, + "is_deny": false, + "is_readonly": false, + "is_writable": false, + "name": "test_test" + } + ], + "total": 5 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -584,45 +564,45 @@ def get_folder_permissions(self, "user_group_type": user_group_type, } return self.request_data(api_name, api_path, req_param, method="get") - + def set_folder_permissions(self, name: str, user_group_type: str, permissions: List[dict[str, object]]) -> dict: - """Set folder permissions for a given folder. - Parameters - ---------- - name : str - The folder name to set permissions for. - - user_group_type : str - The type of user group to set permissions for. - All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. - - permissions : dict - The permissions to set for the folder. - Example: - ```json - [ - { - "name":"guest", - "is_readonly":false, - "is_writable":true, - "is_deny":false, - "is_custom":false - } - ] - ``` - - Returns - ------- - dict - Success - - Example return - -------------- + """ + Set folder permissions for a given folder. + + Parameters + ---------- + name : str + The folder name to set permissions for. + user_group_type : str + The type of user group to set permissions for. + All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. + permissions : dict + The permissions to set for the folder. + Example: ```json - { - "success": true - } + [ + { + "name":"guest", + "is_readonly":false, + "is_writable":true, + "is_deny":false, + "is_custom":false + } + ] ``` + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -635,43 +615,45 @@ def set_folder_permissions(self, name: str, user_group_type: str, permissions: L "permissions": json.dumps(permissions), } return self.request_data(api_name, api_path, req_param, method="get") - + def get_local_group_permissions(self, group: str) -> dict: - """Retrieve share permissions for a given group. - Parameters - ---------- - group : str - The group to list permissions for. - - Returns - ------- - dict - Permissions of a group on Shared folders - - Example return - -------------- - ```json - { - "data": { - "shares": [ - { - "is_aclmode": true, - "is_custom": false, - "is_deny": true, - "is_mask": false, - "is_readonly": false, - "is_sync_share": false, - "is_unite_permission": false, - "is_writable": false, - "name": "ActiveBackupforBusiness", - "share_path": "/volume3/ActiveBackupforBusiness" - } - ], - "total": 1 - }, - "success": true - } - ``` + """ + Retrieve share permissions for a given group. + + Parameters + ---------- + group : str + The group to list permissions for. + + Returns + ------- + dict + Permissions of a group on Shared folders. + + Examples + -------- + ```json + { + "data": { + "shares": [ + { + "is_aclmode": true, + "is_custom": false, + "is_deny": true, + "is_mask": false, + "is_readonly": false, + "is_sync_share": false, + "is_unite_permission": false, + "is_writable": false, + "name": "ActiveBackupforBusiness", + "share_path": "/volume3/ActiveBackupforBusiness" + } + ], + "total": 1 + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -682,53 +664,56 @@ def get_local_group_permissions(self, group: str) -> dict: "name": group, "user_group_type": "local_group", "share_type": json.dumps( - ["dec", "local", "usb", "sata", "cluster", "c2", "cold_storage", "worm"] + ["dec", "local", "usb", "sata", "cluster", + "c2", "cold_storage", "worm"] ), "additional": json.dumps(["hidden", "encryption", "is_aclmode"]), } return self.request_data(api_name, api_path, req_param) - + def set_local_group_permissions( self, group: str, permissions: list[dict[str, Any]] ) -> dict: - """Set group permissions for a given share. - Parameters - ---------- - group : str - The group to set the permissions for. - - permissions : list[dict[str, Any]] - The permissions to set for the group. - Example: - ``` - [ - { - "name": "web", - "is_readonly": False, - "is_writable": False, - "is_deny": True - }, - { - "name": "ActiveBackupforBusiness", - "is_readonly": False, - "is_writable": True, - "is_deny": False - } - ] - ``` + """ + Set group permissions for a given share. - Returns - ------- - dict - Success + Parameters + ---------- + group : str + The group to set the permissions for. - Example return - -------------- - ```json - { - "success": true - } + permissions : list[dict[str, Any]] + The permissions to set for the group. + Example: + ``` + [ + { + "name": "web", + "is_readonly": False, + "is_writable": False, + "is_deny": True + }, + { + "name": "ActiveBackupforBusiness", + "is_readonly": False, + "is_writable": True, + "is_deny": False + } + ] ``` + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Permission" info = self.core_list[api_name] @@ -742,30 +727,30 @@ def set_local_group_permissions( } return self.request_data(api_name, api_path, req_param) - - + def export_encryption_key(self, name: str, password: str) -> dict: - """Export encryption key for a given share. - Parameters - ---------- - name : str - The share name to export the encryption key for. - - password : str - The password to use for exporting the encryption key. - - Returns - ------- - dict - Success - - Example return - -------------- - ```json - { - "success": true - } - ``` + """ + Export encryption key for a given share. + + Parameters + ---------- + name : str + The share name to export the encryption key for. + password : str + The password to use for exporting the encryption key. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Crypto.Key" info = self.core_list[api_name] @@ -775,7 +760,7 @@ def export_encryption_key(self, name: str, password: str) -> dict: "version": info['maxVersion'], "name": name, } - + enc_req_param = { "password": password, } @@ -785,32 +770,32 @@ def export_encryption_key(self, name: str, password: str) -> dict: else: encrypted_params = self.session.encrypt_params(enc_req_param) req_param.update(encrypted_params) - + return self.request_data(api_name, api_path, req_param, method="post") - - + def decrypt_folder(self, name: str, password: str) -> dict: - """Decrypt a given share. - Parameters - ---------- - name : str - The share name to decrypt. - - password : str - The password to use for decrypting the share. - - Returns - ------- - dict - Success - - Example return - -------------- - ```json - { - "success": true - } - ``` + """ + Decrypt a given share. + + Parameters + ---------- + name : str + The share name to decrypt. + password : str + The password to use for decrypting the share. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Crypto" info = self.core_list[api_name] @@ -820,7 +805,7 @@ def decrypt_folder(self, name: str, password: str) -> dict: "version": info['maxVersion'], "name": name, } - + req_param_encrypted = { "password": password, } @@ -830,28 +815,30 @@ def decrypt_folder(self, name: str, password: str) -> dict: else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - + return self.request_data(api_name, api_path, req_param, method="post") - + def encrypt_folder(self, name: str) -> dict: - """Encrypt a given share. - Parameters - ---------- - name : str - The share name to encrypt. - - Returns - ------- - dict - Success - - Example return - -------------- - ```json - { - "success": true - } - ``` + """ + Encrypt a given share. + + Parameters + ---------- + name : str + The share name to encrypt. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = "SYNO.Core.Share.Crypto" info = self.core_list[api_name] @@ -868,13 +855,20 @@ class KeyManagerStore(base_api.BaseApi): """ Core Share KeyManager Store API implementation. """ - + def init(self) -> dict: - """Initialize KeyManagerStore API. """ - - raise NotImplementedError("This method is not completly implemented yet. API return error 403") - + Initialize KeyManagerStore API. + + Returns + ------- + dict + Not implemented yet. + """ + + raise NotImplementedError( + "This method is not completly implemented yet. API return error 403") + api_name = "SYNO.Core.Share.KeyManager.Store" version = self.core_list[api_name]["maxVersion"] api_path = self.core_list[api_name]["path"] @@ -883,25 +877,31 @@ def init(self) -> dict: "method": "init", "share_path": "/usr/syno/etc/.encrypt" } - + req_param_encrypted = { "passphrase": "", } - + # If using https don't use encryption if self.session._secure: req_param.update(req_param_encrypted) else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - - + return self.request_data(api_name, api_path, req_param, method="post") - + def verify(self) -> dict: - + """ + Verify KeyManagerStore API. + + Returns + ------- + dict + Not implemented yet. + """ raise NotImplementedError("This method is not implemented yet.") - + api_name = "SYNO.Core.Share.KeyManager.Store" version = self.core_list[api_name]["maxVersion"] api_path = self.core_list[api_name]["path"] @@ -909,38 +909,39 @@ def verify(self) -> dict: "version": version, "method": "verify", } - + req_param_encrypted = { "passphrase": "", } - + # If using https don't use encryption if self.session._secure: req_param.update(req_param_encrypted) else: encrypted_params = self.session.encrypt_params(req_param_encrypted) req_param.update(encrypted_params) - - + return self.request_data(api_name, api_path, req_param, method="post") - + def explore(self) -> dict: - """Explore KeyManagerStore API. Get list of existing stores - Returns - ------- - dict - List of stores existing on the NAS - - Example return - -------------- - ```json - { - "data": { - "stores": [] - }, - "success": true - } - ``` + """ + Explore KeyManagerStore API. Get list of existing stores. + + Returns + ------- + dict + List of stores existing on the NAS. + + Examples + -------- + ```json + { + "data": { + "stores": [] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.KeyManager.Store" version = self.core_list[api_name]["minVersion"] @@ -949,13 +950,30 @@ def explore(self) -> dict: "version": version, "method": "explore", } - + return self.request_data(api_name, api_path, req_param) - + def add(self, share_name: str, share_cypher: int, share_password: str) -> dict: - - raise NotImplementedError("This method is not completly implemented yet. API return error 403") - + """ + Add KeyManagerStore API. Add a new store. + + Parameters + ---------- + share_name : str + The share name to add to the store. + share_cypher : int + The share cypher to use. + share_password : str + The share password to use. + + Returns + ------- + dict + Not implemented yet. + """ + raise NotImplementedError( + "This method is not completly implemented yet. API return error 403") + api_name = "SYNO.Core.Share.KeyManager.Key" version = self.core_list[api_name]["maxVersion"] api_path = self.core_list[api_name]["path"] @@ -967,31 +985,34 @@ def add(self, share_name: str, share_cypher: int, share_password: str) -> dict: "share_password": share_password, "passphrase": "2PassValidation", } - + return self.request_data(api_name, api_path, req_param, method="post") - + + class KeyManagerAutoKey(base_api.BaseApi): """ Core Share KeyManager AutoKey API implementation. """ - + def list(self) -> dict: - """List KeyManagerStore API. - Returns - ------- - dict - List of keys in the manager - - Example return - -------------- - ```json - { - "data": { - "keys": [] - }, - "success": true - } - ``` + """ + List KeyManagerStore API. + + Returns + ------- + dict + List of keys in the manager. + + Examples + -------- + ```json + { + "data": { + "keys": [] + }, + "success": true + } + ``` """ api_name = "SYNO.Core.Share.KeyManager.AutoKey" version = self.core_list[api_name]["minVersion"] @@ -1000,5 +1021,82 @@ def list(self) -> dict: "version": version, "method": "list", } - - return self.request_data(api_name, api_path, req_param) \ No newline at end of file + + return self.request_data(api_name, api_path, req_param) + + def decrypt_folder(self, name: str, password: str) -> dict: + """ + Decrypt a given share. + + Parameters + ---------- + name : str + The share name to decrypt. + password : str + The password to use for decrypting the share. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "decrypt", + "version": info['maxVersion'], + "name": name, + } + + req_param_encrypted = { + "password": password, + } + # If using https don't use encryption + if self.session._secure: + req_param.update(req_param_encrypted) + else: + encrypted_params = self.session.encrypt_params(req_param_encrypted) + req_param.update(encrypted_params) + + return self.request_data(api_name, api_path, req_param, method="post") + + def encrypt_folder(self, name: str) -> dict: + """ + Encrypt a given share. + + Parameters + ---------- + name : str + The share name to encrypt. + + Returns + ------- + dict + Success. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Share.Crypto" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "method": "encrypt", + "version": info['maxVersion'], + "name": name, + } + return self.request_data(api_name, api_path, req_param, method="post") diff --git a/synology_api/DSM/ControlPanel/SynologyAccount.py b/synology_api/DSM/ControlPanel/SynologyAccount.py index ab3084be..23a16f7f 100644 --- a/synology_api/DSM/ControlPanel/SynologyAccount.py +++ b/synology_api/DSM/ControlPanel/SynologyAccount.py @@ -1,4 +1,11 @@ +""" +Synology Account API endpoint. +""" from synology_api import base_api + class SynologyAccount(base_api.BaseApi): - pass \ No newline at end of file + """ + Synology Account API endpoint. + """ + pass diff --git a/synology_api/DSM/ControlPanel/TaskScheduler.py b/synology_api/DSM/ControlPanel/TaskScheduler.py index 53d4b3de..62098203 100644 --- a/synology_api/DSM/ControlPanel/TaskScheduler.py +++ b/synology_api/DSM/ControlPanel/TaskScheduler.py @@ -1,4 +1,11 @@ +""" +Task Scheduler API endpoint. +""" from synology_api import base_api + class TaskScheduler(base_api.BaseApi): - pass \ No newline at end of file + """ + Task Scheduler API endpoint. + """ + pass diff --git a/synology_api/DSM/ControlPanel/TerminalSNMP.py b/synology_api/DSM/ControlPanel/TerminalSNMP.py index 6070b379..f4483900 100644 --- a/synology_api/DSM/ControlPanel/TerminalSNMP.py +++ b/synology_api/DSM/ControlPanel/TerminalSNMP.py @@ -1,4 +1,11 @@ +""" +Terminal SNMP class for Synology DSM. +""" from synology_api import base_api + class TerminalSNMP(base_api.BaseApi): - pass \ No newline at end of file + """ + Terminal SNMP class for Synology DSM. + """ + pass diff --git a/synology_api/DSM/ControlPanel/UpdateRestore.py b/synology_api/DSM/ControlPanel/UpdateRestore.py index c0788c45..ac2d618d 100644 --- a/synology_api/DSM/ControlPanel/UpdateRestore.py +++ b/synology_api/DSM/ControlPanel/UpdateRestore.py @@ -1,4 +1,11 @@ +""" +Update and restore class for Synology DSM. +""" from synology_api import base_api + class UpdateRestore(base_api.BaseApi): - pass \ No newline at end of file + """ + Update and restore class for Synology DSM. + """ + pass diff --git a/synology_api/DSM/ControlPanel/UserGroup.py b/synology_api/DSM/ControlPanel/UserGroup.py index 16fab3c1..67903d0f 100644 --- a/synology_api/DSM/ControlPanel/UserGroup.py +++ b/synology_api/DSM/ControlPanel/UserGroup.py @@ -1,4 +1,11 @@ +""" +User Group API endpoint. +""" from synology_api import base_api + class UserGroup(base_api.BaseApi): - pass \ No newline at end of file + """ + User Group API endpoint. + """ + pass diff --git a/synology_api/DSM/ControlPanel/__init__.py b/synology_api/DSM/ControlPanel/__init__.py index b6f1a801..32bc6060 100644 --- a/synology_api/DSM/ControlPanel/__init__.py +++ b/synology_api/DSM/ControlPanel/__init__.py @@ -1,3 +1,7 @@ +""" +ControlPanel submodule for Synology DSM API. Provides access to all DSM Control Panel APIs. +""" + from .ApplicationPrivileges import ApplicationPrivileges from .DomainLDAP import DomainLDAP from .ExternalAccess import ExternalAccess @@ -21,7 +25,11 @@ from synology_api import base_api + class ControlPanel(base_api.BaseApi): + """ + ControlPanel submodule for Synology DSM API. Provides access to all DSM Control Panel APIs. + """ _app_priv = None _domain_ldap = None _ext_access = None @@ -41,179 +49,327 @@ class ControlPanel(base_api.BaseApi): _terminal_snmp = None _update_restore = None _user_group = None - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - @property def ApplicationPrivileges(self): + """ + ControlPanel: ApplicationPrivileges. + + Returns + ------- + ApplicationPrivileges + Instance of the ApplicationPrivileges API, sharing the same state as DSM. + """ if self._app_priv is None: # Create ApplicationPrivileges instance without calling __init__ - self._app_priv = ApplicationPrivileges.__new__(ApplicationPrivileges) + self._app_priv = ApplicationPrivileges.__new__( + ApplicationPrivileges) # Share the state self._app_priv.__dict__ = self.__dict__ return self._app_priv - + @property def DomainLDAP(self): + """ + ControlPanel: DomainLDAP. + + Returns + ------- + DomainLDAP + Instance of the DomainLDAP API, sharing the same state as DSM. + """ if self._domain_ldap is None: # Create DomainLDAP instance without calling __init__ self._domain_ldap = DomainLDAP.__new__(DomainLDAP) # Share the state self._domain_ldap.__dict__ = self.__dict__ return self._domain_ldap - + @property def ExternalAccess(self): + """ + ControlPanel: ExternalAccess. + + Returns + ------- + ExternalAccess + Instance of the ExternalAccess API, sharing the same state as DSM. + """ if self._ext_access is None: # Create ExternalAccess instance without calling __init__ self._ext_access = ExternalAccess.__new__(ExternalAccess) # Share the state self._ext_access.__dict__ = self.__dict__ return self._ext_access - + @property def ExternalDevices(self): + """ + ControlPanel: ExternalDevices. + + Returns + ------- + ExternalDevices + Instance of the ExternalDevices API, sharing the same state as DSM. + """ if self._ext_devices is None: # Create ExternalDevices instance without calling __init__ self._ext_devices = ExternalDevices.__new__(ExternalDevices) # Share the state self._ext_devices.__dict__ = self.__dict__ return self._ext_devices - + @property def FileServices(self): + """ + ControlPanel: FileServices. + + Returns + ------- + FileServices + Instance of the FileServices API, sharing the same state as DSM. + """ if self._file_services is None: # Create FileServices instance without calling __init__ self._file_services = FileServices.__new__(FileServices) # Share the state self._file_services.__dict__ = self.__dict__ return self._file_services - + @property def HardwarePower(self): + """ + ControlPanel: HardwarePower. + + Returns + ------- + HardwarePower + Instance of the HardwarePower API, sharing the same state as DSM. + """ if self._hard_power is None: # Create HardwarePower instance without calling __init__ - self._app_priv = HardwarePower.__new__(HardwarePower) + self._hard_power = HardwarePower.__new__(HardwarePower) # Share the state self._hard_power.__dict__ = self.__dict__ return self._hard_power - + @property def IndexingService(self): + """ + ControlPanel: IndexingService. + + Returns + ------- + IndexingService + Instance of the IndexingService API, sharing the same state as DSM. + """ if self._idx_service is None: # Create IndexingService instance without calling __init__ self._idx_service = IndexingService.__new__(IndexingService) # Share the state self._idx_service.__dict__ = self.__dict__ return self._idx_service - + @property def InfoCenter(self): + """ + ControlPanel: InfoCenter. + + Returns + ------- + InfoCenter + Instance of the InfoCenter API, sharing the same state as DSM. + """ if self._info_center is None: # Create InfoCenter instance without calling __init__ self._info_center = InfoCenter.__new__(InfoCenter) # Share the state self._info_center.__dict__ = self.__dict__ return self._info_center - + @property def LoginPortal(self): + """ + ControlPanel: LoginPortal. + + Returns + ------- + LoginPortal + Instance of the LoginPortal API, sharing the same state as DSM. + """ if self._log_portal is None: # Create LoginPortal instance without calling __init__ self._log_portal = LoginPortal.__new__(LoginPortal) # Share the state self._log_portal.__dict__ = self.__dict__ return self._log_portal - + @property def Network(self): + """ + ControlPanel: Network. + + Returns + ------- + Network + Instance of the Network API, sharing the same state as DSM. + """ if self._network is None: # Create Network instance without calling __init__ self._network = Network.__new__(Network) # Share the state self._network.__dict__ = self.__dict__ return self._network - + @property def Notifications(self): + """ + ControlPanel: Notifications. + + Returns + ------- + Notifications + Instance of the Notifications API, sharing the same state as DSM. + """ if self._notification is None: # Create Notifications instance without calling __init__ self._notification = Notifications.__new__(Notifications) # Share the state self._notification.__dict__ = self.__dict__ return self._notification - + @property def RegionalOptions(self): + """ + ControlPanel: RegionalOptions. + + Returns + ------- + RegionalOptions + Instance of the RegionalOptions API, sharing the same state as DSM. + """ if self._region_opt is None: # Create RegionalOptions instance without calling __init__ self._region_opt = RegionalOptions.__new__(RegionalOptions) # Share the state self._region_opt.__dict__ = self.__dict__ return self._region_opt - + @property def Security(self): + """ + ControlPanel: Security. + + Returns + ------- + Security + Instance of the Security API, sharing the same state as DSM. + """ if self._security is None: # Create Security instance without calling __init__ - self._app_priv = Security.__new__(Security) + self._security = Security.__new__(Security) # Share the state self._security.__dict__ = self.__dict__ return self._security - + @property def SharedFolder(self): + """ + ControlPanel: SharedFolder. + + Returns + ------- + SharedFolder + Instance of the SharedFolder API, sharing the same state as DSM. + """ if self._shared_folder is None: # Create SharedFolder instance without calling __init__ self._shared_folder = SharedFolder.__new__(SharedFolder) # Share the state self._shared_folder.__dict__ = self.__dict__ return self._shared_folder - + @property def SynologyAccount(self): + """ + ControlPanel: SynologyAccount. + + Returns + ------- + SynologyAccount + Instance of the SynologyAccount API, sharing the same state as DSM. + """ if self._syno_account is None: # Create ApplicationPrivileges instance without calling __init__ self._syno_account = SynologyAccount.__new__(SynologyAccount) # Share the state self._syno_account.__dict__ = self.__dict__ return self._syno_account - + @property def TaskScheduler(self): + """ + ControlPanel: TaskScheduler. + + Returns + ------- + TaskScheduler + Instance of the TaskScheduler API, sharing the same state as DSM. + """ if self._task_scheduler is None: # Create TaskScheduler instance without calling __init__ self._task_scheduler = TaskScheduler.__new__(TaskScheduler) # Share the state self._task_scheduler.__dict__ = self.__dict__ return self._task_scheduler - + @property def TerminalSNMP(self): + """ + ControlPanel: TerminalSNMP. + + Returns + ------- + TerminalSNMP + Instance of the TerminalSNMP API, sharing the same state as DSM. + """ if self._terminal_snmp is None: # Create TerminalSNMP instance without calling __init__ self._terminal_snmp = TerminalSNMP.__new__(TerminalSNMP) # Share the state self._terminal_snmp.__dict__ = self.__dict__ return self._terminal_snmp - + @property def UpdateRestore(self): + """ + ControlPanel: UpdateRestore. + + Returns + ------- + UpdateRestore + Instance of the UpdateRestore API, sharing the same state as DSM. + """ if self._update_restore is None: # Create UpdateRestore instance without calling __init__ self._update_restore = UpdateRestore.__new__(UpdateRestore) # Share the state self._update_restore.__dict__ = self.__dict__ return self._update_restore - + @property def UserGroup(self): + """ + ControlPanel: UserGroup. + + Returns + ------- + UserGroup + Instance of the UserGroup API, sharing the same state as DSM. + """ if self._user_group is None: # Create UserGroup instance without calling __init__ self._user_group = UserGroup.__new__(UserGroup) # Share the state self._user_group.__dict__ = self.__dict__ return self._user_group - \ No newline at end of file diff --git a/synology_api/DSM/Package/FileStation.py b/synology_api/DSM/Package/FileStation.py index e843572b..d4f39291 100644 --- a/synology_api/DSM/Package/FileStation.py +++ b/synology_api/DSM/Package/FileStation.py @@ -1,7 +1,17 @@ +""" +Implementation of FileStation API based on the Synology API documentation. +""" + from __future__ import annotations from typing import Optional, Any from datetime import datetime -import requests, tqdm, time, io, json, os, sys +import requests +import tqdm +import time +import io +import json +import os +import sys from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor from urllib import parse from treelib import Tree @@ -9,58 +19,60 @@ class FileStation(base_api.BaseApi): - """Implementation of FileStation API based on the Synology API documentation [link](https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf) + """ + Implementation of FileStation API based on the Synology API documentation. See: https://global.download.synology.com/download/Document/Software/DeveloperGuide/Package/FileStation/All/enu/Synology_File_Station_API_Guide.pdf . """ def get_info(self) -> dict[str, object]: - """Get info about FileStation - - Returns - ------- - dict[str, object] - List of FileStation info - - Example return - ---------- - ```json - { - "data": { - "allow_normal_disable_html": true, - "enable_list_usergrp": false, - "enable_send_email_attachment": true, - "enable_view_google": true, - "enable_view_microsoft": true, - "hostname": "SYNO-FLORENTB", - "is_manager": true, - "items": [ - { - "gid": 100 - }, - { - "gid": 101 - }, - { - "gid": 1023 - } - ], - "support_file_request": true, - "support_sharing": true, - "support_vfs": true, - "support_virtual": { - "enable_iso_mount": true, - "enable_remote_mount": true + """ + Get info about FileStation. + + Returns + ------- + dict of str to object + List of FileStation info. + + Examples + -------- + ```json + { + "data": { + "allow_normal_disable_html": true, + "enable_list_usergrp": false, + "enable_send_email_attachment": true, + "enable_view_google": true, + "enable_view_microsoft": true, + "hostname": "SYNO-FLORENTB", + "is_manager": true, + "items": [ + { + "gid": 100 + }, + { + "gid": 101 }, - "support_virtual_protocol": [ - "cifs", - "nfs", - "iso" - ], - "system_codepage": "fre", - "uid": 1027 + { + "gid": 1023 + } + ], + "support_file_request": true, + "support_sharing": true, + "support_vfs": true, + "support_virtual": { + "enable_iso_mount": true, + "enable_remote_mount": true }, - "success": true - } - ``` + "support_virtual_protocol": [ + "cifs", + "nfs", + "iso" + ], + "system_codepage": "fre", + "uid": 1027 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Info' info = self.gen_list[api_name] @@ -70,61 +82,62 @@ def get_info(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_list_share(self, - additional: Optional[list[str]] = None, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - onlywritable: bool = False - ) -> dict[str, object]: - """Get list of shared folders - - Parameters - ---------- - additional : Optional[list[str]], optional - Additionnal field to retrieve from shared folder. Defaults to `None` - All fields known are: `["real_path","size","owner","time","perm","mount_point_type","sync_share","volume_status","indexed","hybrid_share","worm_share"]`. - offset : Optional[int], optional - Offset in the shared folder list. Defaults to `None` - limit : Optional[int], optional - Limit the len of the returned list. Defaults to `None` - sort_by : Optional[str], optional - Specify which file information to sort on. Defaults to `None` - All fields know are: `["name","user","group","mtime","atime","ctime","crtime","posix"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `None` - All possible direction are: `["asc","desc"]` - onlywritable : bool, optional - Force list of shared folder where the user as write access. Defaults to `False` - - Returns - ------- - dict[str, object] - List of shared folder in FileStation - - Example return - ---------- - ```json - { - "data": { - "offset": 0, - "shares": [ - { - "isdir": true, - "name": "docker", - "path": "/docker" - }, - { - "isdir": true, - "name": "Documents", - "path": "/Documents" - } - ], - "total": 2 - }, - "success": true - } - ``` + additional: Optional[list[str]] = None, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + onlywritable: bool = False + ) -> dict[str, object]: + """ + Get list of shared folders. + + Parameters + ---------- + additional : Optional[list[str]], optional + Additionnal field to retrieve from shared folder. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","mount_point_type","sync_share","volume_status","indexed","hybrid_share","worm_share"]`. + offset : Optional[int], optional + Offset in the shared folder list. Defaults to `None` + limit : Optional[int], optional + Limit the len of the returned list. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields know are: `["name","user","group","mtime","atime","ctime","crtime","posix"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + onlywritable : bool, optional + Force list of shared folder where the user as write access. Defaults to `False` + + Returns + ------- + dict[str, object] + List of shared folder in FileStation. + + Examples + -------- + ```json + { + "data": { + "offset": 0, + "shares": [ + { + "isdir": true, + "name": "docker", + "path": "/docker" + }, + { + "isdir": true, + "name": "Documents", + "path": "/Documents" + } + ], + "total": 2 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.List' info = self.gen_list[api_name] @@ -143,71 +156,72 @@ def get_list_share(self, return self.request_data(api_name, api_path, req_param) def get_file_list(self, - folder_path: str, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - pattern: Optional[list[str]] = None, - filetype: Optional[str] = None, - goto_path: Optional[str] = None, - additional: Optional[list[str]] = None, - check_dir: Optional[bool] = None - ) -> dict[str, object]: - """Get list of files in a folder - - Parameters - ---------- - folder_path : str - A listed folder path starting with a shared folder. - offset : Optional[int], optional - Specify how many files are skipped before beginning to return listed files. Defaults to `None` - limit : Optional[int], optional - Number of files requested. 0 indicates to list all files with a given folder. Defaults to `None` - sort_by : Optional[str], optional - Specify which file information to sort on. Defaults to `None` - All fields known are: `["name","size","user","group","mtime","atime","ctime","crtime","posix","type"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `None` - All possible direction are: `["asc","desc"]` - pattern : Optional[list[str]], optional - Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` - Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. - filetype : Optional[str], optional - "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` - All fields know are: `["file","dir","all"]` - goto_path : Optional[str], optional - Folder path starting with a shared folder. Return all files and sub-folders within folder_path path until goto_path path recursively. Defaults to `None` - Note: goto_path is only valid with parameter "additional" contains real_path. - additional : Optional[list[str]], optional - Additionnal field to retrieve from file. Defaults to `None` - All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. - check_dir : Optional[bool], optional - _description_. Defaults to `None` - - Returns - ------- - dict[str, object] - _description_ - - Example return - ---------- - ```json - { - "data": { - "files": [ - { - "isdir": false, - "name": "compose.yaml", - "path": "/docker/compose.yaml" - } - ], - "offset": 0, - "total": 1 - }, - "success": true - } - ``` + folder_path: str, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + pattern: Optional[list[str]] = None, + filetype: Optional[str] = None, + goto_path: Optional[str] = None, + additional: Optional[list[str]] = None, + check_dir: Optional[bool] = None + ) -> dict[str, object]: + """ + Get list of files in a folder. + + Parameters + ---------- + folder_path : str + A listed folder path starting with a shared folder. + offset : Optional[int], optional + Specify how many files are skipped before beginning to return listed files. Defaults to `None` + limit : Optional[int], optional + Number of files requested. 0 indicates to list all files with a given folder. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name","size","user","group","mtime","atime","ctime","crtime","posix","type"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + pattern : Optional[list[str]], optional + Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` + Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. + filetype : Optional[str], optional + "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` + All fields know are: `["file","dir","all"]` + goto_path : Optional[str], optional + Folder path starting with a shared folder. Return all files and sub-folders within folder_path path until goto_path path recursively. Defaults to `None` + Note: goto_path is only valid with parameter "additional" contains real_path. + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. + check_dir : Optional[bool], optional + _description_. Defaults to `None` + + Returns + ------- + dict[str, object] + Information about the files in the folder. + + Examples + -------- + ```json + { + "data": { + "files": [ + { + "isdir": false, + "name": "compose.yaml", + "path": "/docker/compose.yaml" + } + ], + "offset": 0, + "total": 1 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.List' @@ -232,42 +246,43 @@ def get_file_list(self, return self.request_data(api_name, api_path, req_param) def get_file_info(self, path: list[str], additional: Optional[list[str]] = None) -> dict[str, object]: - """Get information of file(s) / folder(s). - - Parameters - ---------- - path : list[str] - One or more folder/file path(s) starting with a shared folder - additional : Optional[list[str]], optional - Additionnal field to retrieve from file. Defaults to `None` - All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. - - Returns - ------- - dict[str, object] - Information of file(s) / folder(s) - - Example return - ---------- - ```json - { - "data": { - "files": [ - { - "isdir": true, - "name": "Films", - "path": "/Films" - }, - { - "isdir": true, - "name": "Documents", - "path": "/Documents" - } - ] - }, - "success": true - } - ``` + """ + Get information of file(s) / folder(s). + + Parameters + ---------- + path : list[str] + One or more folder/file path(s) starting with a shared folder + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type","mount_point_type"]`. + + Returns + ------- + dict[str, object] + Information of file(s) / folder(s). + + Examples + -------- + ```json + { + "data": { + "files": [ + { + "isdir": true, + "name": "Films", + "path": "/Films" + }, + { + "isdir": true, + "name": "Documents", + "path": "/Documents" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.List' info = self.gen_list[api_name] @@ -282,65 +297,66 @@ def get_file_info(self, path: list[str], additional: Optional[list[str]] = None) return self.request_data(api_name, api_path, req_param) def search_start(self, - folder_path: str = None, recursive: Optional[bool] = None, pattern: Optional[list[str]] = None, - extension: Optional[list[str]] = None, filetype: Optional[str] = None, size_from: Optional[int] = None, - size_to: Optional[int] = None, mtime_from: Optional[int] = None, mtime_to: Optional[int] = None, - crtime_from: Optional[int] = None, crtime_to: Optional[int] = None, atime_from: Optional[int] = None, - atime_to: Optional[int] = None, owner: Optional[str] = None, group: Optional[str] = None - ) -> dict[str, object]: - """Start to search files according to given criteria. If more than one criterion is given in different parameters, searched files match all these criteria. - - Parameters - ---------- - folder_path : str, optional - A searched folder path starting with a shared folder. One or more folder paths to be searched, separated by commas "," and around brackets. Defaults to `None` - recursive : Optional[bool], optional - If searching files within a folder and subfolders recursively or not. Defaults to `None` - pattern : Optional[list[str]], optional - Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` - Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern.. Defaults to `None` - extension : Optional[list[str]], optional - Search for files whose extensions match a file type pattern in a case-insensitive glob pattern. If you give this criterion, folders aren't matched. Defaults to `None` - filetype : Optional[str], optional - "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` - All fields know are: `["file","dir","all"]` - size_from : Optional[int], optional - Search for files whose sizes are greater than the given byte size. Defaults to `None` - size_to : Optional[int], optional - Search for files whose sizes are less than the given byte size. Defaults to `None` - mtime_from : Optional[int], optional - Search for files whose last modified time after the given Linux timestamp (UTC) in second. Defaults to `None` - mtime_to : Optional[int], optional - Search for files whose last modified time before the given Linux timestamp (UTC) in second. Defaults to `None` - crtime_from : Optional[int], optional - Search for files whose create time after the given Linux timestamp (UTC) in second. Defaults to `None` - crtime_to : Optional[int], optional - Search for files whose create time before the given Linux timestamp (UTC) in second. Defaults to `None` - atime_from : Optional[int], optional - Search for files whose last access time after the given Linux timestamp (UTC) in second. Defaults to `None` - atime_to : Optional[int], optional - Search for files whose last access time before the given Linux timestamp (UTC) in second. Defaults to `None` - owner : Optional[str], optional - Search for files whose user name matches this criterion. This criterion is case-insensitive. Defaults to `None` - group : Optional[str], optional - Search for files whose group name matches this criterion. This criterion is case-insensitive. Defaults to `None` - - Returns - ------- - dict[str, object] - A unique ID for the search task - - Example return - ---------- - ```json - { - "data": { - "has_not_index_share": true, - "taskid": "51CE617CF57B24E5" - }, - "success": true - } - ``` + folder_path: str = None, recursive: Optional[bool] = None, pattern: Optional[list[str]] = None, + extension: Optional[list[str]] = None, filetype: Optional[str] = None, size_from: Optional[int] = None, + size_to: Optional[int] = None, mtime_from: Optional[int] = None, mtime_to: Optional[int] = None, + crtime_from: Optional[int] = None, crtime_to: Optional[int] = None, atime_from: Optional[int] = None, + atime_to: Optional[int] = None, owner: Optional[str] = None, group: Optional[str] = None + ) -> dict[str, object]: + """ + Start to search files according to given criteria. If more than one criterion is given in different parameters, searched files match all these criteria. + + Parameters + ---------- + folder_path : str, optional + A searched folder path starting with a shared folder. One or more folder paths to be searched, separated by commas "," and around brackets. Defaults to `None` + recursive : Optional[bool], optional + If searching files within a folder and subfolders recursively or not. Defaults to `None` + pattern : Optional[list[str]], optional + Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` + Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern.. Defaults to `None` + extension : Optional[list[str]], optional + Search for files whose extensions match a file type pattern in a case-insensitive glob pattern. If you give this criterion, folders aren't matched. Defaults to `None` + filetype : Optional[str], optional + "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` + All fields know are: `["file","dir","all"]` + size_from : Optional[int], optional + Search for files whose sizes are greater than the given byte size. Defaults to `None` + size_to : Optional[int], optional + Search for files whose sizes are less than the given byte size. Defaults to `None` + mtime_from : Optional[int], optional + Search for files whose last modified time after the given Linux timestamp (UTC) in second. Defaults to `None` + mtime_to : Optional[int], optional + Search for files whose last modified time before the given Linux timestamp (UTC) in second. Defaults to `None` + crtime_from : Optional[int], optional + Search for files whose create time after the given Linux timestamp (UTC) in second. Defaults to `None` + crtime_to : Optional[int], optional + Search for files whose create time before the given Linux timestamp (UTC) in second. Defaults to `None` + atime_from : Optional[int], optional + Search for files whose last access time after the given Linux timestamp (UTC) in second. Defaults to `None` + atime_to : Optional[int], optional + Search for files whose last access time before the given Linux timestamp (UTC) in second. Defaults to `None` + owner : Optional[str], optional + Search for files whose user name matches this criterion. This criterion is case-insensitive. Defaults to `None` + group : Optional[str], optional + Search for files whose group name matches this criterion. This criterion is case-insensitive. Defaults to `None` + + Returns + ------- + dict[str, object] + A unique ID for the search task. + + Examples + -------- + ```json + { + "data": { + "has_not_index_share": true, + "taskid": "51CE617CF57B24E5" + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Search' @@ -369,67 +385,68 @@ def search_start(self, return self.request_data(api_name, api_path, req_param) def get_search_list(self, - taskid: str, - offset: Optional[int] = None, - limit: Optional[int] = None, - sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, - pattern: Optional[list[str]] = None, - filetype: Optional[str] = None, - additional: Optional[list[str]] = None - ) -> dict[str, object]: - """List matched files in a search temporary database. You can check the finished value in response to know if the search operation is processing or has been finished. - - Parameters - ---------- - taskid : str - A unique ID for the search task which is obtained from `search_start` method. - offset : Optional[int], optional - Specify how many files are skipped before beginning to return listed files. Defaults to `None` - limit : Optional[int], optional - Number of files requested. 0 indicates to list all files with a given folder. Defaults to `None` - sort_by : Optional[str], optional - Specify which file information to sort on. Defaults to `None` - All fields known are: `["name","size","user","group","mtime","atime","ctime","crtime","posix","type"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `None` - All possible direction are: `["asc","desc"]` - pattern : Optional[list[str]], optional - Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` - Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. - filetype : Optional[str], optional - "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` - All fields know are: `["file","dir","all"]` - additional : Optional[list[str]], optional - Additionnal field to retrieve from file. Defaults to `None` - All fields known are: `["real_path","size","owner","time","perm","type"]`. - - Returns - ------- - dict[str, object] - Infos about the search and the matched files. - - Example return - ---------- - ```json - { - "data": { - "files": [ - { - "isdir": false, - "name": "compose.yaml", - "path": "/docker/compose.yaml" - } - ], - "finished": true, - "offset": 0, - "total": 1 - }, - "success": true - } - ``` + taskid: str, + offset: Optional[int] = None, + limit: Optional[int] = None, + sort_by: Optional[str] = None, + sort_direction: Optional[str] = None, + pattern: Optional[list[str]] = None, + filetype: Optional[str] = None, + additional: Optional[list[str]] = None + ) -> dict[str, object]: """ - + List matched files in a search temporary database. You can check the finished value in response to know if the search operation is processing or has been finished. + + Parameters + ---------- + taskid : str + A unique ID for the search task which is obtained from `search_start` method. + offset : Optional[int], optional + Specify how many files are skipped before beginning to return listed files. Defaults to `None` + limit : Optional[int], optional + Number of files requested. 0 indicates to list all files with a given folder. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name","size","user","group","mtime","atime","ctime","crtime","posix","type"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + pattern : Optional[list[str]], optional + Given glob pattern(s) to find files whose names and extensions match a case insensitive glob pattern. Defaults to `None` + Note: 1. If the pattern doesn't contain any glob syntax (? and *), * of glob syntax will be added at begin and end of the string automatically for partially matching the pattern. + filetype : Optional[str], optional + "file": only enumerate regular files; "dir": only enumerate folders; "all" enumerate regular files and folders. Defaults to `None` + All fields know are: `["file","dir","all"]` + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type"]`. + + Returns + ------- + dict[str, object] + Infos about the search and the matched files. + + Examples + -------- + ```json + { + "data": { + "files": [ + { + "isdir": false, + "name": "compose.yaml", + "path": "/docker/compose.yaml" + } + ], + "finished": true, + "offset": 0, + "total": 1 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Search' info = self.gen_list[api_name] api_path = info['path'] @@ -449,25 +466,26 @@ def get_search_list(self, return self.request_data(api_name, api_path, req_param) def stop_search_task(self, taskid: str | list[str]) -> dict[str, object]: - """Stop the searching task(s). The search temporary database won't be deleted, so it's possible to list the search result using list method after stopping it - - Parameters - ---------- - taskid : str | list[str] - Unique ID(s) for the search task which are obtained from `search_start` method. Specify multiple search task IDs by using list type. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Stop the searching task(s). The search temporary database won't be deleted, so it's possible to list the search result using list method after stopping it. + + Parameters + ---------- + taskid : str | list[str] + Unique ID(s) for the search task which are obtained from `search_start` method. Specify multiple search task IDs by using list type. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Search' info = self.gen_list[api_name] @@ -481,25 +499,26 @@ def stop_search_task(self, taskid: str | list[str]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def clean_search_task(self, taskid: str | list[str]) -> dict[str, object]: - """ Delete search temporary database(s). - - Parameters - ---------- - taskid : str | list[str] - Unique ID(s) for the search task which are obtained from `search_start` method. Specify multiple search task IDs by using list type. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Delete search temporary database(s). + + Parameters + ---------- + taskid : str | list[str] + Unique ID(s) for the search task which are obtained from `search_start` method. Specify multiple search task IDs by using list type. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Search' info = self.gen_list[api_name] @@ -511,86 +530,87 @@ def clean_search_task(self, taskid: str | list[str]) -> dict[str, object]: } return self.request_data(api_name, api_path, req_param) - + def get_mount_point_list(self, mount_type: str, offset: Optional[int] = None, limit: Optional[int] = None, - sort_by: Optional[str] = None, sort_direction: Optional[str] = None, additional: Optional[list[str]] = None - ) -> dict[str, object]: - """List all mount point folders on one given type of virtual file system. - - Parameters - ---------- - mount_type : str - A type of virtual file systems. - All fields known are: `["cifs","nfs","iso"]` - offset : Optional[int], optional - Specify how many mount point folders are skipped before beginning to return listed files. Defaults to `None` - limit : Optional[int], optional - Number of mount point folders requested. 0 indicates to list all files with a given folder. Defaults to `None` - sort_by : Optional[str], optional - Specify which file information to sort on. Defaults to `None` - All fields known are: `["name",,"user","group","mtime","atime","ctime","crtime","posix"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `None` - All possible direction are: `["asc","desc"]` - additional : Optional[list[str]], optional - Additionnal field to retrieve from file. Defaults to `None` - All fields known are: `["real_path","size","owner","time","perm","volume_status"]`. - - Returns - ------- - dict[str, object] - List of mount point folders - - Example return - ---------- - ```json - { - "data": { - "folders": [ - { - "additional": { - "mount_point_type": "remote", - "owner": { - "gid": 100, - "group": "users", - "uid": 1024, - "user": "admin" - }, - "perm": { - "acl": { - "append": true, - "del": true, - "exec": true, - "read": true, - "write": true - }, - "is_acl_mode": false, - "posix": 777 - }, - "real_path": "/volume1/vidoe/remote", - "time": { - "atime": 1372313445, - "crtime": 1320204670, - "ctime": 1371206944, - "mtime": 1371206944 - }, - "volume_status": { - "freespace": 12282422599680, - "readonly": false, - "totalspace": 801958928384 - } - }, - "isdir": true, - "name": "remote", - "path": "/video/remote" - } - ], - "offset": 0, - "total": 0 - }, - "success": true - } - ``` + sort_by: Optional[str] = None, sort_direction: Optional[str] = None, additional: Optional[list[str]] = None + ) -> dict[str, object]: + """ + List all mount point folders on one given type of virtual file system. + + Parameters + ---------- + mount_type : str + A type of virtual file systems. + All fields known are: `["cifs","nfs","iso"]` + offset : Optional[int], optional + Specify how many mount point folders are skipped before beginning to return listed files. Defaults to `None` + limit : Optional[int], optional + Number of mount point folders requested. 0 indicates to list all files with a given folder. Defaults to `None` + sort_by : Optional[str], optional + Specify which file information to sort on. Defaults to `None` + All fields known are: `["name",,"user","group","mtime","atime","ctime","crtime","posix"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + additional : Optional[list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","volume_status"]`. + + Returns + ------- + dict[str, object] + List of mount point folders. + + Examples + -------- + ```json + { + "data": { + "folders": [ + { + "additional": { + "mount_point_type": "remote", + "owner": { + "gid": 100, + "group": "users", + "uid": 1024, + "user": "admin" + }, + "perm": { + "acl": { + "append": true, + "del": true, + "exec": true, + "read": true, + "write": true + }, + "is_acl_mode": false, + "posix": 777 + }, + "real_path": "/volume1/vidoe/remote", + "time": { + "atime": 1372313445, + "crtime": 1320204670, + "ctime": 1371206944, + "mtime": 1371206944 + }, + "volume_status": { + "freespace": 12282422599680, + "readonly": false, + "totalspace": 801958928384 + } + }, + "isdir": true, + "name": "remote", + "path": "/video/remote" + } + ], + "offset": 0, + "total": 0 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.VirtualFolder' @@ -610,56 +630,57 @@ def get_mount_point_list(self, mount_type: str, offset: Optional[int] = None, li return self.request_data(api_name, api_path, req_param) def get_favorite_list(self, - offset: Optional[int] = None, - limit: Optional[int] = None, - status_filter: Optional[str] = None, - additional: Optional[str | list[str]] = None - ) -> dict[str, object]: - """List user's favorites. - - Parameters - ---------- - offset : Optional[int], optional - Specify how many favorites are skipped before beginning to return user's favorites. Defaults to `None` - limit : Optional[int], optional - Number of favorites requested. 0 indicates to list all favorites. Defaults to `None` - status_filter : Optional[str], optional - Show favorites with a given favorite status. Defaults to `None` - All fields known are: `["valid","broken","all"]` - additional : Optional[str | list[str]], optional - Additionnal field to retrieve from file. Defaults to `None` - All fields known are: `["real_path","owner","time","perm","mount_point_type"]`. - - Returns - ------- - dict[str, object] - List of user's favorites - - Example return - ---------- - ```json - { - "data": { - "favorites": [ - { - "isdir": true, - "name": "My Video Shared folder", - "path": "/video", - "status": "valid" - }, - { - "isdir": false, - "name": "deletedfolder", - "path": "/share/deletedfolder", - "status": "broken" - } - ], - "offset": 0, - "total": 2 - }, - "success": true - } - ``` + offset: Optional[int] = None, + limit: Optional[int] = None, + status_filter: Optional[str] = None, + additional: Optional[str | list[str]] = None + ) -> dict[str, object]: + """ + List user's favorites. + + Parameters + ---------- + offset : Optional[int], optional + Specify how many favorites are skipped before beginning to return user's favorites. Defaults to `None` + limit : Optional[int], optional + Number of favorites requested. 0 indicates to list all favorites. Defaults to `None` + status_filter : Optional[str], optional + Show favorites with a given favorite status. Defaults to `None` + All fields known are: `["valid","broken","all"]` + additional : Optional[str | list[str]], optional + Additionnal field to retrieve from file. Defaults to `None` + All fields known are: `["real_path","owner","time","perm","mount_point_type"]`. + + Returns + ------- + dict[str, object] + List of user's favorites. + + Examples + -------- + ```json + { + "data": { + "favorites": [ + { + "isdir": true, + "name": "My Video Shared folder", + "path": "/video", + "status": "valid" + }, + { + "isdir": false, + "name": "deletedfolder", + "path": "/share/deletedfolder", + "status": "broken" + } + ], + "offset": 0, + "total": 2 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Favorite' @@ -677,33 +698,34 @@ def get_favorite_list(self, return self.request_data(api_name, api_path, req_param) def add_a_favorite(self, path: str, name: Optional[str] = None, index: Optional[int] = -1) -> dict[str, object]: - """ Add a folder to user's favorites. - - Parameters - ---------- - path : str - A folder path starting with a shared folder is added to the user's favorites. - name : Optional[str], optional - A favorite name. Defaults to `None` - index : Optional[int], optional - Index of location of an added favorite. Defaults to `-1` - If it's equal to -1, the favorite will be added to the last one in user's favorite. - If it's between 0 ~ total number of favorites-1, the favorite will be inserted into user's favorites by the index. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` - """ - + """ + Add a folder to user's favorites. + + Parameters + ---------- + path : str + A folder path starting with a shared folder is added to the user's favorites. + name : Optional[str], optional + A favorite name. Defaults to `None` + index : Optional[int], optional + Index of location of an added favorite. Defaults to `-1` + If it's equal to -1, the favorite will be added to the last one in user's favorite. + If it's between 0 ~ total number of favorites-1, the favorite will be inserted into user's favorites by the index. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Favorite' info = self.gen_list[api_name] api_path = info['path'] @@ -718,25 +740,26 @@ def add_a_favorite(self, path: str, name: Optional[str] = None, index: Optional[ return self.request_data(api_name, api_path, req_param) def delete_a_favorite(self, path: str) -> dict[str, object]: - """Delete a favorite in user's favorites. - - Parameters - ---------- - path : str - A folder path starting with a shared folder is deleted from a user's favorites. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Delete a favorite in user's favorites. + + Parameters + ---------- + path : str + A folder path starting with a shared folder is deleted from a user's favorites. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Favorite' info = self.gen_list[api_name] @@ -750,20 +773,21 @@ def delete_a_favorite(self, path: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def clear_broken_favorite(self) -> dict[str, object]: - """ Delete all broken statuses of favorites. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Delete all broken statuses of favorites. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Favorite' info = self.gen_list[api_name] @@ -776,27 +800,28 @@ def clear_broken_favorite(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object]: - """Edit a favorite name. - - Parameters - ---------- - path : str - A folder path starting with a shared folder is edited from a user's favorites. - new_name : str - New favorite name. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Edit a favorite name. + + Parameters + ---------- + path : str + A folder path starting with a shared folder is edited from a user's favorites. + new_name : str + New favorite name. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Favorite' info = self.gen_list[api_name] @@ -811,32 +836,33 @@ def edit_favorite_name(self, path: str, new_name: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def replace_all_favorite(self, path: str | list[str], name: str | list[str]) -> dict[str, object]: - """ Replace multiple favorites of folders to the existing user's favorites. - - Parameters - ---------- - path : str | list[str] - One or more folder paths starting with a shared folder is added to the user's favorites. - The number of paths must be the same as the number of favorite names in the name parameter. - The first path parameter corresponds to the first name parameter. - name : str | list[str] - One or more new favorite names. The number of favorite names must be the same as the number of folder paths in the path parameter. - The first name parameter corresponding to the first path parameter. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` - """ - + """ + Replace multiple favorites of folders to the existing user's favorites. + + Parameters + ---------- + path : str | list[str] + One or more folder paths starting with a shared folder is added to the user's favorites. + The number of paths must be the same as the number of favorite names in the name parameter. + The first path parameter corresponds to the first name parameter. + name : str | list[str] + One or more new favorite names. The number of favorite names must be the same as the number of folder paths in the path parameter. + The first name parameter corresponding to the first path parameter. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Favorite' info = self.gen_list[api_name] api_path = info['path'] @@ -850,26 +876,26 @@ def replace_all_favorite(self, path: str | list[str], name: str | list[str]) -> return self.request_data(api_name, api_path, req_param) def get_thumbnail(self, path: str, size: Optional[str] = "small", rotate: Optional[int] = None) -> bytes: - """ Get a thumbnail of a file. - - Parameters - ---------- - path : str - A file path starting with a shared folder. - size : str - The size of the thumbnail. Defaults to `small` - All fields known are: `["small","medium","large","original"]` - rotate : Optional[int], optional - The angle of the thumbnail. Defaults to `None` - All fields known are: `[0,1,2,3,4] = ["0°","90°","180°","270°","360°"]` - - Returns - ------- - bytes - The thumbnail of the file. If the file is not found, it will raise an exception. - - """ - + """ + Get a thumbnail of a file. + + Parameters + ---------- + path : str + A file path starting with a shared folder. + size : str + The size of the thumbnail. Defaults to `small` + All fields known are: `["small","medium","large","original"]` + rotate : Optional[int], optional + The angle of the thumbnail. Defaults to `None` + All fields known are: `[0,1,2,3,4] = ["0°","90°","180°","270°","360°"]` + + Returns + ------- + bytes + The thumbnail of the file. If the file is not found, it will raise an exception. + """ + api_name = 'SYNO.FileStation.Thumb' info = self.gen_list[api_name] api_path = info['path'] @@ -880,7 +906,8 @@ def get_thumbnail(self, path: str, size: Optional[str] = "small", rotate: Option 'size': size, 'rotate': rotate } - response = self.request_data(api_name, api_path, req_param, response_json=False) + response = self.request_data( + api_name, api_path, req_param, response_json=False) match response.status_code: case 200: return response.content @@ -890,28 +917,29 @@ def get_thumbnail(self, path: str, size: Optional[str] = "small", rotate: Option raise Exception(f"HTTP Status error : {response.status_code}") def start_dir_size_calc(self, path: str | list[str]) -> dict[str, object]: - """Start to calculate size for one or more file/folder paths. - - Parameters - ---------- - path : str | list[str] - One or more file/folder paths starting with a shared folder for calculating cumulative size - - Returns - ------- - dict[str, object] - Task ID for the size calculation request - - Example return - ---------- - ```json - { - "data": { - "taskid": "51CBD7CD5C76E461" - }, - "success": true - } - ``` + """ + Start to calculate size for one or more file/folder paths. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder for calculating cumulative size + + Returns + ------- + dict[str, object] + Task ID for the size calculation request. + + Examples + -------- + ```json + { + "data": { + "taskid": "51CBD7CD5C76E461" + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.DirSize' info = self.gen_list[api_name] @@ -924,31 +952,32 @@ def start_dir_size_calc(self, path: str | list[str]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param)['data']['taskid'] def get_dir_status(self, taskid: str) -> dict[str, object]: - """Get the status of the size calculating task. - - Parameters - ---------- - taskid : str - A unique ID for the task which is obtained from `start_dir_size_calc` method. - - Returns - ------- - dict[str, object] - Infos about the size calculating task - - Example return - ---------- - ```json - { - "data": { - "finished": true, - "num_dir": 3, - "num_file": 104, - "total_size": 29973265 - }, - "success": true - } - ``` + """ + Get the status of the size calculating task. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_dir_size_calc` method. + + Returns + ------- + dict[str, object] + Infos about the size calculating task. + + Examples + -------- + ```json + { + "data": { + "finished": true, + "num_dir": 3, + "num_file": 104, + "total_size": 29973265 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.DirSize' info = self.gen_list[api_name] @@ -962,27 +991,28 @@ def get_dir_status(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def stop_dir_size_calc(self, taskid: str) -> dict[str, object]: - """Stop the calculation. - - Parameters - ---------- - taskid : str - A unique ID for the task which is obtained from `start_dir_size_calc` method. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` - """ - + """ + Stop the calculation. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_dir_size_calc` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.DirSize' info = self.gen_list[api_name] api_path = info['path'] @@ -994,30 +1024,31 @@ def stop_dir_size_calc(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def start_md5_calc(self, file_path: str) -> dict[str, object]: - """Start to get MD5 of a file. - - Parameters - ---------- - file_path : str - A file path starting with a shared folder for calculating MD5 value. - - Returns - ------- - dict[str, object] - Task ID for the size calculation request - - Example return - ---------- - ```json - { - "data": { - "taskid": "51CBD7CD5C76E461" - }, - "success": true - } - ``` """ - + Start to get MD5 of a file. + + Parameters + ---------- + file_path : str + A file path starting with a shared folder for calculating MD5 value. + + Returns + ------- + dict[str, object] + Task ID for the size calculation request. + + Examples + -------- + ```json + { + "data": { + "taskid": "51CBD7CD5C76E461" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.MD5' info = self.gen_list[api_name] api_path = info['path'] @@ -1029,31 +1060,32 @@ def start_md5_calc(self, file_path: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_md5_status(self, taskid: str) -> dict[str, object]: - """ Get the status of the MD5 calculation task. - - Parameters - ---------- - taskid : str - A unique ID for the task which is obtained from `start_md5_status` method. - - Returns - ------- - dict[str, object] - Finished status of the MD5 calculation task and the md5 of requested file - - Example return - ---------- - ```json - { - "data": { - "finished": true, - "md5": "6336c5a59aa63dd2042783f88e15410a" - }, - "success": true - } - ``` """ - + Get the status of the MD5 calculation task. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_md5_status` method. + + Returns + ------- + dict[str, object] + Finished status of the MD5 calculation task and the md5 of requested file. + + Examples + -------- + ```json + { + "data": { + "finished": true, + "md5": "6336c5a59aa63dd2042783f88e15410a" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.MD5' info = self.gen_list[api_name] api_path = info['path'] @@ -1065,25 +1097,26 @@ def get_md5_status(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def stop_md5_calc(self, taskid: str) -> dict[str, object]: - """Stop calculating the MD5 of a file. - - Parameters - ---------- - taskid : str - A unique ID for the task which is obtained from `start_md5_status` method. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Stop calculating the MD5 of a file. + + Parameters + ---------- + taskid : str + A unique ID for the task which is obtained from `start_md5_status` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.DirSize' info = self.gen_list[api_name] @@ -1096,41 +1129,42 @@ def stop_md5_calc(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def check_permissions(self, - path: str, - filename: str, - overwrite: Optional[bool] = False, - create_only: Optional[bool] = True - ) -> dict[str, object]: - """Check if a logged-in user has write permission to create new files/folders in a given folder - - Parameters - ---------- - path : str - A folder path starting with a shared folder to check write permission - filename : str - A filename you want to write to given path - overwrite : Optional[bool], optional - The value could be one of following: Defaults to `False` - - "true": overwrite the destination file if one exists. - - "false": skip if the destination file exists. - - Note: when it's not specified as true or false, it will be responded with error when the destination file exists. - - create_only : Optional[bool], optional - If set to "true", the permission will be allowed when there is non-existent file/folder. Defaults to `True` - - Returns - ------- - dict[str, object] - The request will get error response if no write permission for the specified path. - - Example return - ---------- - ```json - { - "success": true - } - ``` + path: str, + filename: str, + overwrite: Optional[bool] = False, + create_only: Optional[bool] = True + ) -> dict[str, object]: + """ + Check if a logged-in user has write permission to create new files/folders in a given folder. + + Parameters + ---------- + path : str + A folder path starting with a shared folder to check write permission + filename : str + A filename you want to write to given path + overwrite : Optional[bool], optional + The value could be one of following: Defaults to `False` + - "true": overwrite the destination file if one exists. + - "false": skip if the destination file exists. + + Note: when it's not specified as true or false, it will be responded with error when the destination file exists. + + create_only : Optional[bool], optional + If set to "true", the permission will be allowed when there is non-existent file/folder. Defaults to `True` + + Returns + ------- + dict[str, object] + The request will get error response if no write permission for the specified path. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.CheckPermission' info = self.gen_list[api_name] @@ -1146,43 +1180,44 @@ def check_permissions(self, return self.request_data(api_name, api_path, req_param) def upload_file(self, - dest_path: str, - file_path: str, - create_parents: bool = True, - overwrite: bool = True, - verify: bool = False, - progress_bar: bool = True - ) -> tuple[int, dict[str, object]]: - """Upload a file to a given destination path. - - Parameters - ---------- - dest_path : str - A destination folder path starting with a shared folder. - file_path : str - A file path to be uploaded. - create_parents : bool, optional - Create parent folder(s) if none exist. Defaults to `True` - overwrite : bool, optional - If `True` overwrite the destination file if one exist else skip the upload if the destination file exist. Defaults to `True` - verify : bool, optional - If `True` use HTTPS else use HTTP. Defaults to `False` - progress_bar : bool, optional - Enable or note the progress bar in the stdout. Defaults to `True` - - Returns - ------- - tuple[int, dict[str, object]] - If failed return a tuple with the status code and the error message - else return the response json - - Example return - ---------- - ```json - { - "success": true - } - ``` + dest_path: str, + file_path: str, + create_parents: bool = True, + overwrite: bool = True, + verify: bool = False, + progress_bar: bool = True + ) -> tuple[int, dict[str, object]]: + """ + Upload a file to a given destination path. + + Parameters + ---------- + dest_path : str + A destination folder path starting with a shared folder. + file_path : str + A file path to be uploaded. + create_parents : bool, optional + Create parent folder(s) if none exist. Defaults to `True` + overwrite : bool, optional + If `True` overwrite the destination file if one exist else skip the upload if the destination file exist. Defaults to `True` + verify : bool, optional + If `True` use HTTPS else use HTTP. Defaults to `False` + progress_bar : bool, optional + Enable or note the progress bar in the stdout. Defaults to `True` + + Returns + ------- + tuple[int, dict[str, object]] + If failed return a tuple with the status code and the error message + else return the response json. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Upload' info = self.gen_list[api_name] @@ -1211,13 +1246,15 @@ def upload_file(self, unit_divisor=1024 ) - monitor = MultipartEncoderMonitor(encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) + monitor = MultipartEncoderMonitor( + encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) r = session.post( url, data=monitor, verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': monitor.content_type} + headers={"X-SYNO-TOKEN": self.session._syno_token, + 'Content-Type': monitor.content_type} ) else: @@ -1225,7 +1262,8 @@ def upload_file(self, url, data=encoder, verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': encoder.content_type} + headers={"X-SYNO-TOKEN": self.session._syno_token, + 'Content-Type': encoder.content_type} ) session.close() @@ -1235,37 +1273,38 @@ def upload_file(self, return r.json() def get_shared_link_info(self, link_id: str) -> dict[str, object]: - """ Get information of a sharing link by the sharing link ID - - Parameters - ---------- - link_id : str - A unique ID of a sharing link. - - Returns - ------- - dict[str, object] - Information about the sharing link - - Example return - ---------- - ```json - { - "data": { - "date_available": "0", - "date_expired": "0", - "has_password": false, - "id": "pHTBKQf9", - "isFolder": false, - "link_owner": "admin", - "name": "ITEMA_20448251-0.mp3", - "path": "/test/ITEMA_20448251-0.mp3", - "status": "valid", - "url": "http://myds.com:5000/fbsharing/pHTBKQf9" - }, - "success": true - } - ``` + """ + Get information of a sharing link by the sharing link ID. + + Parameters + ---------- + link_id : str + A unique ID of a sharing link. + + Returns + ------- + dict[str, object] + Information about the sharing link. + + Examples + -------- + ```json + { + "data": { + "date_available": "0", + "date_expired": "0", + "has_password": false, + "id": "pHTBKQf9", + "isFolder": false, + "link_owner": "admin", + "name": "ITEMA_20448251-0.mp3", + "path": "/test/ITEMA_20448251-0.mp3", + "status": "valid", + "url": "http://myds.com:5000/fbsharing/pHTBKQf9" + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Sharing' info = self.gen_list[api_name] @@ -1278,54 +1317,56 @@ def get_shared_link_info(self, link_id: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def get_shared_link_list(self, offset: Optional[int] = None, limit: Optional[int] = None, sort_by: Optional[str] = None, - sort_direction: Optional[str] = None, force_clean: Optional[bool] = None - ) -> dict[str, object]: - """List user's file sharing links - - Parameters - ---------- - offset : Optional[int], optional - Specify how many sharing links are skipped before beginning to return listed sharing links. Defaults to `None` - limit : Optional[int], optional - Number of sharing links requested. 0 means to list all sharing links. Defaults to `None` + sort_direction: Optional[str] = None, force_clean: Optional[bool] = None + ) -> dict[str, object]: + """ + List user's file sharing links. + + Parameters + ---------- + offset : Optional[int], optional + Specify how many sharing links are skipped before beginning to return listed sharing links. Defaults to `None` + limit : Optional[int], optional + Number of sharing links requested. 0 means to list all sharing links. Defaults to `None` + sort_by : Optional[str], optional Specify which file information to sort on. Defaults to `None` - All fields known are: `["name","isFolder","path","date_expired","date_available","status","has_password","id","url","link_owner"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `None` - All possible direction are: `["asc","desc"]` - force_clean : Optional[bool], optional - If set to false, the data will be retrieved from cache database rapidly. If set to true, all sharing information including sharing statuses and user name of sharing owner will be synchronized. It consumes some time. Defaults to `None` - - Returns - ------- - dict[str, object] - Information about the sharing links - - Example return - ---------- - ```json - { - "data": { - "links": [ - { - "date_available": "0", - "date_expired": "0", - "has_password": false, - "id": "pHTBKQf9", - "isFolder": false, - "link_owner": "admin", - "name": "ITEMA_20448251-0.mp3", - "path": "/test/ITEMA_20448251-0.mp3", - "status": "valid", - "url": "http://myds.com:5000/fbsharing/pHTBKQf9" - } - ], - "offset": 0, - "total": 1 - }, - "success": true - } - ``` + All fields known are: `["name","isFolder","path","date_expired","date_available","status","has_password","id","url","link_owner"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `None` + All possible direction are: `["asc","desc"]` + force_clean : Optional[bool], optional + If set to false, the data will be retrieved from cache database rapidly. If set to true, all sharing information including sharing statuses and user name of sharing owner will be synchronized. It consumes some time. Defaults to `None` + + Returns + ------- + dict[str, object] + Information about the sharing links. + + Examples + -------- + ```json + { + "data": { + "links": [ + { + "date_available": "0", + "date_expired": "0", + "has_password": false, + "id": "pHTBKQf9", + "isFolder": false, + "link_owner": "admin", + "name": "ITEMA_20448251-0.mp3", + "path": "/test/ITEMA_20448251-0.mp3", + "status": "valid", + "url": "http://myds.com:5000/fbsharing/pHTBKQf9" + } + ], + "offset": 0, + "total": 1 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Sharing' info = self.gen_list[api_name] @@ -1342,49 +1383,50 @@ def get_shared_link_list(self, offset: Optional[int] = None, limit: Optional[int return self.request_data(api_name, api_path, req_param) def create_sharing_link(self, path: str | list[str], password: Optional[str] = None, date_expired: Optional[str | int] = None, - date_available: Optional[str | int] = None - ) -> dict[str, object]: - """Generate one or more sharing link(s) by file/folder path(s). - - Parameters - ---------- - path : str | list[str] - One or more file/folder paths with which to generate sharing links. - password : Optional[str], optional - The password for the sharing link when accessing it. The max password length are 16 characters. Defaults to `None` - date_expired : Optional[str | int], optional - The expiration date for the sharing link, written in the format YYYYMM-DD. When set to 0 (default), the sharing link is permanent. Defaults to `None` - - Note: SHOULD put the double quote outside expiration date and is based on user's DS date. - - date_available : Optional[str | int], optional - The available date for the sharing link to become effective, written in the format YYYY-MM-DD. When set to 0 (default), the sharing link is valid immediately after creation. Defaults to `None` - - Note: SHOULD put the double quote outside available date and is based on user's DS date. - - Returns - ------- - dict[str, object] - Information about the sharing link(s) generated - - Example return - ---------- - ```json - { - "data": { - "links": [ - { - "error": 0, - "id": "y4LmvpaX", - "path": "/test/ITEMA_20445972-0.mp3", - "qrcode": "iVBORw0KGgoAAAANSUh...", - "url": "http://myds.com:5000/fbsharing/y4LmvpaX" - } - ] - }, - "success": true - } - ``` + date_available: Optional[str | int] = None + ) -> dict[str, object]: + """ + Generate one or more sharing link(s) by file/folder path(s). + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths with which to generate sharing links. + password : Optional[str], optional + The password for the sharing link when accessing it. The max password length are 16 characters. Defaults to `None` + date_expired : Optional[str | int], optional + The expiration date for the sharing link, written in the format YYYYMM-DD. When set to 0 (default), the sharing link is permanent. Defaults to `None` + + Note: SHOULD put the double quote outside expiration date and is based on user's DS date. + + date_available : Optional[str | int], optional + The available date for the sharing link to become effective, written in the format YYYY-MM-DD. When set to 0 (default), the sharing link is valid immediately after creation. Defaults to `None` + + Note: SHOULD put the double quote outside available date and is based on user's DS date. + + Returns + ------- + dict[str, object] + Information about the sharing link(s) generated. + + Examples + -------- + ```json + { + "data": { + "links": [ + { + "error": 0, + "id": "y4LmvpaX", + "path": "/test/ITEMA_20445972-0.mp3", + "qrcode": "iVBORw0KGgoAAAANSUh...", + "url": "http://myds.com:5000/fbsharing/y4LmvpaX" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Sharing' info = self.gen_list[api_name] @@ -1401,25 +1443,26 @@ def create_sharing_link(self, path: str | list[str], password: Optional[str] = N return self.request_data(api_name, api_path, req_param) def delete_shared_link(self, link_id: str | list[str]) -> dict[str, object]: - """Delete one or more sharing links. - - Parameters - ---------- - link_id : str | list[str] - Unique IDs of file sharing link(s) to be deleted - - Returns - ------- - dict[str, object] - Returns an empty success response if completed without error; otherwise returns error object array contains failed IDs - - Example return - ---------- - ```json - {, - "success": true - } - ``` + """ + Delete one or more sharing links. + + Parameters + ---------- + link_id : str | list[str] + Unique IDs of file sharing link(s) to be deleted + + Returns + ------- + dict[str, object] + Returns an empty success response if completed without error; otherwise returns error object array contains failed IDs. + + Examples + -------- + ```json + {, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Sharing' info = self.gen_list[api_name] @@ -1433,20 +1476,21 @@ def delete_shared_link(self, link_id: str | list[str]) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def clear_invalid_shared_link(self) -> dict[str, object]: - """Remove all expired and broken sharing links. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Remove all expired and broken sharing links. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Sharing' info = self.gen_list[api_name] @@ -1459,38 +1503,39 @@ def clear_invalid_shared_link(self) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def edit_shared_link(self, link_id: str | list[str], password: Optional[str] = None, date_expired: Optional[str | int] = None, - date_available: Optional[str | int] = None - ) -> dict[str, object]: - """Edit sharing link(s). - - Parameters - ---------- - link_id : str | list[str] - Unique ID(s) of sharing link(s) to edit. - password : Optional[str], optional - The password for the sharing link when accessing it. The max password length are 16 characters. Defaults to `None` - date_expired : Optional[str | int], optional - The expiration date for the sharing link, written in the format YYYYMM-DD. When set to 0 (default), the sharing link is permanent. Defaults to `None` - - Note: SHOULD put the double quote outside expiration date and is based on user's DS date. - - date_available : Optional[str | int], optional - The available date for the sharing link to become effective, written in the format YYYY-MM-DD. When set to 0 (default), the sharing link is valid immediately after creation. Defaults to `None` - - Note: SHOULD put the double quote outside available date and is based on user's DS date. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error - - Example return - ---------- - ```json - { - "success": true - } - ``` + date_available: Optional[str | int] = None + ) -> dict[str, object]: + """ + Edit sharing link(s). + + Parameters + ---------- + link_id : str | list[str] + Unique ID(s) of sharing link(s) to edit. + password : Optional[str], optional + The password for the sharing link when accessing it. The max password length are 16 characters. Defaults to `None` + date_expired : Optional[str | int], optional + The expiration date for the sharing link, written in the format YYYYMM-DD. When set to 0 (default), the sharing link is permanent. Defaults to `None` + + Note: SHOULD put the double quote outside expiration date and is based on user's DS date. + + date_available : Optional[str | int], optional + The available date for the sharing link to become effective, written in the format YYYY-MM-DD. When set to 0 (default), the sharing link is valid immediately after creation. Defaults to `None` + + Note: SHOULD put the double quote outside available date and is based on user's DS date. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Sharing' info = self.gen_list[api_name] @@ -1505,54 +1550,55 @@ def edit_shared_link(self, link_id: str | list[str], password: Optional[str] = N } return self.request_data(api_name, api_path, req_param) - def create_folder(self, folder_path: str | list[str], name: str | list[str], - force_parent: Optional[bool] = False, additional: Optional[str | list[str]] = None - ) -> dict[str, object]: - """Create folders. - - Parameters - ---------- - folder_path : str | list[str] - One or more shared folder paths, separated by commas and around brackets. - If `force_parent` is `true`, and `folder_path` does not exist, the `folder_path` will be created. - If `force_parent` is `false`, `folder_path` must exist or a false value will be returned. - The number of paths must be the same as the number of names in the name parameter. - The first `folder_path` parameter corresponds to the first name parameter. - name : str | list[str] - One or more new folder names. - The number of names must be the same as the number of folder_paths paths in the `folder_path` parameter. - The first `name` parameter corresponding to the first `folder_path` parameter. - force_parent : Optional[bool], optional - Defaults to `False`. - If `true` : no error occurs if a folder exists and create parent folders as needed. - If `false` : parent folders are not created. - additional : Optional[str | list[str]], optional - Additionnal field to retrieve from folder. Defaults to `None` - All fields known are: `["real_path","size","owner","time","perm","type"]`. - - Returns - ------- - dict[str, object] - List of folder(s) created informations. - - Example return - ---------- - ```json - { - "data": { - "folders": [ - { - "isdir": true, - "name": "test", - "path": "/video/test" - } - ] - }, - "success": true - } - ``` + def create_folder(self, folder_path: str | list[str], name: str | list[str], + force_parent: Optional[bool] = False, additional: Optional[str | list[str]] = None + ) -> dict[str, object]: """ - + Create folders. + + Parameters + ---------- + folder_path : str | list[str] + One or more shared folder paths, separated by commas and around brackets. + If `force_parent` is `true`, and `folder_path` does not exist, the `folder_path` will be created. + If `force_parent` is `false`, `folder_path` must exist or a false value will be returned. + The number of paths must be the same as the number of names in the name parameter. + The first `folder_path` parameter corresponds to the first name parameter. + name : str | list[str] + One or more new folder names. + The number of names must be the same as the number of folder_paths paths in the `folder_path` parameter. + The first `name` parameter corresponding to the first `folder_path` parameter. + force_parent : Optional[bool], optional + Defaults to `False`. + If `true` : no error occurs if a folder exists and create parent folders as needed. + If `false` : parent folders are not created. + additional : Optional[str | list[str]], optional + Additionnal field to retrieve from folder. Defaults to `None` + All fields known are: `["real_path","size","owner","time","perm","type"]`. + + Returns + ------- + dict[str, object] + List of folder(s) created informations. + + Examples + -------- + ```json + { + "data": { + "folders": [ + { + "isdir": true, + "name": "test", + "path": "/video/test" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.CreateFolder' info = self.gen_list[api_name] api_path = info['path'] @@ -1566,48 +1612,49 @@ def create_folder(self, folder_path: str | list[str], name: str | list[str], return self.request_data(api_name, api_path, req_param) def rename_folder(self, path: str | list[str], name: str | list[str], additional: Optional[str | list[str]] = None, search_taskid: Optional[str] = None) -> dict[str, object]: - """Rename folders. - - Parameters - ---------- - path : str | list[str] - One or more paths of files/folders to be renamed. - The number of paths must be the same as the number of names in the `name` parameter. - The first `path` parameter corresponds to the first `name` parameter. - name : str | list[str] - One or more new folder names. - The number of names must be the same as the number of paths paths in the `path` parameter. - The first `name` parameter corresponding to the first `path` parameter. - additional : Optional[str | list[str]], optional - Defaults to `None` - Additionnal field to retrieve from folder. - All fields known are: `["real_path","size","owner","time","perm","type"]`. - search_taskid : Optional[str], optional - The task ID of the `search_start` method. Defaults to `None` - - Returns - ------- - dict[str, object] - List of folder(s) renamed informations. - - Example return - ---------- - ```json - { - "data": { - "files": [ - { - "isdir": true, - "name": "test", - "path": "/video/test" - } - ] - }, - "success": true - } - ``` """ - + Rename folders. + + Parameters + ---------- + path : str | list[str] + One or more paths of files/folders to be renamed. + The number of paths must be the same as the number of names in the `name` parameter. + The first `path` parameter corresponds to the first `name` parameter. + name : str | list[str] + One or more new folder names. + The number of names must be the same as the number of paths paths in the `path` parameter. + The first `name` parameter corresponding to the first `path` parameter. + additional : Optional[str | list[str]], optional + Defaults to `None` + Additionnal field to retrieve from folder. + All fields known are: `["real_path","size","owner","time","perm","type"]`. + search_taskid : Optional[str], optional + The task ID of the `search_start` method. Defaults to `None` + + Returns + ------- + dict[str, object] + List of folder(s) renamed informations. + + Examples + -------- + ```json + { + "data": { + "files": [ + { + "isdir": true, + "name": "test", + "path": "/video/test" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.Rename' info = self.gen_list[api_name] api_path = info['path'] @@ -1621,55 +1668,56 @@ def rename_folder(self, path: str | list[str], name: str | list[str], additional return self.request_data(api_name, api_path, req_param) def start_copy_move(self, - path: str | list[str], - dest_folder_path: str, - overwrite: Optional[bool] = None, - remove_src: Optional[bool] = False, - accurate_progress: Optional[bool] = True, - search_taskid: Optional[str] = None - ) -> dict[str, object]: - """Start to copy/move files. - - Parameters - ---------- - path : str | list[str] - One or more file/folder paths starting with a shared folder to copy/move. - dest_folder_path : str - A destination folder path where files/folders are copied/moved. - overwrite : Optional[bool], optional - Defaults to `None`. - If `true` : overwrite all existing files with the same name. - If `false` : skip all existing files with the same name. - - Note: do not overwrite or skip existed files. If there is any existing files, an error occurs (error code: 1003). - - remove_src : Optional[bool], optional - Defaults to `False`. - If `true`: move files/folders. If `false`: copy files/folders. - accurate_progress : Optional[bool], optional - Defaults to `True`. - If `true` : calculate the progress by each moved/copied file within sub-folder. - If `false` : calculate the progress by files which you give in path parameters. This calculates the progress faster, but is less precise. - search_taskid : Optional[str], optional - The task ID of the `search_start` method. Defaults to `None`. - - Returns - ------- - dict[str, object] - Return unique task ID for the copy/move task. - - Example return - ---------- - ```json - { - "data": { - "taskid": "FileStation_51D00B7912CDE0B0" - }, - "success": true - } - ``` + path: str | list[str], + dest_folder_path: str, + overwrite: Optional[bool] = None, + remove_src: Optional[bool] = False, + accurate_progress: Optional[bool] = True, + search_taskid: Optional[str] = None + ) -> dict[str, object]: """ - + Start to copy/move files. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to copy/move. + dest_folder_path : str + A destination folder path where files/folders are copied/moved. + overwrite : Optional[bool], optional + Defaults to `None`. + If `true` : overwrite all existing files with the same name. + If `false` : skip all existing files with the same name. + + Note: do not overwrite or skip existed files. If there is any existing files, an error occurs (error code: 1003). + + remove_src : Optional[bool], optional + Defaults to `False`. + If `true`: move files/folders. If `false`: copy files/folders. + accurate_progress : Optional[bool], optional + Defaults to `True`. + If `true` : calculate the progress by each moved/copied file within sub-folder. + If `false` : calculate the progress by files which you give in path parameters. This calculates the progress faster, but is less precise. + search_taskid : Optional[str], optional + The task ID of the `search_start` method. Defaults to `None`. + + Returns + ------- + dict[str, object] + Return unique task ID for the copy/move task. + + Examples + -------- + ```json + { + "data": { + "taskid": "FileStation_51D00B7912CDE0B0" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.FileStation.CopyMove' info = self.gen_list[api_name] api_path = info['path'] @@ -1687,33 +1735,34 @@ def start_copy_move(self, return self.request_data(api_name, api_path, req_param) def get_copy_move_status(self, taskid: str) -> dict[str, object]: - """ Get the copying/moving status. - - Parameters - ---------- - taskid : str - A unique ID for the copy/move task which is obtained from `start_copy_move` method - - Returns - ------- - dict[str, object] - Infos about the copy/move task - - Example return - ---------- - ```json - { - "data": { - "dest_folder_path": "/video/test", - "finished": false, - "path": "/video/test.avi", - "processed_size": 1057, - "progress": 0.01812258921563625, - "total": 58325 - }, - "success": true - } - ``` + """ + Get the copying/moving status. + + Parameters + ---------- + taskid : str + A unique ID for the copy/move task which is obtained from `start_copy_move` method + + Returns + ------- + dict[str, object] + Infos about the copy/move task. + + Examples + -------- + ```json + { + "data": { + "dest_folder_path": "/video/test", + "finished": false, + "path": "/video/test.avi", + "processed_size": 1057, + "progress": 0.01812258921563625, + "total": 58325 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.CopyMove' info = self.gen_list[api_name] @@ -1726,25 +1775,26 @@ def get_copy_move_status(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def stop_copy_move_task(self, taskid: str) -> dict[str, object]: - """ Stop a copy/move task - - Parameters - ---------- - taskid : str - A unique ID for the copy/move task which is obtained from `start_copy_move` method - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Stop a copy/move task. + + Parameters + ---------- + taskid : str + A unique ID for the copy/move task which is obtained from `start_copy_move` method + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.CopyMove' info = self.gen_list[api_name] @@ -1757,44 +1807,45 @@ def stop_copy_move_task(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def start_delete_task(self, - path: str | list[str], - accurate_progress: Optional[bool] = True, - recursive: Optional[bool] = True, - search_taskid: Optional[str] = None - ) -> dict[str, object]: - """ Delete file(s)/folder(s). This is a non-blocking method. You should poll a request with `get_delete_status` method to get the task status or stop the task with `stop_delete_task` method. - - Parameters - ---------- - path : str | list[str] - One or more file/folder paths starting with a shared folder to delete. - accurate_progress : Optional[bool], optional - Defaults to `True` - If `true` : calculates the progress of each deleted file with the sub-folder recursively. - If `false` : calculates the progress of files which you give in `path` parameters. The latter is faster than recursively, but less precise. - Note: Only non-blocking methods suits using the `get_delete_status` method to get progress. - recursive : Optional[bool], optional - Defaults to `True`. - If `true` : delete files/folders recursively. - If `false` : Only delete first-level file/folder. If a deleted folder contains any file, an error occurs because the folder can't be directly deleted. - search_taskid : Optional[str], optional - A unique ID for the search task which is obtained from `search_start` method. It's used to delete the file in the search result. Defaults to `None` - - Returns - ------- - dict[str, object] - A unique task ID for the delete task. - - Example return - ---------- - ```json - { - "data": { - "taskid": "FileStation_51CEC9C979340E5A" - }, - "success": true - } - ``` + path: str | list[str], + accurate_progress: Optional[bool] = True, + recursive: Optional[bool] = True, + search_taskid: Optional[str] = None + ) -> dict[str, object]: + """ + Delete file(s)/folder(s). This is a non-blocking method. You should poll a request with `get_delete_status` method to get the task status or stop the task with `stop_delete_task` method. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to delete. + accurate_progress : Optional[bool], optional + Defaults to `True` + If `true` : calculates the progress of each deleted file with the sub-folder recursively. + If `false` : calculates the progress of files which you give in `path` parameters. The latter is faster than recursively, but less precise. + Note: Only non-blocking methods suits using the `get_delete_status` method to get progress. + recursive : Optional[bool], optional + Defaults to `True`. + If `true` : delete files/folders recursively. + If `false` : Only delete first-level file/folder. If a deleted folder contains any file, an error occurs because the folder can't be directly deleted. + search_taskid : Optional[str], optional + A unique ID for the search task which is obtained from `search_start` method. It's used to delete the file in the search result. Defaults to `None` + + Returns + ------- + dict[str, object] + A unique task ID for the delete task. + + Examples + -------- + ```json + { + "data": { + "taskid": "FileStation_51CEC9C979340E5A" + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Delete' info = self.gen_list[api_name] @@ -1810,33 +1861,34 @@ def start_delete_task(self, return self.request_data(api_name, api_path, req_param) def get_delete_status(self, taskid: str) -> dict[str, object]: - """ Get the deleting status. - - Parameters - ---------- - taskid : str - A unique ID for the delete task which is obtained from `start_delete_task` method. - - Returns - ------- - dict[str, object] - Infos about the delete task. - - Example return - ---------- - ```json - { - "data": { - "finished": false, - "path": "/video/1000", - "processed_num": 193, - "processing_path": "/video/1000/509", - "progress": 0.03199071809649467, - "total": 6033 - }, - "success": true - } - ``` + """ + Get the deleting status. + + Parameters + ---------- + taskid : str + A unique ID for the delete task which is obtained from `start_delete_task` method. + + Returns + ------- + dict[str, object] + Infos about the delete task. + + Examples + -------- + ```json + { + "data": { + "finished": false, + "path": "/video/1000", + "processed_num": 193, + "processing_path": "/video/1000/509", + "progress": 0.03199071809649467, + "total": 6033 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Delete' info = self.gen_list[api_name] @@ -1849,25 +1901,26 @@ def get_delete_status(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def stop_delete_task(self, taskid: str) -> dict[str, object]: - """Stop a delete task. - - Parameters - ---------- - taskid : str - A unique ID for the delete task which is obtained from `start_delete_task` method. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Stop a delete task. + + Parameters + ---------- + taskid : str + A unique ID for the delete task which is obtained from `start_delete_task` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Delete' info = self.gen_list[api_name] @@ -1880,31 +1933,32 @@ def stop_delete_task(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def delete_delete_task(self, path: str | list[str], recursive: Optional[bool] = True, search_taskid: Optional[str] = None) -> dict[str, object]: - """ Delete files/folders. This is a blocking method. The response is not returned until the deletion operation is completed. - - Parameters - ---------- - path : str | list[str] - One or more file/folder paths starting with a shared folder to delete. - recursive : Optional[bool], optional - Defaults to `True`. - If `true` : Recursively delete files within a folder. - If `false` : Only delete first-level file/folder. If a deleted folder contains any file, an error occurs because the folder can't be directly deleted. - search_taskid : Optional[str], optional - A unique ID for the search task which is obtained from `search_start` method. It's used to delete the file in the search result. Defaults to `None` - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Delete files/folders. This is a blocking method. The response is not returned until the deletion operation is completed. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to delete. + recursive : Optional[bool], optional + Defaults to `True`. + If `true` : Recursively delete files within a folder. + If `false` : Only delete first-level file/folder. If a deleted folder contains any file, an error occurs because the folder can't be directly deleted. + search_taskid : Optional[str], optional + A unique ID for the search task which is obtained from `search_start` method. It's used to delete the file in the search result. Defaults to `None` + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Delete' info = self.gen_list[api_name] @@ -1918,47 +1972,48 @@ def delete_delete_task(self, path: str | list[str], recursive: Optional[bool] = } return self.request_data(api_name, api_path, req_param) - def start_extract_task(self, file_path: str, dest_folder_path: str, overwrite: Optional[bool] = False, - keep_dir: Optional[bool] = True, create_subfolder: Optional[bool] = False, codepage: Optional[str] = None, - password: Optional[str] = None, item_id: Optional[str | list[str]] = None - ) -> dict[str, object]: - """Start to extract an archive. This is a non-blocking method. You should poll a request with `get_extract_status` method to get the task status or stop the task with `stop_extract_task` method. - - Parameters - ---------- - file_path : str - A file path of an archive to be extracted, starting with a shared folder - dest_folder_path : str - A destination folder path starting with a shared folder to which the archive will be extracted. - overwrite : Optional[bool], optional - Whether or not to overwrite if the extracted file exists in the destination folder. Defaults to `False` - keep_dir : Optional[bool], optional - Whether to keep the folder structure within an archive. Defaults to `True` - create_subfolder : Optional[bool], optional - Whether to create a subfolder with an archive name which archived files are extracted to. Defaults to `False` - codepage : Optional[str], optional - The language codepage used for decoding file name with an archive. Defaults to `None` - All fields known are: `["enu","cht","chs","krn","ger","fre","ita","spn","jpn","dan","nor","sve","nld","rus","plk","ptb","ptg","hun","trk","csy"]` - password : Optional[str], optional - The password for extracting the file. Defaults to `None` - item_id : Optional[str | list[str]], optional - Item IDs of archived files used for extracting files within an archive. Item IDs could be listed by requesting the `get_file_list_of_archive` method. Defaults to `None` - - Returns - ------- - dict[str, object] - Unique task ID for the extract task. - - Example return - ---------- - ```json - { - "data": { - "taskid": "FileStation_51CBB59C68EFE6A3" - }, - "success": true - } - ``` + def start_extract_task(self, file_path: str, dest_folder_path: str, overwrite: Optional[bool] = False, + keep_dir: Optional[bool] = True, create_subfolder: Optional[bool] = False, codepage: Optional[str] = None, + password: Optional[str] = None, item_id: Optional[str | list[str]] = None + ) -> dict[str, object]: + """ + Start to extract an archive. This is a non-blocking method. You should poll a request with `get_extract_status` method to get the task status or stop the task with `stop_extract_task` method. + + Parameters + ---------- + file_path : str + A file path of an archive to be extracted, starting with a shared folder + dest_folder_path : str + A destination folder path starting with a shared folder to which the archive will be extracted. + overwrite : Optional[bool], optional + Whether or not to overwrite if the extracted file exists in the destination folder. Defaults to `False` + keep_dir : Optional[bool], optional + Whether to keep the folder structure within an archive. Defaults to `True` + create_subfolder : Optional[bool], optional + Whether to create a subfolder with an archive name which archived files are extracted to. Defaults to `False` + codepage : Optional[str], optional + The language codepage used for decoding file name with an archive. Defaults to `None` + All fields known are: `["enu","cht","chs","krn","ger","fre","ita","spn","jpn","dan","nor","sve","nld","rus","plk","ptb","ptg","hun","trk","csy"]` + password : Optional[str], optional + The password for extracting the file. Defaults to `None` + item_id : Optional[str | list[str]], optional + Item IDs of archived files used for extracting files within an archive. Item IDs could be listed by requesting the `get_file_list_of_archive` method. Defaults to `None` + + Returns + ------- + dict[str, object] + Unique task ID for the extract task. + + Examples + -------- + ```json + { + "data": { + "taskid": "FileStation_51CBB59C68EFE6A3" + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Extract' info = self.gen_list[api_name] @@ -1978,30 +2033,31 @@ def start_extract_task(self, file_path: str, dest_folder_path: str, overwrite: O return self.request_data(api_name, api_path, req_param)['data']['taskid'] def get_extract_status(self, taskid: str) -> dict[str, object]: - """Get the extract task status - - Parameters - ---------- - taskid : str - A unique ID for the extract task which is obtained from `start_extract_task` method - - Returns - ------- - dict[str, object] - Information about the extract task - - Example return - ---------- - ```json - { - "data": { - "dest_folder_path": "/download/download", - "finished": false, - "progress": 0.1 - }, - "success": true - } - ``` + """ + Get the extract task status. + + Parameters + ---------- + taskid : str + A unique ID for the extract task which is obtained from `start_extract_task` method + + Returns + ------- + dict[str, object] + Information about the extract task. + + Examples + -------- + ```json + { + "data": { + "dest_folder_path": "/download/download", + "finished": false, + "progress": 0.1 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Extract' info = self.gen_list[api_name] @@ -2014,25 +2070,26 @@ def get_extract_status(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def stop_extract_task(self, taskid: str) -> dict[str, object]: - """Stop the extract task - - Parameters - ---------- - taskid : str - A unique ID for the extract task which is obtained from `start_extract_task` method - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Stop the extract task. + + Parameters + ---------- + taskid : str + A unique ID for the extract task which is obtained from `start_extract_task` method + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Extract' info = self.gen_list[api_name] @@ -2044,69 +2101,70 @@ def stop_extract_task(self, taskid: str) -> dict[str, object]: } return self.request_data(api_name, api_path, req_param) - def get_file_list_of_archive(self, file_path: str, offset: Optional[int] = 0, limit: Optional[int] = -1, - sort_by: Optional[str] = 'name', sort_direction: Optional[str] = 'asc', codepage: Optional[str] = None, - password: Optional[str] = None, item_id: Optional[str] = None - ) -> dict[str, object]: - """ List archived files contained in an archive - - Parameters - ---------- - file_path : str - An archive file path starting with a shared folder to list. - offset : Optional[int], optional - Specify how many archived files are skipped before beginning to return listed archived files in an archive. Defaults to `0`. - limit : Optional[int], optional - Number of archived files requested. -1 indicates in an archive to list all archived files. Defaults to `-1`. - sort_by : Optional[str], optional - Specify which archived file information to sort on. Defaults to `'name'` - All fields known are: `["name","size","pack_size","mtime"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `'asc'` - All possible direction are: `["asc","desc"]`. - codepage : Optional[str], optional - The language codepage used for decoding file name with an archive. Defaults to `None` - All fields known are: `["enu","cht","chs","krn","ger","fre","ita","spn","jpn","dan","nor","sve","nld","rus","plk","ptb","ptg","hun","trk","csy"]` - password : Optional[str], optional - The password for extracting the file.. Defaults to `None` - item_id : Optional[str], optional - Item ID of an archived folder to be listed within an archive. (None) or -1 will list archive files in a root folder within an archive. Defaults to `None` - - Returns - ------- - dict[str, object] - Information about the archived files - - Example return - ---------- - ```json - { - "data": { - "items": [ - { - "is_dir": false, - "item_id": 1, - "mtime": "2013-02-03 00:17:12", - "name": "ITEMA_20445972-0.mp3", - "pack_size": 51298633, - "path": "ITEMA_20445972-0.mp3", - "size": 51726464 - }, - { - "is_dir": false, - "item_id": 0, - "mtime": "2013-03-03 00:18:12", - "name": "ITEMA_20455319-0.mp3", - "pack_size": 51434239, - "path": "ITEMA_20455319-0.mp3", - "size": 51896448 - } - ], - "total":2 - }, - "success": true - } - ``` + def get_file_list_of_archive(self, file_path: str, offset: Optional[int] = 0, limit: Optional[int] = -1, + sort_by: Optional[str] = 'name', sort_direction: Optional[str] = 'asc', codepage: Optional[str] = None, + password: Optional[str] = None, item_id: Optional[str] = None + ) -> dict[str, object]: + """ + List archived files contained in an archive. + + Parameters + ---------- + file_path : str + An archive file path starting with a shared folder to list. + offset : Optional[int], optional + Specify how many archived files are skipped before beginning to return listed archived files in an archive. Defaults to `0`. + limit : Optional[int], optional + Number of archived files requested. -1 indicates in an archive to list all archived files. Defaults to `-1`. + sort_by : Optional[str], optional + Specify which archived file information to sort on. Defaults to `'name'` + All fields known are: `["name","size","pack_size","mtime"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `'asc'` + All possible direction are: `["asc","desc"]`. + codepage : Optional[str], optional + The language codepage used for decoding file name with an archive. Defaults to `None` + All fields known are: `["enu","cht","chs","krn","ger","fre","ita","spn","jpn","dan","nor","sve","nld","rus","plk","ptb","ptg","hun","trk","csy"]` + password : Optional[str], optional + The password for extracting the file.. Defaults to `None` + item_id : Optional[str], optional + Item ID of an archived folder to be listed within an archive. (None) or -1 will list archive files in a root folder within an archive. Defaults to `None` + + Returns + ------- + dict[str, object] + Information about the archived files. + + Examples + -------- + ```json + { + "data": { + "items": [ + { + "is_dir": false, + "item_id": 1, + "mtime": "2013-02-03 00:17:12", + "name": "ITEMA_20445972-0.mp3", + "pack_size": 51298633, + "path": "ITEMA_20445972-0.mp3", + "size": 51726464 + }, + { + "is_dir": false, + "item_id": 0, + "mtime": "2013-03-03 00:18:12", + "name": "ITEMA_20455319-0.mp3", + "pack_size": 51434239, + "path": "ITEMA_20455319-0.mp3", + "size": 51896448 + } + ], + "total":2 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Extract' info = self.gen_list[api_name] @@ -2125,51 +2183,52 @@ def get_file_list_of_archive(self, file_path: str, offset: Optional[int] = 0, li } return self.request_data(api_name, api_path, req_param) - def start_file_compression(self, path: str | list[str], dest_file_path: str, level: Optional[int] = 'moderate', - mode: Optional[str] = 'add', format: Optional[str] = 'zip', password: Optional[str] = None - ) -> dict[str, object] | tuple[str]: - """Start to compress file(s)/folder(s). - - Parameters - ---------- - path : str | list[str] - One or more file paths to be compressed, starting with a shared folder. - dest_file_path : str - A destination file path (including file name) of an archive for the compressed archive. - level : Optional[int], optional - Defaults to `'moderate'`. - Compress level used, could be one of following values: - - `moderate`: moderate compression and normal compression speed. - - `store`: pack files with no compress. fastest: fastest compression speed but less compression. - - `best`: slowest compression speed but optimal compression. - mode : Optional[str], optional - Defaults to `'add'` - Compress mode used, could be one of following values: - - `add`: Update existing items and add new files. If an archive does not exist, a new one is created. - - `update`: Update existing items if newer on the file system and add new files. If the archive does not exist create a new archive. - - `refreshen`: Update existing items of an archive if newer on the file system. Does not add new files to the archive. - - `synchronize`: Update older files in the archive and add files that are not already in the archive. - format : Optional[str], optional - The compress format, ZIP or 7z format. Defaults to `'zip'` - All fields known are: `["zip","7z"]` - password : Optional[str], optional - The password for the archive. Defaults to `None` - - Returns - ------- - dict[str, object] | tuple[str] - Unique task ID for the compress task. - - Example return - ---------- - ```json - { - "data": { - "taskid": "FileStation_51CBB25CC31961FD" - }, - "success": true - } - ``` + def start_file_compression(self, path: str | list[str], dest_file_path: str, level: Optional[int] = 'moderate', + mode: Optional[str] = 'add', format: Optional[str] = 'zip', password: Optional[str] = None + ) -> dict[str, object] | tuple[str]: + """ + Start to compress file(s)/folder(s). + + Parameters + ---------- + path : str | list[str] + One or more file paths to be compressed, starting with a shared folder. + dest_file_path : str + A destination file path (including file name) of an archive for the compressed archive. + level : Optional[int], optional + Defaults to `'moderate'`. + Compress level used, could be one of following values: + - `moderate`: moderate compression and normal compression speed. + - `store`: pack files with no compress. fastest: fastest compression speed but less compression. + - `best`: slowest compression speed but optimal compression. + mode : Optional[str], optional + Defaults to `'add'` + Compress mode used, could be one of following values: + - `add`: Update existing items and add new files. If an archive does not exist, a new one is created. + - `update`: Update existing items if newer on the file system and add new files. If the archive does not exist create a new archive. + - `refreshen`: Update existing items of an archive if newer on the file system. Does not add new files to the archive. + - `synchronize`: Update older files in the archive and add files that are not already in the archive. + format : Optional[str], optional + The compress format, ZIP or 7z format. Defaults to `'zip'` + All fields known are: `["zip","7z"]` + password : Optional[str], optional + The password for the archive. Defaults to `None` + + Returns + ------- + dict[str, object] | tuple[str] + Unique task ID for the compress task. + + Examples + -------- + ```json + { + "data": { + "taskid": "FileStation_51CBB25CC31961FD" + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Compress' info = self.gen_list[api_name] @@ -2187,29 +2246,30 @@ def start_file_compression(self, path: str | list[str], dest_file_path: str, lev return self.request_data(api_name, api_path, req_param) def get_compress_status(self, taskid: str) -> dict[str, object]: - """ Get the compress task status - - Parameters - ---------- - taskid : str - A unique ID for the compress task. This is obtained from `start_file_compression` method. - - Returns - ------- - dict[str, object] - Information about the compress task - - Example return - ---------- - ```json - { - "data": { - "dest_file_path": "/download/download.zip", - "finished": true - }, - "success": true - } - ``` + """ + Get the compress task status. + + Parameters + ---------- + taskid : str + A unique ID for the compress task. This is obtained from `start_file_compression` method. + + Returns + ------- + dict[str, object] + Information about the compress task. + + Examples + -------- + ```json + { + "data": { + "dest_file_path": "/download/download.zip", + "finished": true + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Compress' info = self.gen_list[api_name] @@ -2222,25 +2282,26 @@ def get_compress_status(self, taskid: str) -> dict[str, object]: return self.request_data(api_name, api_path, req_param) def stop_compress_task(self, taskid: str) -> dict[str, object]: - """Stop the compress task. - - Parameters - ---------- - taskid : str - A unique ID for the compress task. This is obtained from `start_file_compression` method. - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Stop the compress task. + + Parameters + ---------- + taskid : str + A unique ID for the compress task. This is obtained from `start_file_compression` method. + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.Compress' info = self.gen_list[api_name] @@ -2252,125 +2313,126 @@ def stop_compress_task(self, taskid: str) -> dict[str, object]: } return self.request_data(api_name, api_path, req_param) - def get_list_of_all_background_task(self, offset: Optional[int] = 0, limit: Optional[int] = 0, - sort_by: Optional[str] = 'crtime', sort_direction: Optional[str] = 'asc', api_filter: Optional[str | list[str]] = None - ) -> dict[str, object]: - """List all background tasks including copy, move, delete, compress and extract tasks. - - Parameters - ---------- - offset : Optional[int], optional - Specify how many background tasks are skipped before beginning to return listed background tasks. Defaults to `0` - limit : Optional[int], optional - Number of background tasks requested. 0 indicates to list all background tasks. Defaults to `0` - sort_by : Optional[str], optional - Specify which information of the background task to sort on. Defaults to `'crtime'` - All fields known are: `["crtime","finished"]` - sort_direction : Optional[str], optional - Specify to sort ascending or to sort descending. Defaults to `'asc'` - All possible direction are: `["asc","desc"]` - api_filter : Optional[str | list[str]], optional - List background tasks with one or more given API name(s). If not given, all background tasks are listed. Defaults to `None` - All fields known are: `["SYNO.FileStation.CopyMove","SYNO.FileStation.Delete","SYNO.FileStation.Compress","SYNO.FileStation.Extract"]` - - Returns - ------- - dict[str, object] - List of background tasks - - Example return - ---------- - ```json - { - "data": { - "tasks": [ - { - "api": "SYNO.FileStation.CopyMove", - "crtime": 1372926088, - "finished": true, - "method": "start", - "params": { - "accurate_progress": true, - "dest_folder_path": "/video/test", - "overwrite": true, - "path": [ - "/video/test2/test.avi" - ], - "remove_src": false - }, - "path": "/video/test2/test.avi", - "processed_size": 12800, - "processing_path": "/video/test2/test.avi", - "progress": 1, - "taskid": "FileStation_51D53088860DD653", - "total": 12800, - "version": 1 - }, - { - "api": "SYNO.FileStation.Compress", - "crtime": 1372926097, - "finished": true, - "method": "start", - "params": { - "dest_file_path": "/video/test/test.zip", - "format": "zip", - "level": "", - "mode": "", - "password": "", - "path": [ - "/video/test/test.avi" - ] - }, - "progress": 0, - "taskid": "FileStation_51D53091A82CD948", - "total": -1, - "version": 1 - }, - { - "api": "SYNO.FileStation.Extract", - "crtime": 1372926103, - "finished": true, - "method": "start", - "params": { - "create_subfolder": false, - "dest_folder_path": "/video/test", - "file_path": [ - "/video/test/test.zip" - ], - "keep_dir": true, - "overwrite": false - }, - "progress": 1, - "taskid": "FileStation_51D530978633C014", - "total": -1, - "version": 1 - }, - { - "api": "SYNO.FileStation.Delete", - "crtime": 1372926110, - "finished": true, - "method": "start", - "params": { - "accurate_progress": true, - "path": [ - "/video/test/test.avi" - ] - }, - "path": "/video/test/test.avi", - "processed_num": 1, - "processing_path": "/video/test/test.avi", - "progress": 1, - "taskid": "FileStation_51D5309EE1E10BD9", - "total": 1, - "version": 1 - } - ], - "offset": 0, - "total": 4 - }, - "success": true - } - ``` + def get_list_of_all_background_task(self, offset: Optional[int] = 0, limit: Optional[int] = 0, + sort_by: Optional[str] = 'crtime', sort_direction: Optional[str] = 'asc', api_filter: Optional[str | list[str]] = None + ) -> dict[str, object]: + """ + List all background tasks including copy, move, delete, compress and extract tasks. + + Parameters + ---------- + offset : Optional[int], optional + Specify how many background tasks are skipped before beginning to return listed background tasks. Defaults to `0` + limit : Optional[int], optional + Number of background tasks requested. 0 indicates to list all background tasks. Defaults to `0` + sort_by : Optional[str], optional + Specify which information of the background task to sort on. Defaults to `'crtime'` + All fields known are: `["crtime","finished"]` + sort_direction : Optional[str], optional + Specify to sort ascending or to sort descending. Defaults to `'asc'` + All possible direction are: `["asc","desc"]` + api_filter : Optional[str | list[str]], optional + List background tasks with one or more given API name(s). If not given, all background tasks are listed. Defaults to `None` + All fields known are: `["SYNO.FileStation.CopyMove","SYNO.FileStation.Delete","SYNO.FileStation.Compress","SYNO.FileStation.Extract"]` + + Returns + ------- + dict[str, object] + List of background tasks. + + Examples + -------- + ```json + { + "data": { + "tasks": [ + { + "api": "SYNO.FileStation.CopyMove", + "crtime": 1372926088, + "finished": true, + "method": "start", + "params": { + "accurate_progress": true, + "dest_folder_path": "/video/test", + "overwrite": true, + "path": [ + "/video/test2/test.avi" + ], + "remove_src": false + }, + "path": "/video/test2/test.avi", + "processed_size": 12800, + "processing_path": "/video/test2/test.avi", + "progress": 1, + "taskid": "FileStation_51D53088860DD653", + "total": 12800, + "version": 1 + }, + { + "api": "SYNO.FileStation.Compress", + "crtime": 1372926097, + "finished": true, + "method": "start", + "params": { + "dest_file_path": "/video/test/test.zip", + "format": "zip", + "level": "", + "mode": "", + "password": "", + "path": [ + "/video/test/test.avi" + ] + }, + "progress": 0, + "taskid": "FileStation_51D53091A82CD948", + "total": -1, + "version": 1 + }, + { + "api": "SYNO.FileStation.Extract", + "crtime": 1372926103, + "finished": true, + "method": "start", + "params": { + "create_subfolder": false, + "dest_folder_path": "/video/test", + "file_path": [ + "/video/test/test.zip" + ], + "keep_dir": true, + "overwrite": false + }, + "progress": 1, + "taskid": "FileStation_51D530978633C014", + "total": -1, + "version": 1 + }, + { + "api": "SYNO.FileStation.Delete", + "crtime": 1372926110, + "finished": true, + "method": "start", + "params": { + "accurate_progress": true, + "path": [ + "/video/test/test.avi" + ] + }, + "path": "/video/test/test.avi", + "processed_num": 1, + "processing_path": "/video/test/test.avi", + "progress": 1, + "taskid": "FileStation_51D5309EE1E10BD9", + "total": 1, + "version": 1 + } + ], + "offset": 0, + "total": 4 + }, + "success": true + } + ``` """ api_name = 'SYNO.FileStation.BackgroundTask' info = self.gen_list[api_name] @@ -2385,27 +2447,28 @@ def get_list_of_all_background_task(self, offset: Optional[int] = 0, limit: Opti 'filter': json.dumps(api_filter) if isinstance(api_filter, list) else api_filter } return self.request_data(api_name, api_path, req_param) - + def clear_all_finished_background_task(self, taskid: Optional[str | list[str]] = None) -> dict[str, object]: - """Delete all finished background tasks. - - Parameters - ---------- - taskid : Optional[str | list[str]], optional - Unique IDs of finished copy, move, delete, compress or extract tasks. If it's not given, all finished tasks are deleted. Defaults to `None` - - Returns - ------- - dict[str, object] - No specific response. It returns an empty success response if completed without error. - - Example return - ---------- - ```json - { - "success": true - } - ``` + """ + Delete all finished background tasks. + + Parameters + ---------- + taskid : Optional[str | list[str]], optional + Unique IDs of finished copy, move, delete, compress or extract tasks. If it's not given, all finished tasks are deleted. Defaults to `None` + + Returns + ------- + dict[str, object] + No specific response. It returns an empty success response if completed without error. + + Examples + -------- + ```json + { + "success": true + } + ``` """ api_name = 'SYNO.FileStation.BackgroundTask' info = self.gen_list[api_name] @@ -2416,38 +2479,38 @@ def clear_all_finished_background_task(self, taskid: Optional[str | list[str]] = 'taskid': json.dumps(taskid) if isinstance(taskid, list) else taskid } return self.request_data(api_name, api_path, req_param) - + def get_file(self, path: str | list[str], mode: str, dest_path: str = ".", chunk_size: int = 8192, verify: bool = False) -> Optional[io.BytesIO]: - """Download a file - - Parameters - ---------- - path : str | list[str] - One or more file/folder paths starting with a shared folder to be downloaded. When more than one file is to be downloaded, files/folders will be compressed as a zip file. - mode : str - Mode used to download files/folders, value could be: - - `open`: print the file content to stdout - - `download`: write the file content to a file based on the `dest_path` parameter - - `serve`: return the file content as a stream - dest_path : str, optional - Destination folder where the file is downloaded, if mode is `download`. Defaults to `"."` - chunk_size : int, optional - Size of chunk to download. Defaults to `8192` - verify : bool, optional - If `True` use HTTPS else use HTTP. Defaults to `False` - - Returns - ------- - Optional[io.BytesIO] - If mode is `serve`, return the file content as a stream - + """ + Download a file. + + Parameters + ---------- + path : str | list[str] + One or more file/folder paths starting with a shared folder to be downloaded. When more than one file is to be downloaded, files/folders will be compressed as a zip file. + mode : str + Mode used to download files/folders, value could be: + - `open`: print the file content to stdout + - `download`: write the file content to a file based on the `dest_path` parameter + - `serve`: return the file content as a stream + dest_path : str, optional + Destination folder where the file is downloaded, if mode is `download`. Defaults to `"."` + chunk_size : int, optional + Size of chunk to download. Defaults to `8192` + verify : bool, optional + If `True` use HTTPS else use HTTP. Defaults to `False` + + Returns + ------- + Optional[io.BytesIO] + If mode is `serve`, return the file content as a stream. """ api_name = 'SYNO.FileStation.Download' info = self.gen_list[api_name] api_path = info['path'] session = requests.session() - str_path: str = json.dumps(path) if isinstance(path, list) else path + str_path: str = json.dumps(path) if isinstance(path, list) else path url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=download&path=%s&mode=%s&_sid=%s' % ( api_name, info['maxVersion'], str_path, mode, self._sid) @@ -2463,7 +2526,7 @@ def get_file(self, path: str | list[str], mode: str, dest_path: str = ".", chunk r.raise_for_status() if not os.path.isdir(dest_path): os.makedirs(dest_path) - + if isinstance(path, list): if len(path) > 1: file_name = f"{os.path.splitext(os.path.basename(path[0]))[0]}.zip" @@ -2480,17 +2543,17 @@ def get_file(self, path: str | list[str], mode: str, dest_path: str = ".", chunk with session.get(url, stream=True, verify=verify, headers={"X-SYNO-TOKEN": self.session._syno_token}) as r: r.raise_for_status() return io.BytesIO(r.content) - + def generate_file_tree(self, folder_path: str, tree: Tree) -> None: - """Generate the file tree based on the folder path you give, you need to create the root node before call this function - - Parameters - ---------- - folder_path : str - Folder path to generate file tree - tree : Tree - Instance of the Tree of lib "Treelib", this will be modified by the method - + """ + Generate the file tree based on the folder path you give, you need to create the root node before call this function. + + Parameters + ---------- + folder_path : str + Folder path to generate file tree + tree : Tree + Instance of the Tree of lib "Treelib", this will be modified by the method """ data: dict = self.get_file_list( folder_path=folder_path @@ -2502,9 +2565,8 @@ def generate_file_tree(self, folder_path: str, tree: Tree) -> None: file_name: str = file.get("name") file_path: str = file.get("path") if file.get("isdir"): - + tree.create_node(file_name, file_path, parent=folder_path) self.generate_file_tree(file_path, tree) else: tree.create_node(file_name, file_path, parent=folder_path) - diff --git a/synology_api/DSM/Package/PackageCenter.py b/synology_api/DSM/Package/PackageCenter.py index bae577a8..7db980b6 100644 --- a/synology_api/DSM/Package/PackageCenter.py +++ b/synology_api/DSM/Package/PackageCenter.py @@ -1,51 +1,63 @@ +""" +Core Package API implementation. + +Implementation of the PackageCenter application APIs. +""" + import json from typing import List from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor -import os, requests, tqdm, time +import os +import requests +import tqdm +import time from synology_api import base_api + class PackageCenter(base_api.BaseApi): """ - Core Package API implementation. Implementation of the PackageCenter application APIs + Core Package API implementation. + + Implementation of the PackageCenter application APIs. """ - + def get_package(self, package_id: str, additional: List[str] = []) -> dict: - """Get infos of a package - - Parameters - ---------- - package_id : str - Package ID - additional : List[str], optional - Additional field to retrieves. Defaults to `[]` - All filed known are: - `["status","dsm_apps"]` - - Returns - ------- - dict - Informations about the package - - Example return - ---------- - ```json - { - "data": { - "additional": { - "dsm_apps": " com.plexapp.plexmediaserver", - "status": "running", - "status_code": 0, - "status_description": "retrieve from status script", - "status_origin": "running" - }, - "id": "PlexMediaServer", - "name": "Plex Media Server", - "timestamp": 1739228562839, - "version": "1.41.3.9314-72009314" + """ + Get infos of a package. + + Parameters + ---------- + package_id : str + Package ID. + additional : list of str, optional + Additional fields to retrieve. Defaults to []. + All fields known are: ["status", "dsm_apps"]. + + Returns + ------- + dict + Information about the package. + + Examples + -------- + ```json + { + "data": { + "additional": { + "dsm_apps": " com.plexapp.plexmediaserver", + "status": "running", + "status_code": 0, + "status_description": "retrieve from status script", + "status_origin": "running" }, - "success": true - } - ``` + "id": "PlexMediaServer", + "name": "Plex Media Server", + "timestamp": 1739228562839, + "version": "1.41.3.9314-72009314" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package' info = self.core_list[api_name] @@ -57,47 +69,49 @@ def get_package(self, package_id: str, additional: List[str] = []) -> dict: "additional": json.dumps(additional) } return self.request_data(api_name, api_path, req_param) - + def list_installed(self, additional: list = [], ignore_hidden: bool = False) -> dict: - """List installed packages - Parameters - ---------- - additional : list[str], optional - Additional fields to retrieve. Defaults to `[]`. - All fields known are: - `["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url", - "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", - "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages","install_type", - "autoupdate", "silent_upgrade", "installing_progress", "ctl_uninstall", "updated_at", "status", - "url","available_operation"]`. - ignore_hidden : bool - TODO: Write description - - Returns - ------- - dict - List of packages installed on the NAS - - Example return - -------------- - ```json - { - "data": { - "packages": [ - { - "additional": { - "install_type": "" - }, - "id": "ActiveBackup-Office365", - "name": "Active Backup for Microsoft 365", - "timestamp": 1738880043640, - "version": "2.5.5-14034" - } - ] - }, - "success": true - } - ``` + """ + List installed packages. + + Parameters + ---------- + additional : list[str], optional + Additional fields to retrieve. Defaults to `[]`. + All fields known are: + `["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url", + "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", + "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages","install_type", + "autoupdate", "silent_upgrade", "installing_progress", "ctl_uninstall", "updated_at", "status", + "url","available_operation"]`. + ignore_hidden : bool + TODO: Write description + + Returns + ------- + dict + List of packages installed on the NAS. + + Examples + -------- + ```json + { + "data": { + "packages": [ + { + "additional": { + "install_type": "" + }, + "id": "ActiveBackup-Office365", + "name": "Active Backup for Microsoft 365", + "timestamp": 1738880043640, + "version": "2.5.5-14034" + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package' info = self.core_list[api_name] @@ -108,29 +122,31 @@ def list_installed(self, additional: list = [], ignore_hidden: bool = False) -> "ignore_hidden": ignore_hidden, "additional": json.dumps(additional) } - + return self.request_data(api_name, api_path, req_param) - + def list_installable(self) -> dict: - """List installable packages - Returns - ------- - dict - List of beta_package, categories and packages available - - Example return - -------------- - ```json - { - "data": { - "banners": [], - "beta_packages": [...], - "categories": [...], - "packages": [...] - }, - "success": true - } - ``` + """ + List installable packages. + + Returns + ------- + dict + List of beta_package, categories and packages available. + + Examples + -------- + ```json + { + "data": { + "banners": [], + "beta_packages": [...], + "categories": [...], + "packages": [...] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Server' info = self.core_list[api_name] @@ -141,55 +157,57 @@ def list_installable(self) -> dict: "blforcereload": False, "blloadothers": False } - + return self.request_data(api_name, api_path, req_param) - + def get_package_center_settings(self) -> dict: - """Get package center settings - Returns - ------- - dict - List settings of the Package center - - Example return - -------------- - ```json - { - "data": { - "autoupdateall": false, - "autoupdateimportant": true, - "default_vol": "/volume1", - "enable_autoupdate": true, - "enable_dsm": true, - "enable_email": false, - "mailset": true, - "trust_level": 0, - "update_channel": true, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 184.72 GB )", - "mount_point": "/volume1", - "size_free": "198336327680", - "size_total": "206158430208", - "vol_desc": "Apps", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.14 GB )", - "mount_point": "/volume2", - "size_free": "2567467421696", - "size_total": "3623234412544", - "vol_desc": "Stockage", - "volume_features": [] - } - ] - }, - "success": true - } - ``` + """ + Get package center settings. + + Returns + ------- + dict + List settings of the Package center. + + Examples + -------- + ```json + { + "data": { + "autoupdateall": false, + "autoupdateimportant": true, + "default_vol": "/volume1", + "enable_autoupdate": true, + "enable_dsm": true, + "enable_email": false, + "mailset": true, + "trust_level": 0, + "update_channel": true, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 184.72 GB )", + "mount_point": "/volume1", + "size_free": "198336327680", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.14 GB )", + "mount_point": "/volume2", + "size_free": "2567467421696", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ] + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting' info = self.core_list[api_name] @@ -198,58 +216,54 @@ def get_package_center_settings(self) -> dict: "method": "get", "version": info['maxVersion'], } - + return self.request_data(api_name, api_path, req_param) - - def set_package_center_settings(self, - enable_email: bool, enable_dsm: bool, enable_autoupdate: bool, - autoupdateall: bool, autoupdateimportant: bool, - default_vol: str, update_channel: str - ) -> dict: - """Set settings of the package center - Parameters - ---------- - enable_email : bool - Enable email notification - - enable_dsm : bool - Enable desktop notification - - enable_autoupdate: bool - Update packages automatically - - autoupdateall : bool - Auto update all packages - - autoupdateimportant : bool - Auto update "important" packages - - default_vol : str - Default volume for installation, all your volumes or `"no_default_vol" = Always ask me` - - udpate_channel : str - "stable" => Disable beta packages - "beta" => Enable beta packages - - Returns - ------- - dict - Return some settings - - Example return - -------------- - ```json - { - "data": { - "enable_dsm": true, - "enable_email": false, - "update_channel": "stable" - }, - "success": true - } - ``` + + def set_package_center_settings(self, + enable_email: bool, enable_dsm: bool, enable_autoupdate: bool, + autoupdateall: bool, autoupdateimportant: bool, + default_vol: str, update_channel: str + ) -> dict: """ - + Set settings of the package center. + + Parameters + ---------- + enable_email : bool + Enable email notification + enable_dsm : bool + Enable desktop notification + enable_autoupdate : bool + Update packages automatically + autoupdateall : bool + Auto update all packages + autoupdateimportant : bool + Auto update "important" packages + default_vol : str + Default volume for installation, all your volumes or `"no_default_vol" = Always ask me` + update_channel : str + "stable" => Disable beta packages + "beta" => Enable beta packages + + Returns + ------- + dict + Return some settings. + + Examples + -------- + ```json + { + "data": { + "enable_dsm": true, + "enable_email": false, + "update_channel": "stable" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Package.Setting' info = self.core_list[api_name] api_path = info['path'] @@ -264,49 +278,51 @@ def set_package_center_settings(self, "default_vol": default_vol, "update_channel": update_channel } - + return self.request_data(api_name, api_path, req_param) - + def get_package_center_infos(self) -> dict: - """Get package center informations - Returns - ------- - dict - List of configs - - Return example - -------------- - ```json - { - "data": { - "config": { - "auth_key": "------------------------------", - "blBetaChannel": false, - "blOtherServer": false, - "def_void": "", - "ds_build": "72806", - "ds_major": "7", - "ds_minor": "2", - "ds_timezone": "Amsterdam", - "ds_unique": "synology_r1000_723+", - "myPayBaseURL": "https://payment.synology.com", - "myds_id": "7886858", - "serial": "2260TPR7X30E6", - "success": true - }, - "prerelease": { - "agreed": true, - "success": true - }, - "term": { - "agreed_term_version": "0003", - "curr_term_version": "0003", - "success": true - } + """ + Get package center informations. + + Returns + ------- + dict + List of configs. + + Examples + -------- + ```json + { + "data": { + "config": { + "auth_key": "------------------------------", + "blBetaChannel": false, + "blOtherServer": false, + "def_void": "", + "ds_build": "72806", + "ds_major": "7", + "ds_minor": "2", + "ds_timezone": "Amsterdam", + "ds_unique": "synology_r1000_723+", + "myPayBaseURL": "https://payment.synology.com", + "myds_id": "7886858", + "serial": "2260TPR7X30E6", + "success": true }, - "success": true - } - ``` + "prerelease": { + "agreed": true, + "success": true + }, + "term": { + "agreed_term_version": "0003", + "curr_term_version": "0003", + "success": true + } + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Info' info = self.core_list[api_name] @@ -318,28 +334,29 @@ def get_package_center_infos(self) -> dict: return self.request_data(api_name, api_path, req_param) def feasibility_check_install(self, packages: List[str]) -> dict: - """Check if installation is possible - - Parameters - ---------- - packages : List[str] - List of package IDs to check for feasibility - - Returns - ------- - dict - _description_ - - Example return - ---------- - ```json - { - "data": { - "template": "data" - }, - "success": true - } - ``` + """ + Check if installation is possible. + + Parameters + ---------- + packages : List[str] + List of package IDs to check for feasibility + + Returns + ------- + dict + A dictionary containing the feasibility check results. + + Examples + -------- + ```json + { + "data": { + "template": "data" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting' info = self.core_list[api_name] @@ -350,39 +367,40 @@ def feasibility_check_install(self, packages: List[str]) -> dict: "type": "install_check", "packages": json.dumps(packages) } - + return self.request_data(api_name, api_path, req_param) - + def download_package(self, url: str, package_id: str, checksum: str, filesize: str) -> dict: - """Start download of the package, return a taskId for check status - - Parameters - ---------- - url : str - Url that can be retrieve from package info using `get_installable` function, in the `link` field - package_id : str - Package ID that can be retrieve from package info using `get_installable` function, in the `id` field - checksum : str - Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field - filesize : str - Filesize that can be retrieve from package info using `get_installable` function, in the `size` field - - Returns - ------- - dict - Retreive first progress of the download and the taskid used to check download status with `get_dowload_package_status` function - - Example return - ---------- - ```json - { - "data": { - "progress": 1.0000000000000001e-05, - "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer" - }, - "success": true - } - ``` + """ + Start download of the package, return a taskId for check status. + + Parameters + ---------- + url : str + Url that can be retrieve from package info using `get_installable` function, in the `link` field + package_id : str + Package ID that can be retrieve from package info using `get_installable` function, in the `id` field + checksum : str + Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field + filesize : str + Filesize that can be retrieve from package info using `get_installable` function, in the `size` field + + Returns + ------- + dict + Retreive first progress of the download and the taskid used to check download status with `get_dowload_package_status` function. + + Examples + -------- + ```json + { + "data": { + "progress": 1.0000000000000001e-05, + "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] @@ -399,42 +417,43 @@ def download_package(self, url: str, package_id: str, checksum: str, filesize: s "filesize": filesize } return self.request_data(api_name, api_path, req_param) - + def get_dowload_package_status(self, task_id: str) -> dict: - """Get current download status of the package - - Parameters - ---------- - task_id : str - task ID retrieve from response of `download_package` function - - Returns - ------- - dict - Retrieve informations about the download, important info is the `progress` field - - Example return - ---------- - ```json - { - "data": { - "beta": false, - "blqinst": false, - "finished": false, - "id": "DhcpServer", - "installing": false, - "name": "DhcpServer", - "pid": 27844, - "progress": 1.0000000000000001e-05, - "remote_link": "https://global.synologydownload.com/download/Package/spk/DhcpServer/1.0.2-0046/DhcpServer-x86_64-1.0.2-0046.spk", - "size": "1378697", - "success": true, - "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer", - "tmp_folder": "/volume1/@tmp/synopkg/download.esnnkb" - }, - "success": true - } - ``` + """ + Get current download status of the package. + + Parameters + ---------- + task_id : str + Task ID retrieve from response of `download_package` function + + Returns + ------- + dict + Retrieve informations about the download, important info is the `progress` field. + + Examples + -------- + ```json + { + "data": { + "beta": false, + "blqinst": false, + "finished": false, + "id": "DhcpServer", + "installing": false, + "name": "DhcpServer", + "pid": 27844, + "progress": 1.0000000000000001e-05, + "remote_link": "https://global.synologydownload.com/download/Package/spk/DhcpServer/1.0.2-0046/DhcpServer-x86_64-1.0.2-0046.spk", + "size": "1378697", + "success": true, + "taskid": "@SYNOPKG_DOWNLOAD_DhcpServer", + "tmp_folder": "/volume1/@tmp/synopkg/download.esnnkb" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] @@ -445,45 +464,46 @@ def get_dowload_package_status(self, task_id: str) -> dict: "task_id": task_id } return self.request_data(api_name, api_path, req_param) - + def check_installation_from_download(self, task_id: str) -> dict: - """Get info about downloaded package file, response field is used for `check_installation` and `install_package` function - - Parameters - ---------- - task_id : str - task ID retrieve from response of `download_package` function - - Returns - ------- - dict - Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function - - Example return - ---------- - ```json - { - "data": { - "description": "DHCP Server turns your DiskStation into a DHCP server within LAN to assign dynamic IP addresses and manage DHCP clients.", - "distributor": "", - "dsm_apps": "SYNO.SDS.DHCP.Instance", - "filename": "/volume1/@tmp/synopkg/download.esnnkb/@SYNOPKG_DOWNLOAD_DhcpServer", - "id": "DhcpServer", - "install_on_cold_storage": false, - "install_reboot": false, - "install_type": "system", - "maintainer": "Synology Inc.", - "name": "DHCP Server", - "startable": true, - "status": "non_installed", - "status_code": 255, - "status_description": "failed to locate given package", - "status_origin": "non_installed", - "version": "1.0.2-0046" - }, - "success": true - } - ``` + """ + Get info about downloaded package file, response field is used for `check_installation` and `install_package` function. + + Parameters + ---------- + task_id : str + Task ID retrieve from response of `download_package` function + + Returns + ------- + dict + Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function. + + Examples + -------- + ```json + { + "data": { + "description": "DHCP Server turns your DiskStation into a DHCP server within LAN to assign dynamic IP addresses and manage DHCP clients.", + "distributor": "", + "dsm_apps": "SYNO.SDS.DHCP.Instance", + "filename": "/volume1/@tmp/synopkg/download.esnnkb/@SYNOPKG_DOWNLOAD_DhcpServer", + "id": "DhcpServer", + "install_on_cold_storage": false, + "install_reboot": false, + "install_type": "system", + "maintainer": "Synology Inc.", + "name": "DHCP Server", + "startable": true, + "status": "non_installed", + "status_code": 255, + "status_description": "failed to locate given package", + "status_origin": "non_installed", + "version": "1.0.2-0046" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation.Download' info = self.core_list[api_name] @@ -494,65 +514,66 @@ def check_installation_from_download(self, task_id: str) -> dict: "taskid": task_id } return self.request_data(api_name, api_path, req_param) - + def upload_package_file(self, file_path: str, verify: bool = False, progress_bar: bool = True, additional: list = []) -> dict: - """Upload a file for install a package - - Parameters - ---------- - file_path : str - File path - verify : bool, optional - Use https. Defaults to `False` - progress_bar : bool, optional - Enable progress bar in the terminal. Defaults to `True` - additional : list, optional - Additional field to retrieves. Defaults to `[]` - All fields know are: - `["description","maintainer","distributor","startable","dsm_apps","status","install_reboot", - "install_type","install_on_cold_storage","break_pkgs","replace_pkgs"]`. - - Returns - ------- - dict - Informations about the uploaded file for installation - - Example return - ---------- - ```json - { - "data": { - "additional": { - "break_pkgs": null, - "description": "Plex organizes all of your personal media so you can easily access and enjoy it.", - "distributor": "", - "dsm_apps": " com.plexapp.plexmediaserver", - "install_on_cold_storage": false, - "install_reboot": false, - "install_type": "", - "maintainer": "Plex Inc", - "replace_pkgs": { "Plex Media Server": "" }, - "startable": true, - "status": "running", - "status_code": 0, - "status_description": "retrieve from status script", - "status_origin": "running" - }, - "codesign_error": 4532, - "id": "PlexMediaServer", - "name": "Plex Media Server", - "task_id": "@SYNOPKG_UPLOAD_17392283048566DD3", - "version": "1.41.3.9314-72009314" + """ + Upload a file for install a package. + + Parameters + ---------- + file_path : str + File path + verify : bool, optional + Use https. Defaults to `False` + progress_bar : bool, optional + Enable progress bar in the terminal. Defaults to `True` + additional : list, optional + Additional field to retrieves. Defaults to `[]` + All fields know are: + `["description","maintainer","distributor","startable","dsm_apps","status","install_reboot", + "install_type","install_on_cold_storage","break_pkgs","replace_pkgs"]`. + + Returns + ------- + dict + Informations about the uploaded file for installation. + + Examples + -------- + ```json + { + "data": { + "additional": { + "break_pkgs": null, + "description": "Plex organizes all of your personal media so you can easily access and enjoy it.", + "distributor": "", + "dsm_apps": " com.plexapp.plexmediaserver", + "install_on_cold_storage": false, + "install_reboot": false, + "install_type": "", + "maintainer": "Plex Inc", + "replace_pkgs": { "Plex Media Server": "" }, + "startable": true, + "status": "running", + "status_code": 0, + "status_description": "retrieve from status script", + "status_origin": "running" }, - "success": true - } - ``` + "codesign_error": 4532, + "id": "PlexMediaServer", + "name": "Plex Media Server", + "task_id": "@SYNOPKG_UPLOAD_17392283048566DD3", + "version": "1.41.3.9314-72009314" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] api_path = info['path'] filename = os.path.basename(file_path) - + session = requests.session() with open(file_path, 'rb') as payload: @@ -573,13 +594,15 @@ def upload_package_file(self, file_path: str, verify: bool = False, progress_bar unit_divisor=1024 ) - monitor = MultipartEncoderMonitor(encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) + monitor = MultipartEncoderMonitor( + encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) r = session.post( url, data=monitor, verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': monitor.content_type} + headers={"X-SYNO-TOKEN": self.session._syno_token, + 'Content-Type': monitor.content_type} ) else: @@ -587,7 +610,8 @@ def upload_package_file(self, file_path: str, verify: bool = False, progress_bar url, data=encoder, verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, 'Content-Type': encoder.content_type} + headers={"X-SYNO-TOKEN": self.session._syno_token, + 'Content-Type': encoder.content_type} ) session.close() @@ -595,25 +619,26 @@ def upload_package_file(self, file_path: str, verify: bool = False, progress_bar return r.status_code, r.json() return r.json() - + def get_default_install_volume(self) -> dict: - """Get default install volume for package - - Returns - ------- - dict - Return default volume, if default volume is set to `Always ask me` it return error 4501 - - Example return - ---------- - ```json - { - "data": { - "default_vol": "/volume1" - }, - "success": true - } - ``` + """ + Get default install volume for package. + + Returns + ------- + dict + Return default volume, if default volume is set to `Always ask me` it return error 4501. + + Examples + -------- + ```json + { + "data": { + "default_vol": "/volume1" + }, + "success": true + } + ``` """ api_name = 'SYNO.Core.Package.Setting.Volume' info = self.core_list[api_name] @@ -622,67 +647,68 @@ def get_default_install_volume(self) -> dict: "method": "get", "version": info['maxVersion'], } - + return self.request_data(api_name, api_path, req_param) - - def check_installation(self, - package_id: str, install_type: str = "", install_on_cold_storage: bool = False, - blCheckDep: bool = False, replacepkgs: dict = {} - ) -> dict: - """Check installation of the package on the default volume - - Parameters - ---------- - package_id : str - Id of the package to install - install_type : str, optionnal - Installation type, Defaults to `""`. TODO: Add description and possible types - install_on_cold_storage : bool, optional - Defaults to `False`. TODO: Add description - blCheckDep : bool, optional - Defaults to `False`. TODO: Add description - replacepkgs : dict, optional - Defaults to `{}`. TODO: Add description - - Returns - ------- - dict - List of usefull informations about volumes - - Example return - ---------- - ```json - { - "data": { - "is_occupied": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 184.52 GB )", - "mount_point": "/volume1", - "size_free": "198126022656", - "size_total": "206158430208", - "vol_desc": "vol1", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.16 GB )", - "mount_point": "/volume2", - "size_free": "2567484923904", - "size_total": "3623234412544", - "vol_desc": "vol2", - "volume_features": [] - } - ], - "volume_path": "/volume1" - }, - "success": true, - } - ``` + + def check_installation(self, + package_id: str, install_type: str = "", install_on_cold_storage: bool = False, + blCheckDep: bool = False, replacepkgs: dict = {} + ) -> dict: """ - + Check installation of the package on the default volume. + + Parameters + ---------- + package_id : str + Id of the package to install + install_type : str, optionnal + Installation type, Defaults to `""`. TODO: Add description and possible types + install_on_cold_storage : bool, optional + Defaults to `False`. TODO: Add description + blCheckDep : bool, optional + Defaults to `False`. TODO: Add description + replacepkgs : dict, optional + Defaults to `{}`. TODO: Add description + + Returns + ------- + dict + List of usefull informations about volumes. + + Examples + -------- + ```json + { + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 184.52 GB )", + "mount_point": "/volume1", + "size_free": "198126022656", + "size_total": "206158430208", + "vol_desc": "vol1", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.16 GB )", + "mount_point": "/volume2", + "size_free": "2567484923904", + "size_total": "3623234412544", + "vol_desc": "vol2", + "volume_features": [] + } + ], + "volume_path": "/volume1" + }, + "success": true, + } + ``` + """ + api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] api_path = info['path'] @@ -696,63 +722,64 @@ def check_installation(self, "blCheckDep": blCheckDep, "replacepkgs": json.dumps(replacepkgs) } - + return self.request_data(api_name, api_path, req_param) - + def upgrade_package(self, task_id: str, check_codesign: bool = False, force: bool = False, installrunpackage: bool = True, extra_values: dict = {}) -> dict: - """Upgrade an existing package - - Parameters - ---------- - task_id : str - Task id of the download or the upload file - check_codesign : bool, optional - Check signature of the source code of the package (is it a Synology one). Defaults to `False` - force : bool, optional - Force installation. Defaults to `False` - installrunpackage : bool, optional - Run package after installation. Defaults to `True` - extra_values : dict, optional - Extra values due to some package installation. Defaults to `{}` - All known extra values are: - - Surveillance station - ```json - { - "chkSVS_Alias": true, - "strSVS_Alias": "cam", - "chkSVS_HTTP": true, - "strSVS_HTTP": "9900", - "chkSVS_HTTPS": true, - "strSVS_HTTPS": "9901" - } - ``` - - Returns - ------- - dict - Message and some info about installation - - Example return - ---------- + """ +Upgrade an existing package. + + Parameters + ---------- + task_id : str + Task id of the download or the upload file + check_codesign : bool, optional + Check signature of the source code of the package (is it a Synology one). Defaults to `False` + force : bool, optional + Force installation. Defaults to `False` + installrunpackage : bool, optional + Run package after installation. Defaults to `True` + extra_values : dict, optional + Extra values due to some package installation. Defaults to `{}` + All known extra values are: + - Surveillance station ```json - { - "data": { - "message": "

Installation Successful!

\n

Note: If Plex cannot access your media, verify user PlexMediaServer is granted permission in Control Panel.


\nSet access to your media share(s) by performing the following steps:

\n1. Open Control Panel and select Shared Folder
\n2. Select the share which contains your media and click Edit
\n3. Click the Permissions tab
\n4. Change the dropdown from Local Users to System internal user
\n5. Check the Read/Write checkbox for the PlexMediaServer user
\n6. Click Save to confirm the new permissions
\n7. Repeat steps 2-6 for each share you want Plex Media Server to access
\n", - "packageName": "Plex Media Server", - "worker_message": [] - }, - "success": true, - } + { + "chkSVS_Alias": true, + "strSVS_Alias": "cam", + "chkSVS_HTTP": true, + "strSVS_HTTP": "9900", + "chkSVS_HTTPS": true, + "strSVS_HTTPS": "9901" + } ``` + + Returns + ------- + dict + Message and some info about installation. + + Examples + -------- + ```json + { + "data": { + "message": "

Installation Successful!

\n

Note: If Plex cannot access your media, verify user PlexMediaServer is granted permission in Control Panel.


\nSet access to your media share(s) by performing the following steps:

\n1. Open Control Panel and select Shared Folder
\n2. Select the share which contains your media and click Edit
\n3. Click the Permissions tab
\n4. Change the dropdown from Local Users to System internal user
\n5. Check the Read/Write checkbox for the PlexMediaServer user
\n6. Click Save to confirm the new permissions
\n7. Repeat steps 2-6 for each share you want Plex Media Server to access
\n", + "packageName": "Plex Media Server", + "worker_message": [] + }, + "success": true, + } + ``` """ - + api_name = 'SYNO.Core.Package.Installation' info = self.core_list[api_name] api_path = info['path'] req_param = { - "method":"upgrade", - "version":info['minVersion'], - "type":0, + "method": "upgrade", + "version": info['minVersion'], + "type": 0, "check_codesign": check_codesign, "force": force, "installrunpackage": installrunpackage, @@ -760,96 +787,98 @@ def upgrade_package(self, task_id: str, check_codesign: bool = False, force: boo "extra_values": json.dumps(extra_values), } return self.request_data(api_name, api_path, req_param) - - def install_package(self, package_id:str, volume_path: str, file_path: str, check_codesign: bool = True, force: bool = True, installrunpackage: bool = True, extra_values: dict = {}) -> dict: - """Install a package that is already downloaded - - Parameters - ---------- - package_id : str - Id of the package to install - volume_path : str - Volume path of the installation, can get from `check_installation` function - file_path : str - File path of the installation, can get from `check_installation_from_download` function - check_codesign : bool, optional - Check signature of the source code of the package (is it a Synology one). Defaults to `False` - force : bool, optional - Force installation. Defaults to `False` - installrunpackage : bool, optional - Run package after installation. Defaults to `True` - extra_values : dict, optional - Extra values due to some package installation. Defaults to `{}` - All known extra values are: - - Surveillance station - ```json - { - "chkSVS_Alias": true, - "strSVS_Alias": "cam", - "chkSVS_HTTP": true, - "strSVS_HTTP": "9900", - "chkSVS_HTTPS": true, - "strSVS_HTTPS": "9901" - } - ``` - Returns - ------- - dict - Message and some info about installation - - Example return - ---------- + + def install_package(self, package_id: str, volume_path: str, file_path: str, check_codesign: bool = True, force: bool = True, installrunpackage: bool = True, extra_values: dict = {}) -> dict: + """ + Install a package that is already downloaded. + + Parameters + ---------- + package_id : str + Id of the package to install + volume_path : str + Volume path of the installation, can get from `check_installation` function + file_path : str + File path of the installation, can get from `check_installation_from_download` function + check_codesign : bool, optional + Check signature of the source code of the package (is it a Synology one). Defaults to `False` + force : bool, optional + Force installation. Defaults to `False` + installrunpackage : bool, optional + Run package after installation. Defaults to `True` + extra_values : dict, optional + Extra values due to some package installation. Defaults to `{}` + All known extra values are: + - Surveillance station ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.Core.Package.Installation", - "data": { - "is_occupied": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 185.09 GB )", - "mount_point": "/volume1", - "size_free": "198739943424", - "size_total": "206158430208", - "vol_desc": "Apps", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.17 GB )", - "mount_point": "/volume2", - "size_free": "2567495630848", - "size_total": "3623234412544", - "vol_desc": "Stockage", - "volume_features": [] - } - ], - "volume_path": "/volume1" - }, - "method": "check", - "success": true, - "version": 1 - }, - { - "api": "SYNO.Core.Package.Installation", - "data": { - "packageName": "Text Editor", - "worker_message": [] - }, - "method": "install", - "success": true, - "version": 1 - } - ] - }, - "success": true - } + { + "chkSVS_Alias": true, + "strSVS_Alias": "cam", + "chkSVS_HTTP": true, + "strSVS_HTTP": "9900", + "chkSVS_HTTPS": true, + "strSVS_HTTPS": "9901" + } ``` + + Returns + ------- + dict + Message and some info about installation. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Package.Installation", + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 185.09 GB )", + "mount_point": "/volume1", + "size_free": "198739943424", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.17 GB )", + "mount_point": "/volume2", + "size_free": "2567495630848", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ], + "volume_path": "/volume1" + }, + "method": "check", + "success": true, + "version": 1 + }, + { + "api": "SYNO.Core.Package.Installation", + "data": { + "packageName": "Text Editor", + "worker_message": [] + }, + "method": "install", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` """ compound = [ { @@ -865,9 +894,9 @@ def install_package(self, package_id:str, volume_path: str, file_path: str, chec }, { "api": "SYNO.Core.Package.Installation", - "method":"install", - "version":self.core_list["SYNO.Core.Package.Installation"]['minVersion'], - "type":0, + "method": "install", + "version": self.core_list["SYNO.Core.Package.Installation"]['minVersion'], + "type": 0, "volume_path": volume_path, "path": file_path, "check_codesign": check_codesign, @@ -879,34 +908,36 @@ def install_package(self, package_id:str, volume_path: str, file_path: str, chec return self.batch_request(compound=compound) def uninstall_package(self, package_id: str) -> dict: - """Uninstall a package - - Parameters - ---------- - package_id : str - Id of the package to uninstall - - Returns - ------- - dict - Possible message to the user - - Example return - ---------- - ```json - { - "data": { - "message": "", - "worker_message": [] - }, - "success": true - } - ``` """ - + Uninstall a package. + + Parameters + ---------- + package_id : str + Id of the package to uninstall + + Returns + ------- + dict + Possible message to the user. + + Examples + -------- + ```json + { + "data": { + "message": "", + "worker_message": [] + }, + "success": true + } + ``` + """ + if not self._is_package_already_installed(package_id=package_id): - raise Exception(f"""Package "{package_id}" is not installed, it cannot be uninstalled""") - + raise Exception( + f"""Package "{package_id}" is not installed, it cannot be uninstalled""") + api_name = 'SYNO.Core.Package.Uninstallation' info = self.core_list[api_name] api_path = info['path'] @@ -916,87 +947,102 @@ def uninstall_package(self, package_id: str) -> dict: "id": package_id, "dsm_apps": "" } - + return self.request_data(api_name, api_path, req_param) def _is_package_already_installed(self, package_id: str) -> bool: + """ + Check if a package is already installed. + + Parameters + ---------- + package_id : str + Package ID to check + + Returns + ------- + bool + `True` if the package is already installed, `False` otherwise. + """ response: dict = self.list_installed() data: dict = response.get("data") installed_packages = data.get("packages") - package_infos: dict = next((package for package in installed_packages if package["id"] == package_id), None) + package_infos: dict = next( + (package for package in installed_packages if package["id"] == package_id), None) return package_infos != None def easy_install(self, package_id: str, volume_path: str, install_dependencies: bool = True) -> dict: - """Execute an "easy" installation process of the package - - Parameters - ---------- - package_id : str - Package ID to install - volume_path : str - Volume path where you want to install the package - install_dependencies : bool, optional - If you want to install dependencies. Defaults to `True` - - Returns - ------- - dict - Information about installation, same as `install_package` function - - Example return - ---------- - ```json - { - "data": { - "has_fail": false, - "result": [ - { - "api": "SYNO.Core.Package.Installation", - "data": { - "is_occupied": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 185.11 GB )", - "mount_point": "/volume1", - "size_free": "198759485440", - "size_total": "206158430208", - "vol_desc": "Apps", - "volume_features": [] - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 2391.17 GB )", - "mount_point": "/volume2", - "size_free": "2567495565312", - "size_total": "3623234412544", - "vol_desc": "Stockage", - "volume_features": [] - } - ], - "volume_path": "/volume1" - }, - "method": "check", - "success": true, - "version": 1 + """ + Execute an "easy" installation process of the package. + + Parameters + ---------- + package_id : str + Package ID to install + volume_path : str + Volume path where you want to install the package + install_dependencies : bool, optional + If you want to install dependencies. Defaults to `True` + + Returns + ------- + dict + Information about installation, same as `install_package` function. + + Examples + -------- + ```json + { + "data": { + "has_fail": false, + "result": [ + { + "api": "SYNO.Core.Package.Installation", + "data": { + "is_occupied": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 185.11 GB )", + "mount_point": "/volume1", + "size_free": "198759485440", + "size_total": "206158430208", + "vol_desc": "Apps", + "volume_features": [] + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 2391.17 GB )", + "mount_point": "/volume2", + "size_free": "2567495565312", + "size_total": "3623234412544", + "vol_desc": "Stockage", + "volume_features": [] + } + ], + "volume_path": "/volume1" }, - { - "api": "SYNO.Core.Package.Installation", - "data": { - "packageName": "Text Editor", - "worker_message": [] - }, - "method": "install", - "success": true, - "version": 1 - } - ] - }, - "success": true - } - ``` - """ + "method": "check", + "success": true, + "version": 1 + }, + { + "api": "SYNO.Core.Package.Installation", + "data": { + "packageName": "Text Editor", + "worker_message": [] + }, + "method": "install", + "success": true, + "version": 1 + } + ] + }, + "success": true + } + ``` + """ # Package already installed if self._is_package_already_installed(package_id): @@ -1005,37 +1051,43 @@ def easy_install(self, package_id: str, volume_path: str, install_dependencies: response: dict = self.list_installable() data: dict = response.get("data") installable_packages = data.get("packages") - package_infos: dict = next((package for package in installable_packages if package["id"] == package_id), None) + package_infos: dict = next( + (package for package in installable_packages if package["id"] == package_id), None) # Package not found if package_infos == None: - raise Exception(f"""Package "{package_id}" not found in installable list, installation not possible""") - + raise Exception( + f"""Package "{package_id}" not found in installable list, installation not possible""") # Check dependencies deppkgs = package_infos.get("deppkgs") if deppkgs: if not install_dependencies: - raise Exception(f"""Package "{package_id}" has dependencies that needs to be installed but "install_dependencies" is set to "False" """) + raise Exception( + f"""Package "{package_id}" has dependencies that needs to be installed but "install_dependencies" is set to "False" """) deppkg: str for deppkg in deppkgs: if not self._is_package_already_installed(deppkg): - print(f"""Installation of dependency "{deppkg}" for "{package_id}" started""") - self.easy_install(package_id=deppkg, volume_path=volume_path) - print(f"""Installation of dependency "{deppkg}" for "{package_id}" done""") - + print( + f"""Installation of dependency "{deppkg}" for "{package_id}" started""") + self.easy_install(package_id=deppkg, + volume_path=volume_path) + print( + f"""Installation of dependency "{deppkg}" for "{package_id}" done""") + # Store information of the package url = package_infos.get("link") filesize = package_infos.get("size") version = package_infos.get("version") checksum = package_infos.get("md5") - - ## Start installation sequence - + + # Start installation sequence + # Start download the package installation file - response: dict = self.download_package(url=url, package_id=package_id, checksum=checksum, filesize=filesize) + response: dict = self.download_package( + url=url, package_id=package_id, checksum=checksum, filesize=filesize) data: dict = response.get("data") task_id = data.get("taskid") - + # Create progress bar of the status response: dict = self.get_dowload_package_status(task_id=task_id) data: dict = response.get("data") @@ -1043,7 +1095,8 @@ def easy_install(self, package_id: str, volume_path: str, install_dependencies: if not data.get("finished"): with tqdm.tqdm(total=100) as pbar: while not data.get("finished"): - response: dict = self.get_dowload_package_status(task_id=task_id) + response: dict = self.get_dowload_package_status( + task_id=task_id) data: dict = response.get("data") progress: float = data.get("progress") if progress: @@ -1059,10 +1112,10 @@ def easy_install(self, package_id: str, volume_path: str, install_dependencies: status = data.get("status") file_path = data.get("filename") print(f"""Downloaded file status : {status}""") - + # Check installation response = self.check_installation(package_id=package_id) - + # Install package extra_values = {} if package_id == "SurveillanceStation": @@ -1074,5 +1127,5 @@ def easy_install(self, package_id: str, volume_path: str, install_dependencies: "chkSVS_HTTPS": True, "strSVS_HTTPS": "9901" } - + return self.install_package(package_id=package_id, volume_path=volume_path, file_path=file_path, extra_values=extra_values) diff --git a/synology_api/DSM/Package/__init__.py b/synology_api/DSM/Package/__init__.py index b624c349..4ab7b736 100644 --- a/synology_api/DSM/Package/__init__.py +++ b/synology_api/DSM/Package/__init__.py @@ -1,2 +1,9 @@ + +""" +Package submodule for Synology DSM API. + +Provides FileStation and PackageCenter API classes. +""" + from .FileStation import FileStation -from .PackageCenter import PackageCenter \ No newline at end of file +from .PackageCenter import PackageCenter diff --git a/synology_api/DSM/__init__.py b/synology_api/DSM/__init__.py index 433754c4..42906cec 100644 --- a/synology_api/DSM/__init__.py +++ b/synology_api/DSM/__init__.py @@ -1,20 +1,51 @@ +""" +Main entry point for Synology DSM API access. +""" + from .ControlPanel import ControlPanel from .Package.FileStation import FileStation from .Package.PackageCenter import PackageCenter - from synology_api import base_api + class DSM(base_api.BaseApi): + """ + Main entry point for Synology DSM API access. Provides access to ControlPanel, FileStation, and PackageCenter APIs. + + Parameters + ---------- + *args : tuple + Positional arguments passed to BaseApi. + **kwargs : dict + Keyword arguments passed to BaseApi. + """ _ctrl_panel = None _file_station = None _package_center = None - + def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + """ + Initialize DSM API wrapper. + Parameters + ---------- + *args : tuple + Positional arguments passed to BaseApi. + **kwargs : dict + Keyword arguments passed to BaseApi. + """ + super().__init__(*args, **kwargs) @property def ControlPanel(self): + """ + ControlPanel: ControlPanel. + + Returns + ------- + ControlPanel + Instance of the ControlPanel API, sharing the same state as DSM. + """ if self._ctrl_panel is None: # Create ControlPanel instance without calling __init__ self._ctrl_panel = ControlPanel.__new__(ControlPanel) @@ -24,18 +55,34 @@ def ControlPanel(self): @property def FileStation(self): + """ + FileStation: FileStation. + + Returns + ------- + FileStation + Instance of the FileStation API, sharing the same state as DSM. + """ if self._file_station is None: # Create FileStation instance without calling __init__ self._file_station = FileStation.__new__(FileStation) # Share the state self._file_station.__dict__ = self.__dict__ return self._file_station - + @property def PackageCenter(self): + """ + PackageCenter: PackageCenter. + + Returns + ------- + PackageCenter + Instance of the PackageCenter API, sharing the same state as DSM. + """ if self._package_center is None: # Create PackageCenter instance without calling __init__ self._package_center = PackageCenter.__new__(PackageCenter) # Share the state self._package_center.__dict__ = self.__dict__ - return self._package_center \ No newline at end of file + return self._package_center From 273d5911065db7545b9f1d52ea330f779109ac7b Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sat, 13 Sep 2025 13:54:38 +0200 Subject: [PATCH 082/126] Udpate FileStation generate_file_tree --- synology_api/DSM/ControlPanel/SharedFolder.py | 77 ------------------- synology_api/DSM/Package/FileStation.py | 63 +++++++++++---- 2 files changed, 48 insertions(+), 92 deletions(-) diff --git a/synology_api/DSM/ControlPanel/SharedFolder.py b/synology_api/DSM/ControlPanel/SharedFolder.py index 74b6b195..d2222b40 100644 --- a/synology_api/DSM/ControlPanel/SharedFolder.py +++ b/synology_api/DSM/ControlPanel/SharedFolder.py @@ -1023,80 +1023,3 @@ def list(self) -> dict: } return self.request_data(api_name, api_path, req_param) - - def decrypt_folder(self, name: str, password: str) -> dict: - """ - Decrypt a given share. - - Parameters - ---------- - name : str - The share name to decrypt. - password : str - The password to use for decrypting the share. - - Returns - ------- - dict - Success. - - Examples - -------- - ```json - { - "success": true - } - ``` - """ - api_name = "SYNO.Core.Share.Crypto" - info = self.core_list[api_name] - api_path = info["path"] - req_param = { - "method": "decrypt", - "version": info['maxVersion'], - "name": name, - } - - req_param_encrypted = { - "password": password, - } - # If using https don't use encryption - if self.session._secure: - req_param.update(req_param_encrypted) - else: - encrypted_params = self.session.encrypt_params(req_param_encrypted) - req_param.update(encrypted_params) - - return self.request_data(api_name, api_path, req_param, method="post") - - def encrypt_folder(self, name: str) -> dict: - """ - Encrypt a given share. - - Parameters - ---------- - name : str - The share name to encrypt. - - Returns - ------- - dict - Success. - - Examples - -------- - ```json - { - "success": true - } - ``` - """ - api_name = "SYNO.Core.Share.Crypto" - info = self.core_list[api_name] - api_path = info["path"] - req_param = { - "method": "encrypt", - "version": info['maxVersion'], - "name": name, - } - return self.request_data(api_name, api_path, req_param, method="post") diff --git a/synology_api/DSM/Package/FileStation.py b/synology_api/DSM/Package/FileStation.py index d4f39291..1d3655ca 100644 --- a/synology_api/DSM/Package/FileStation.py +++ b/synology_api/DSM/Package/FileStation.py @@ -15,6 +15,7 @@ from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor from urllib import parse from treelib import Tree +import warnings from synology_api import base_api @@ -2544,29 +2545,61 @@ def get_file(self, path: str | list[str], mode: str, dest_path: str = ".", chunk r.raise_for_status() return io.BytesIO(r.content) - def generate_file_tree(self, folder_path: str, tree: Tree) -> None: + def generate_file_tree(self, + folder_path: str, + tree: Tree, + max_depth: Optional[int] = 1, + start_depth: Optional[int] = 0) -> None: """ - Generate the file tree based on the folder path you give, you need to create the root node before call this function. + Recursively generate the file tree based on the folder path you give constrained with. + + You need to create the root node before calling this function. Parameters ---------- folder_path : str - Folder path to generate file tree + Folder path to generate file tree. tree : Tree - Instance of the Tree of lib "Treelib", this will be modified by the method - """ - data: dict = self.get_file_list( + Instance of the Tree from the `treelib` library. + max_depth : int, optional + Non-negative number of maximum depth of tree generation if node tree is directory, default to '1' to generate full tree. If 'max_depth=0' it will be equivalent to no recursion. + start_depth : int, optional + Non negative number to start to control tree generation default to '0'. + """ + api_name = 'hotfix' # fix for docs_parser.py issue + + if start_depth < 0: + start_depth = 0 + warnings.warn( + f"'start_depth={start_depth}'. It should not be less or than 0, setting 'start_depth' to 0!", + RuntimeWarning, + stacklevel=2 + ) + + assert start_depth <= max_depth, ValueError( + f"'start_depth' should not be greater than 'max_depth'. Got '{start_depth=}, {max_depth=}'") + assert isinstance(tree, Tree), ValueError( + "'tree' has to be a type of 'Tree'") + + data: dict[str, object] = self.get_file_list( folder_path=folder_path ).get("data") files = data.get("files") - file: dict - for file in files: - file_name: str = file.get("name") - file_path: str = file.get("path") - if file.get("isdir"): - - tree.create_node(file_name, file_path, parent=folder_path) - self.generate_file_tree(file_path, tree) + _file_info_getter = map(lambda x: ( + x.get('isdir'), x.get('name'), x.get('path')), files) + for isdir, file_name, file_path in _file_info_getter: + + if isdir and (start_depth >= max_depth): + tree.create_node(file_name, file_path, parent=folder_path, data={ + "isdir": isdir, "max_depth": True}) + + elif isdir: + tree.create_node(file_name, file_path, parent=folder_path, data={ + "isdir": isdir, "max_depth": False}) + self.generate_file_tree( + file_path, tree, max_depth, start_depth + 1) + else: - tree.create_node(file_name, file_path, parent=folder_path) + tree.create_node(file_name, file_path, parent=folder_path, data={ + "isdir": isdir, "max_depth": False}) From 05259610bf356a0f0a8d820830c4a2164299c0ee Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sat, 13 Sep 2025 20:03:16 +0200 Subject: [PATCH 083/126] Implementation of Login Portal --- synology_api/DSM/ControlPanel/LoginPortal.py | 820 ++++++++++++++++++- 1 file changed, 819 insertions(+), 1 deletion(-) diff --git a/synology_api/DSM/ControlPanel/LoginPortal.py b/synology_api/DSM/ControlPanel/LoginPortal.py index 935a3d86..2fe0df0d 100644 --- a/synology_api/DSM/ControlPanel/LoginPortal.py +++ b/synology_api/DSM/ControlPanel/LoginPortal.py @@ -2,10 +2,828 @@ Login portal class for Synology DSM. """ from synology_api import base_api +import json class LoginPortal(base_api.BaseApi): """ Login portal class for Synology DSM. """ - pass + + def get_dsm_web_service_info(self) -> dict: + """ + Get the web status of the login portal. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "data": { + "enable_avahi": true, + "enable_custom_domain": false, + "enable_hsts": false, + "enable_https_redirect": false, + "enable_max_connections": false, + "enable_reuseport": false, + "enable_server_header": true, + "enable_spdy": true, + "enable_ssdp": true, + "fqdn": null, + "http_port": 5000, + "https_port": 5001, + "main_app": "DSM", + "max_connections": 2048, + "max_connections_limit": { + "lower": 2048, + "upper": 131070 + }, + "server_header": "nginx", + "support_reuseport": true + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Web.DSM" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "get", + } + return self.request_data(api_name, api_path, req_param) + + def list_app_portal(self, additionnal: list = []) -> dict: + """ + List application portals. + + Parameters + ---------- + additionnal : list, optional + Additional fields to include in the response, by default []. Possible values are "default_setting". + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "data": { + "portal": [ + { + "display_name": "Active Backup for Microsoft 365 Portal", + "enable_redirect": false, + "id": "SYNO.SDS.ActiveBackupOffice365.Portal.Instance" + }, + { + "display_name": "Synology Calendar", + "enable_redirect": false, + "id": "SYNO.Cal.Application" + }, + { + "display_name": "Synology Contacts", + "enable_redirect": false, + "id": "SYNO.Contacts.AppInstance" + }, + { + "display_name": "Download Station", + "enable_redirect": false, + "id": "SYNO.SDS.DownloadStation.Application" + }, + { + "display_name": "File Station", + "enable_redirect": false, + "id": "SYNO.SDS.App.FileStation3.Instance" + }, + { + "display_name": "Note Station", + "enable_redirect": false, + "id": "SYNO.SDS.NoteStation.Application" + }, + { + "acl": null, + "alias": "cam", + "display_name": "Surveillance Station", + "enable_redirect": false, + "fqdn": null, + "hsts": false, + "http_port": 9900, + "id": "SYNO.SDS.SurveillanceStation" + }, + { + "display_name": "Synology Drive", + "enable_redirect": false, + "id": "SYNO.SDS.SheetStation.Application" + }, + { + "display_name": "Virtual Machine Manager", + "enable_redirect": false, + "id": "SYNO.SDS.Virtualization.Application" + } + ] + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "list", + "additional": json.dumps(additionnal), + } + return self.request_data(api_name, api_path, req_param) + + def list_reverse_proxy(self) -> dict: + """ + List reverse proxy rules. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "data": { + "entries": [] + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.ReverseProxy" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "list", + } + return self.request_data(api_name, api_path, req_param) + + def list_access_control(self) -> dict: + """ + List access control rules. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "data": { + "entries": [ + { + "UUID": "4d0b7d3d-d8a5-4b91-a160-efd45703005f", + "name": "test", + "rules": [ + { + "access": true, + "address": "127.0.0.1" + } + ] + } + ] + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.AccessControl" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "list", + } + return self.request_data(api_name, api_path, req_param) + + def get_login_theme(self) -> dict: + """ + Get the current login theme. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "data": { + "background_color": "#FFFFFF", + "background_position": "fill", + "background_seq": 0, + "enable_background_customize": false, + "enable_logo_customize": false, + "login_footer_enable_html": false, + "login_title": "", + "login_version_logo": false, + "logo_position": "center", + "logo_seq": 0, + "only_background_color": false, + "weather_info": "display" + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.Theme.Login" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "get", + } + return self.request_data(api_name, api_path, req_param) + + def get_app_theme(self, app_id: str) -> dict: + """ + Get the theme for a specific application. + + Parameters + ---------- + app_id : str + The ID of the application. The app_id can be found in the `list_app_portal()` returns. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "background_color": "#FFFFFF", + "background_position": "fill", + "background_seq": 0, + "enable_background_customize": false, + "enable_logo_customize": false, + "from_dsm": true, + "login_footer_enable_html": false, + "login_title": "", + "login_version_logo": false, + "logo_position": "center", + "logo_seq": 0, + "only_background_color": false, + "weather_info": "display" + } + ``` + """ + api_name = "SYNO.Core.Theme.AppPortalLogin" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "get", + "app": app_id, + } + return self.request_data(api_name, api_path, req_param) + + def set_dsm_web_service_info(self, + enable_custom_domain: bool, enable_avahi: bool, enable_hsts: bool, enable_https_redirect: bool, + enable_max_connections: bool, enable_reuseport: bool, enable_server_header: bool, enable_spdy: bool, + enable_ssdp: bool, fqdn: str = "", http_port: int = 5000, https_port: int = 5001, main_app: str = "DSM", max_connections: int = 2048, + max_connections_limit: dict = {"lower": 2048, "upper": 131070}, server_header: str = "nginx", support_reuseport: bool = True + ) -> dict: + """ + Set the web service information for DSM. Note that this will likely restart the web service. + + Parameters + ---------- + enable_custom_domain : bool + Enable custom domain. + enable_avahi : bool + Enable Avahi (mDNS) support. + enable_hsts : bool + Enable HTTP Strict Transport Security (HSTS). + enable_https_redirect : bool + Enable HTTPS redirection. + enable_max_connections : bool + Enable maximum connections limit. + enable_reuseport : bool + Enable SO_REUSEPORT option. + enable_server_header : bool + Enable server header in responses. + enable_spdy : bool + Enable SPDY protocol support. + enable_ssdp : bool + Enable SSDP support. + fqdn : str, optional + Fully qualified domain name, by default "". + http_port : int, optional + HTTP port number, by default 5000. + https_port : int, optional + HTTPS port number, by default 5001. + main_app : str, optional + Main application to launch on login, by default "DSM". + max_connections : int, optional + Maximum number of connections, by default 2048. + max_connections_limit : dict, optional + Dictionary with 'lower' and 'upper' keys for max connections limit, by default {"lower": 2048, "upper": 131070}. + server_header : str, optional + Server header string, by default "nginx". + support_reuseport : bool, optional + Whether SO_REUSEPORT is supported, by default True. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Web.DSM" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "set", + "enable_custom_domain": enable_custom_domain, + "enable_avahi": enable_avahi, + "enable_hsts": enable_hsts, + "enable_https_redirect": enable_https_redirect, + "enable_max_connections": enable_max_connections, + "enable_reuseport": enable_reuseport, + "enable_server_header": enable_server_header, + "enable_spdy": enable_spdy, + "enable_ssdp": enable_ssdp, + "fqdn": fqdn, + "http_port": http_port, + "https_port": https_port, + "main_app": main_app, + "max_connections": max_connections, + "max_connections_limit": json.dumps(max_connections_limit), + "server_header": server_header, + "support_reuseport": support_reuseport + } + return self.request_data(api_name, api_path, req_param) + + def set_login_theme(self, + background_color: str = "#FFFFFF", background_position: str = "fill", background_seq: int = 0, + enable_background_customize: bool = False, enable_logo_customize: bool = False, + login_footer_enable_html: bool = False, login_title: str = "", login_version_logo: bool = False, + logo_position: str = "center", logo_seq: int = 0, only_background_color: bool = False, + weather_info: str = "display" + ) -> dict: + """ + Set the login theme for DSM. + + Parameters + ---------- + background_color : str, optional + Background color in HEX format, by default "#FFFFFF". + background_position : str, optional + Background image position, by default "fill". Possible values are "fill", "fit", "stretch", "center", "tile". + background_seq : int, optional + Background image sequence number, by default 0. + enable_background_customize : bool, optional + Enable custom background image, by default False. + enable_logo_customize : bool, optional + Enable custom logo image, by default False. + login_footer_enable_html : bool, optional + Enable HTML in the login footer, by default False. + login_title : str, optional + Custom login title text, by default "". + login_version_logo : bool, optional + Show DSM version logo on the login page, by default False. + logo_position : str, optional + Logo image position, by default "center". Possible values are "left", "center", "right". + logo_seq : int, optional + Logo image sequence number, by default 0. + only_background_color : bool, optional + Use only background color without image, by default False. + weather_info : str, optional + Weather information display option, by default "display". Possible values are "display", "hide". + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.Theme.Login" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "set", + "background_color": background_color, + "background_position": background_position, + "background_seq": background_seq, + "enable_background_customize": enable_background_customize, + "enable_logo_customize": enable_logo_customize, + "login_footer_enable_html": login_footer_enable_html, + "login_title": login_title, + "login_version_logo": login_version_logo, + "logo_position": logo_position, + "logo_seq": logo_seq, + "only_background_color": only_background_color, + "weather_info": weather_info + } + return self.request_data(api_name, api_path, req_param) + + def get_config(self) -> dict: + """ + Get the login portal configuration. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "data": { + "show_titlebar": true + }, + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.Config" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "get", + } + return self.request_data(api_name, api_path, req_param) + + def set_config(self, show_titlebar: bool) -> dict: + """ + Set the login portal configuration. + + Parameters + ---------- + show_titlebar : bool + Whether to show the title bar on the login portal. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.Config" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "set", + "show_titlebar": show_titlebar + } + return self.request_data(api_name, api_path, req_param) + + def create_access_control_profile(self, name: str, rules: list) -> dict: + """ + Create an access control profile. + + Parameters + ---------- + name : str + Name of the access control profile. + rules : list + List of rules for the access control profile. Each rule is a dictionary with keys: + - action: "allow" or "deny" + - source: source IP or subnet in CIDR notation + - protocol: "http", "https", or "both" + - port: port number or range (e.g., "80", "443", "8000-9000") + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.AccessControl" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "create", + "name": name, + "rules": json.dumps(rules) + } + return self.request_data(api_name, api_path, req_param) + + def edit_access_control_profile(self, uuid: str, name: str, rules: list) -> dict: + """ + Edit an existing access control profile. + + Parameters + ---------- + uuid : str + UUID of the access control profile to edit. The UUID can be found in the `list_access_control()` returns. + name : str + New name for the access control profile. + rules : list + New list of rules for the access control profile. Each rule is a dictionary with keys: + - address : str (source IP or subnet in CIDR notation) + - access : bool (True for allow, False for deny) + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.AccessControl" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "edit", + "uuid": uuid, + "name": name, + "rules": json.dumps(rules) + } + return self.request_data(api_name, api_path, req_param) + + def delete_access_control_profile(self, uuids: list) -> dict: + """ + Delete one or more access control profiles. + + Parameters + ---------- + uuids : list + List of UUIDs of the access control profiles to delete. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.AccessControl" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "delete", + "uuids": json.dumps(uuids) + } + return self.request_data(api_name, api_path, req_param) + + def create_reverse_proxy_rule(self, entry: dict) -> dict: + """ + Create a reverse proxy rule. + + Parameters + ---------- + entry : dict + The reverse proxy rule configuration. Example: + { + "description": "yrdy", + "proxy_connect_timeout": 60, + "proxy_read_timeout": 60, + "proxy_send_timeout": 60, + "proxy_http_version": 1, + "proxy_intercept_errors": False, + "frontend": { + "acl": None, + "fqdn": None, + "port": 8000, + "protocol": 0, + "https": {"hsts": False} + }, + "backend": { + "fqdn": "localhost", + "port": 8080, + "protocol": 0 + }, + "customize_headers": [ + {"name": "yoyo", "value": "test"} + ] + } + + Returns + ------- + dict + Success response from the API. + + Examples + -------- + ```json + { + 'success': True + } + ``` + """ + api_name = 'SYNO.Core.AppPortal.ReverseProxy' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': 1, + 'method': 'create', + 'entry': json.dumps(entry) + } + return self.request_data(api_name, api_path, req_param) + + def edit_reverse_proxy_rule(self, entry: dict) -> dict: + """ + Edit a reverse proxy rule. + + Parameters + ---------- + entry : dict + The reverse proxy rule configuration, including UUID and _key. Example: + { + "description": "yrdy", + "proxy_connect_timeout": 60, + "proxy_read_timeout": 60, + "proxy_send_timeout": 60, + "proxy_http_version": 1, + "proxy_intercept_errors": False, + "UUID": "91dbcc5b-2467-4047-996c-2b5beb4fbefa", + "backend": { + "fqdn": "localhost", + "port": 8080, + "protocol": 0 + }, + "customize_headers": [ + {"name": "yoyo", "value": "test"} + ], + "frontend": { + "acl": None, + "fqdn": None, + "port": 8000, + "protocol": 0, + "https": {"hsts": False} + } + } + + Returns + ------- + dict + API response. + + Examples + -------- + ```json + { + 'success': True + } + ``` + """ + api_name = 'SYNO.Core.AppPortal.ReverseProxy' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': 1, + 'method': 'update', + 'entry': json.dumps(entry) + } + return self.request_data(api_name, api_path, req_param) + + def delete_reverse_proxy_rule(self, uuids: list) -> dict: + """ + Delete one or more reverse proxy rules. + + Parameters + ---------- + uuids : list + List of UUIDs of the reverse proxy rules to delete. + + Returns + ------- + dict + The response from the API call. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = "SYNO.Core.AppPortal.ReverseProxy" + info = self.core_list[api_name] + api_path = info["path"] + req_param = { + "version": info["maxVersion"], + "method": "delete", + "uuids": json.dumps(uuids) + } + return self.request_data(api_name, api_path, req_param) + + def edit_app_portal(self, id: str, display_name: str, additional: dict, enable_custom_domain: bool = False, + acl: str = None, fqdn: str = None, enable_redirect: bool = False) -> dict: + """ + Edit (set) an app portal. + + Parameters + ---------- + id : str + The app portal instance ID. + display_name : str + The display name for the portal. + additional : dict + Additional settings, e.g.: + { + "default_setting": { + "alias": "microsoft365", + "fqdn": "", + "hsts": False, + "http_port": 28003, + "https_port": 28004 + } + } + enable_custom_domain : bool, optional + Enable custom domain. Default is False. + acl : str, optional + Access control profile uuid. Default is None. + fqdn : str, optional + Fully qualified domain name. Default is None. + enable_redirect : bool, optional + Enable redirect. Default is False. + + Returns + ------- + dict + API response. + + Examples + -------- + ```json + { + 'success': True + } + ``` + """ + api_name = 'SYNO.Core.AppPortal' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': 2, + 'method': 'set', + 'id': id, + 'display_name': display_name, + 'additional': json.dumps(additional), + 'enable_custom_domain': enable_custom_domain, + 'acl': acl, + 'fqdn': fqdn, + 'enable_redirect': enable_redirect + } + return self.request_data(api_name, api_path, req_param) From e6a7c747299e393d2fb61bf6c455349d1128891d Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 14 Sep 2025 22:58:11 +0200 Subject: [PATCH 084/126] Implementation of Notifications --- .../DSM/ControlPanel/Notifications.py | 1196 ++++++++++++++++- 1 file changed, 1195 insertions(+), 1 deletion(-) diff --git a/synology_api/DSM/ControlPanel/Notifications.py b/synology_api/DSM/ControlPanel/Notifications.py index f3eaf040..2bd75748 100644 --- a/synology_api/DSM/ControlPanel/Notifications.py +++ b/synology_api/DSM/ControlPanel/Notifications.py @@ -2,10 +2,1204 @@ Notifications API endpoint. """ from synology_api import base_api +import json +import requests class Notifications(base_api.BaseApi): """ Notifications API endpoint. """ - pass + + def list_filter_settings(self) -> dict: + """ + List current filter settings. + + Returns + ------- + dict + Current filter settings including enabled rule levels and types. + + Examples + -------- + ```json + { + "data": { + "All": [ + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_INFO", + "name": "AutoBlockAdd", + "source": "dsm", + "tag": "AutoBlockAdd", + "title": "IP address blocked", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_WARN", + "name": "AutoBlockDatabaseRulesWarning", + "source": "dsm", + "tag": "AutoBlockDatabaseRulesWarning", + "title": "Too many IP addresses in the Block List on %HOSTNAME%", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_ERROR", + "name": "CMSClientConnectFailed", + "source": "dsm", + "tag": "CMSClientConnectFailed", + "title": "Unable to connect to the CMS Host", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_INFO", + "name": "CMSClientDetachSuccess", + "source": "dsm", + "tag": "CMSClientDetachSuccess", + "title": "Disjoined from CMS host", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_INFO", + "name": "CMSClientJoinSuccess", + "source": "dsm", + "tag": "CMSClientJoinSuccess", + "title": "Joined CMS host", + "warnPercent": 1 + } + ], + "send_welcome_mail": false, + "sender_mail": "test@gmail.com", + "sender_name": "", + "smtp_auth": { + "enable": true, + "user": "test@gmail.com" + }, + "smtp_info": { + "port": 465, + "server": "smtp.gmail.com", + "ssl": true + }, + "subject_prefix": "[SYNO-FLORENTB]" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail.Conf' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def list_event(self) -> dict: + """ + List recent notification events. + + Returns + ------- + dict + Recent notification events including timestamps, app IDs, levels, and messages. + + Examples + -------- + ```json + { + "data": { + "All": [ + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_INFO", + "name": "AutoBlockAdd", + "source": "dsm", + "tag": "AutoBlockAdd", + "title": "IP address blocked", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_WARN", + "name": "AutoBlockDatabaseRulesWarning", + "source": "dsm", + "tag": "AutoBlockDatabaseRulesWarning", + "title": "Too many IP addresses in the Block List on %HOSTNAME%", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_ERROR", + "name": "CMSClientConnectFailed", + "source": "dsm", + "tag": "CMSClientConnectFailed", + "title": "Unable to connect to the CMS Host", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "format": "mail", + "group": "System", + "level": "NOTIFICATION_INFO", + "name": "CMSClientDetachSuccess", + "source": "dsm", + "tag": "CMSClientDetachSuccess", + "title": "Disjoined from CMS host", + "warnPercent": 1 + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.FilterSettings.Template' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_filter_rule_settings(self, template_id: int) -> dict: + """ + Get the filter settings for a specific template. + + Parameters + ---------- + template_id : int + The ID of the template to retrieve settings for. + + Returns + ------- + dict + API response containing the filter settings for the specified template. + + Examples + -------- + ```json + { + "data": { + "All": [ + { + "appid": "SYNO.SDS.AdminCenter.Application", + "enabled": false, + "format": "mail", + "group": "System", + "level": "NOTIFICATION_INFO", + "name": "AutoBlockAdd", + "source": "dsm", + "tag": "AutoBlockAdd", + "title": "IP address blocked", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "enabled": true, + "format": "mail", + "group": "System", + "level": "NOTIFICATION_WARN", + "name": "AutoBlockDatabaseRulesWarning", + "source": "dsm", + "tag": "AutoBlockDatabaseRulesWarning", + "title": "Too many IP addresses in the Block List on %HOSTNAME%", + "warnPercent": 1 + }, + { + "appid": "SYNO.SDS.AdminCenter.Application", + "enabled": true, + "format": "mail", + "group": "System", + "level": "NOTIFICATION_ERROR", + "name": "CMSClientConnectFailed", + "source": "dsm", + "tag": "CMSClientConnectFailed", + "title": "Unable to connect to the CMS Host", + "warnPercent": 1 + } + ], + "template_id": 5, + "template_name": "test" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.FilterSettings.Template' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'get', + 'template_id': template_id + } + return self.request_data(api_name, api_path, req_param) + + def get_push_mail(self) -> dict: + """ + Get push mail configuration. + + Returns + ------- + dict + Push notification configuration details including service status and linked devices. + + Examples + -------- + ```json + { + "data": { + "enable_mail": true, + "mail": [ + "test@gmail.com" + ], + "subject_prefix": "", + "template_id": 1 + }, + "success": true + } + """ + api_name = 'SYNO.Core.Notification.Push.Mail' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def refresh_token(self) -> dict: + """ + Refresh the push notification token. + + Returns + ------- + dict + Status of the token refresh operation. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'refresh_token' + } + return self.request_data(api_name, api_path, req_param) + + def set_mail_config(self, + enable_mail: bool, + enable_oauth: bool, + subject_prefix: str, + smtp_info: dict, + send_welcome_mail: bool, + sender_name: str, + sender_mail: str, + oauth_provider: str) -> dict: + """ + Set the mail configuration for notifications. + + Parameters + ---------- + enable_mail : bool + Enable mail notifications. + enable_oauth : bool + Enable OAuth authentication. + subject_prefix : str + Prefix for the email subject. + smtp_info : dict + SMTP server information, e.g.: + {"server": "smtp.gmail.com", "port": 465, "ssl": True} + send_welcome_mail : bool + Send a welcome mail after configuration. + sender_name : str + Name of the sender. + sender_mail : str + Email address of the sender. + oauth_provider : str + OAuth provider (e.g., "gmail"). + + Returns + ------- + dict + API response. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail.Conf' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable_mail': enable_mail, + 'enable_oauth': enable_oauth, + 'subject_prefix': subject_prefix, + 'smtp_info': json.dumps(smtp_info), + 'send_welcome_mail': send_welcome_mail, + 'sender_name': sender_name, + 'sender_mail': sender_mail, + 'oauth_provider': oauth_provider + } + return self.request_data(api_name, api_path, req_param) + + def send_test_mail(self, smtp_info: dict, mail: list[str], subject_prefix: str) -> dict: + """ + Send a test mail to verify the mail configuration. + + Parameters + ---------- + smtp_info : dict + SMTP server information, e.g.: + {"server": "smtp.gmail.com", "port": 465, "ssl": True} + mail : list[str] + List of email addresses to send the test email to. + subject_prefix : str + Prefix for the email subject. + + Returns + ------- + dict + Status of the test email operation. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'send_test', + 'smtp_info': json.dumps(smtp_info) if smtp_info else None, + 'mail': json.dumps(mail) if mail else None, + 'subject_prefix': subject_prefix + } + return self.request_data(api_name, api_path, req_param) + + def send_test_push_mail(self, target_id_list: list[int] = None) -> dict: + """ + Send a test push mail to synology account. + + Parameters + ---------- + target_id_list : list[int], optional + List of target IDs to send the test push mail to. If None, sends to all linked devices. + + Returns + ------- + dict + Status of the test email operation. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Push.Mail' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'send_test' + } + if target_id_list: + req_param['target_id_list'] = json.dumps(target_id_list) if len( + target_id_list) > 1 else target_id_list[0] + + return self.request_data(api_name, api_path, req_param) + + def create_mail_profile(self, template_id: int, mail: list[str]) -> dict: + """ + Create a new mail profile for notifications. + + Parameters + ---------- + template_id : int + ID of the filter template to use. Use `list_filter_template` to get available templates. + mail : list[str] + List of email addresses to receive notifications. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail.Profile.Conf' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'create', + 'template_id': template_id, + 'mail': json.dumps(mail) + } + return self.request_data(api_name, api_path, req_param) + + def edit_mail_profile(self, profile_id: int, template_id: int, mail: list[str]) -> dict: + """ + Edit an existing mail profile for notifications. + + Parameters + ---------- + profile_id : int + ID of the profile to edit. Use `get_mail_config` to get existing profiles. + template_id : int + ID of the filter template to use. Use `list_filter_template` to get available templates. + mail : list[str] + List of email addresses to receive notifications. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail.Profile.Conf' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'profile_id': profile_id, + 'template_id': template_id, + 'mail': json.dumps(mail) + } + return self.request_data(api_name, api_path, req_param) + + def delete_mail_profile(self, profile_id: int) -> dict: + """ + Delete a mail profile for notifications. + + Parameters + ---------- + profile_id : int + ID of the profile to delete. Use `get_mail_config` to get existing profiles. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Mail.Profile.Conf' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'delete', + 'profile_id': profile_id + } + return self.request_data(api_name, api_path, req_param) + + def create_filter_rule(self, template_name: str, settings: list[dict]) -> dict: + """ + Create a new notification filter rule template. + + Parameters + ---------- + template_name : str + The name of the filter template. + settings : list of dict + List of filter settings, e.g.: + [ + {"tag": "AutoBlockAdd", "enabled": False}, + {"tag": "AutoBlockDatabaseRulesWarning", "enabled": True}, + ... + ] + + Returns + ------- + dict + template ID. + + Examples + -------- + ```json + { + "data": { + "template_id": 2 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.FilterSettings.Template' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'create', + 'template_name': template_name, + 'settings': json.dumps(settings) + } + return self.request_data(api_name, api_path, req_param) + + def edit_filter_rule(self, template_id: int, template_name: str, settings: list[dict]) -> dict: + """ + Edit an existing notification filter rule template. + + Parameters + ---------- + template_id : int + ID of the filter template to edit. Use `list_filter_template` to get existing templates. + template_name : str + The name of the filter template. + settings : list of dict + List of filter settings, e.g.: + [ + {"tag": "AutoBlockAdd", "enabled": False}, + {"tag": "AutoBlockDatabaseRulesWarning", "enabled": True}, + ... + ] + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.FilterSettings.Template' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'set', + 'template_id': template_id, + 'template_name': template_name, + 'settings': json.dumps(settings) + } + return self.request_data(api_name, api_path, req_param) + + def delete_filter_rule(self, template_id: int) -> dict: + """ + Delete a notification filter rule template. + + Parameters + ---------- + template_id : int + ID of the filter template to delete. Use `list_filter_template` to get existing templates. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.FilterSettings.Template' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'delete', + 'template_id': template_id + } + return self.request_data(api_name, api_path, req_param) + + def list_push_service(self) -> dict: + """ + List available push notification services. + + Returns + ------- + dict + Available push notification services. + + Examples + -------- + ```json + { + "data": { + "count": 1, + "list": [ + { + "app_version": "2.5.4-468", + "device_name": "IN2013", + "firmware_version": "13", + "profile_id": 5, + "target_id": 61451444, + "template_id": 2 + } + ], + "success": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Push.Mobile' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def get_push_service_auth_token(self) -> dict: + """ + Get authentication token for push notification services. + + Returns + ------- + dict + Authentication token details. + + Examples + -------- + ```json + { + "data": { + "oauth_id": xxxxxxxxxxxxxxxxxxx, + "pushbrowser_server": "https://notification.synology.com/web/", + "register_token": "YOUR_REGISTER_TOKEN" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Push.Mobile' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def unpair_push_service(self, target_id: int) -> dict: + """ + Unpair a push notification service. + + Parameters + ---------- + target_id : int + Target ID of the push service to unpair. Use `list_push_service` to get existing services. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Push.Mobile' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'unpair', + 'target_id_list': str(target_id) + } + return self.request_data(api_name, api_path, req_param) + + def list_webhook(self) -> dict: + """ + List configured webhooks for notifications. + + Returns + ------- + dict + Configured webhooks details. + + Examples + -------- + ```json + { + "data": { + "count": 1, + "list": [ + { + "profile_id": 6, + "target_config": { + "interval": 0, + "needssl": true, + "port": 443, + "prefix": "[SYNO-FLORENTB]", + "provider": "test", + "req_header": "", + "req_method": "get", + "req_param": "", + "sepchar": " ", + "type": "custom", + "url": "https://webhook.site/558e159f-2dd8-48a1-8afb-ee9715ef5753?text=%40%40TEXT%40%40", + "use_default_lang": true + }, + "target_id": 6, + "target_name": "test", + "target_type": "webhook", + "template_config": { + "default_enabled_rule_level": "NOTIFICATION_ERROR", + "default_type": "Critical", + "is_default": true + }, + "template_id": 3, + "template_name": "Critical" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Webhook.Provider' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'list' + } + return self.request_data(api_name, api_path, req_param) + + def _format_req_list(self, req_list): + """ + Convert a list of dicts or tuples to Synology API string format. Example: [{"name": "X-Token", "value": "abc"}, {"name": "X-Id", "value": "123"}] -> "X-Token:abc\rX-Id:123\r". + + Parameters + ---------- + req_list : list of dict + List of dicts with 'name' and 'value' keys. + + Returns + ------- + str + Formatted string for Synology API. + """ + if not req_list: + return "\r" + formatted = "".join( + f"{item['name']}:{item['value']}\r" for item in req_list) + return formatted + + def create_webhook(self, + provider: str, + url: str, + template_id: int, + req_header: list = None, + req_param: list = [ + {"name": "text", "value": "@@TEXT@@"}], + port: int = 443, + type_: str = "custom", + interval: int = 0, + req_method: str = "get", + needssl: bool = True, + use_default_lang: bool = True, + prefix: str = "", + sepchar: str = " ") -> dict: + """ + Create a new webhook provider for notifications, formatting req_header and req_param as required. + + Parameters + ---------- + provider : str + The provider name. + url : str + The webhook URL. + template_id : int + The template ID. + req_header : list of dict, optional + Example: [{"name": "X-Token", "value": "abc"}]. + req_param : list of dict, optional + Example: [{"name": "X-Token", "value": "abc"}]. + port : int, optional + The port to use (default: 443). + type_ : str, optional + The type of webhook (default: "custom"). Only "custom" is supported, TODO: Add others types. + interval : int, optional + The interval (default: 0). + req_method : str, optional + The HTTP request method (default: "get"). + needssl : bool, optional + Whether SSL is needed (default: True). + use_default_lang : bool, optional + Use default language (default: True). + prefix : str, optional + Prefix for the notification (default: ""). + sepchar : str, optional + Separator character (default: " "). + + Returns + ------- + dict + API response success. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + + api_name = 'SYNO.Core.Notification.Push.Webhook.Provider' + info = self.core_list[api_name] + api_path = info['path'] + req_param_dict = { + 'version': info['maxVersion'], + 'method': 'create', + 'type': type_, + 'port': port, + 'template_id': template_id, + 'interval': interval, + 'req_method': req_method, + 'req_header': self._format_req_list(req_header), + 'req_param': self._format_req_list(req_param), + 'needssl': needssl, + 'provider': provider, + 'use_default_lang': use_default_lang, + 'prefix': prefix, + 'sepchar': sepchar, + 'url': url + } + + return self.request_data(api_name, api_path, req_param_dict) + + def edit_webhook(self, + profile_id: int, + provider: str, + url: str, + template_id: int, + req_header: list = None, + req_param: list = None, + port: int = 443, + type_: str = "custom", + interval: int = 0, + req_method: str = "get", + needssl: bool = True, + use_default_lang: bool = True, + prefix: str = "", + sepchar: str = " ") -> dict: + """ + Update (set) a webhook provider for notifications, formatting req_header and req_param as required. + + Parameters + ---------- + profile_id : int + The profile ID of the webhook provider. + provider : str + The provider name. + url : str + The webhook URL. + template_id : int + The template ID. + req_header : list of dict, optional + Example: [{"name": "X-Token", "value": "abc"}] + req_param : list of dict, optional + Example: [{"name": "foo", "value": "bar"}] + port : int, optional + The port to use (default: 443). + type_ : str, optional + The type of webhook (default: "custom"). Only "custom" is supported, TODO: Add others types. + interval : int, optional + The interval (default: 0). + req_method : str, optional + The HTTP request method (default: "get"). + needssl : bool, optional + Whether SSL is needed (default: True). + use_default_lang : bool, optional + Use default language (default: True). + prefix : str, optional + Prefix for the notification (default: ""). + sepchar : str, optional + Separator character (default: " "). + + Returns + ------- + dict + API response. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Push.Webhook.Provider' + info = self.core_list[api_name] + api_path = info['path'] + req_param_dict = { + 'version': info['maxVersion'], + 'method': 'set', + 'profile_id': profile_id, + 'type': type_, + 'port': port, + 'template_id': template_id, + 'interval': interval, + 'req_method': req_method, + 'req_header': self._format_req_list(req_header), + 'req_param': self._format_req_list(req_param), + 'needssl': needssl, + 'provider': provider, + 'use_default_lang': use_default_lang, + 'prefix': prefix, + 'sepchar': sepchar, + 'url': url + } + return self.request_data(api_name, api_path, req_param_dict) + + def delete_webhook(self, profile_id: int) -> dict: + """ + Delete a webhook provider for notifications. + + Parameters + ---------- + profile_id : int + The profile ID of the webhook provider to delete. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Push.Webhook.Provider' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'delete', + 'profile_id': profile_id + } + return self.request_data(api_name, api_path, req_param) + + def get_variables(self) -> dict: + """ + Get notification variables such as company name and HTTP URL. + + Returns + ------- + dict + Notification variables including company name and HTTP URL. + + Examples + -------- + ```json + { + "data": { + "company_name": "Synology", + "http_url": "http://www.synology.com" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.Variables' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def edit_variables(self, company_name: str, http_url: str) -> dict: + """ + Edit notification variables such as company name and HTTP URL. + + Parameters + ---------- + company_name : str + The company name to set. + http_url : str + The HTTP URL to set. + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + # If http_url is not empty, verify it's a valid URL + if http_url and not (http_url.startswith("http://") or http_url.startswith("https://")): + raise ValueError( + "http_url must start with 'http://' or 'https://'") + + api_name = 'SYNO.Core.Notification.Advance.Variables' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'company_name': company_name, + 'http_url': http_url + } + return self.request_data(api_name, api_path, req_param) + + def get_event_message(self, event_tag: str) -> dict: + """ +Get the subject and message for a specific event tag. + + Parameters + ---------- + event_tag : str + The event tag to retrieve (e.g., "ActiveBackupOffice365_restore_warning"). + + Returns + ------- + dict + API response containing the subject and message for the specified event tag. + + Examples + -------- + ```json + { + "data": { + "content": "", + "default_content": "Les données [%SERVICENAME%] du compte [%SRCUSERNAME%] ont été partiellement restaurées sur le compte [%DESTUSERNAME%] par [%TRIGGER%] (succès : %SUCCESSNUM% ; avertissement : %WARNINGNUM%).\nHeure de début : %STARTTIME%\nHeure de fin : %ENDTIME%\nConnectez-vous à la console d'administration d'Active Backup for Microsoft 365 pour plus d'informations, puis réessayez plus tard.\n\nDe %HOSTNAME%", + "default_subject": "%PACKAGENAME% - Les données de sauvegarde sur [%HOSTNAME%] ont été partiellement restaurées", + "subject": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.CustomizedData' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get', + 'event_tag': event_tag + } + return self.request_data(api_name, api_path, req_param) + + def edit_event_message(self, event_tag: str, subject: str, message: str) -> dict: + """ + Edit the subject and message for a specific event tag. + + Parameters + ---------- + event_tag : str + The event tag to edit (e.g., "ActiveBackupOffice365_restore_warning"). + subject : str + The subject template for the event. + message : str + The message template for the event. Must be a valid html
...
with text in it. + E.g., "
Les données [%SERVICENAME%] du compte [%SRCUSERNAME%] ont été partiellement restaurées sur le compte [%DESTUSERNAME%] par [%TRIGGER%] (succès : %SUCCESSNUM% ; avertissement : %WARNINGNUM%).
Heure de début : %STARTTIME%
Heure de fin : %ENDTIME%
Connectez-vous à la console d'administration d'Active Backup for Microsoft 365 pour plus d'informations, puis réessayez plus tard.

De %HOSTNAME%
". + + Returns + ------- + dict + API response success status. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Notification.Advance.CustomizedData' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'event_tag': event_tag, + 'subject': subject, + 'message': message + } + return self.request_data(api_name, api_path, req_param) From bdb0746df11a7fccbd930390b318abeab45b7562 Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 14 Sep 2025 23:10:50 +0200 Subject: [PATCH 085/126] Fix wrong api name Fix unused import --- synology_api/DSM/ControlPanel/Notifications.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/synology_api/DSM/ControlPanel/Notifications.py b/synology_api/DSM/ControlPanel/Notifications.py index 2bd75748..46fc1f66 100644 --- a/synology_api/DSM/ControlPanel/Notifications.py +++ b/synology_api/DSM/ControlPanel/Notifications.py @@ -3,7 +3,6 @@ """ from synology_api import base_api import json -import requests class Notifications(base_api.BaseApi): @@ -827,7 +826,7 @@ def list_webhook(self) -> dict: } ``` """ - api_name = 'SYNO.Core.Notification.Webhook.Provider' + api_name = 'SYNO.Core.Notification.Push.Webhook.Provider' info = self.core_list[api_name] api_path = info['path'] req_param = { From 33d7a87f7b740dadcebbb51d57fbd152e3938670 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 15:10:42 +0000 Subject: [PATCH 086/126] chore(deps): bump the python-packages group with 2 updates Bumps the python-packages group with 2 updates: [requests](https://github.com/psf/requests) and [treelib](https://github.com/caesar0301/treelib). Updates `requests` from 2.32.4 to 2.32.5 - [Release notes](https://github.com/psf/requests/releases) - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md) - [Commits](https://github.com/psf/requests/compare/v2.32.4...v2.32.5) Updates `treelib` from 1.7.1 to 1.8.0 - [Release notes](https://github.com/caesar0301/treelib/releases) - [Changelog](https://github.com/caesar0301/treelib/blob/master/HISTORY) - [Commits](https://github.com/caesar0301/treelib/compare/v1.7.1...v1.8.0) --- updated-dependencies: - dependency-name: requests dependency-version: 2.32.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages - dependency-name: treelib dependency-version: 1.8.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0b9d0efe..89610a3c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ setuptools==80.9.0 -requests==2.32.4 +requests==2.32.5 urllib3==2.5.0 requests-toolbelt==1.0.0 tqdm==4.67.1 psutil==7.0.0 docstring-extractor==0.4.0 -treelib==1.7.1 +treelib==1.8.0 PyYAML==6.0.2 cffi==2.0.0 cryptography==45.0.7 From b6239be8a0e4f93b5032536680a296c7da4c1e2b Mon Sep 17 00:00:00 2001 From: fboissadier Date: Mon, 15 Sep 2025 22:24:13 +0200 Subject: [PATCH 087/126] Implementation of RegionalOptions --- .../DSM/ControlPanel/RegionalOptions.py | 377 +++++++++++++++++- 1 file changed, 375 insertions(+), 2 deletions(-) diff --git a/synology_api/DSM/ControlPanel/RegionalOptions.py b/synology_api/DSM/ControlPanel/RegionalOptions.py index 9f5e24b4..104c4b9d 100644 --- a/synology_api/DSM/ControlPanel/RegionalOptions.py +++ b/synology_api/DSM/ControlPanel/RegionalOptions.py @@ -2,10 +2,383 @@ Regional options class for Synology DSM. """ from synology_api import base_api +import enum + + +class LanguageEnum(enum.Enum): + """ + Enum for available languages in Synology DSM. + """ + ENGLISH = "enu" + FRENCH = "fre" + GERMAN = "ger" + GREEK = "gre" + HEBREW = "heb" + THAI = "tha" + ITALIAN = "ita" + SPANISH = "spn" + TRADITIONAL_CHINESE = "cht" + SIMPLIFIED_CHINESE = "chs" + JAPANESE = "jpn" + KOREAN = "krn" + PORTUGUESE_BRAZIL = "ptb" + RUSSIAN = "rus" + DANISH = "dan" + NORWEGIAN = "nor" + SWEDISH = "sve" + DUTCH = "nld" + POLISH = "plk" + PORTUGUESE_GALICIAN = "ptg" + HUNGARIAN = "hun" + TURKISH = "trk" + CZECH = "csy" + ARABIC = "ara" + DEFAULT = "def" class RegionalOptions(base_api.BaseApi): """ - Regional options class for Synology DSM. +Regional options class for Synology DSM. """ - pass + + def get_time_info(self) -> dict: + """ +Get Date & Time information, Time Zone and Time Settings. + + Returns + ------- + dict + Date & Time information, Time Zone and Time Settings. + + Examples + -------- + ```json + { + "data": { + "date": "2025/9/15", + "date_format": "d/m/Y", + "enable_ntp": "ntp", + "hour": 20, + "minute": 48, + "now": "Mon Sep 15 20:48:00 2025\n", + "second": 0, + "server": "time.google.com", + "time_format": "H:i", + "timestamp": 1757962080, + "timezone": "Amsterdam" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.NTP' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_language_info(self) -> dict: + """ + Get Language information. + + Returns + ------- + dict + Language information. + + Examples + -------- + ```json + { + "data": { + "codepage": "fre", + "language": "def", + "maillang": "fre" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.Language' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_ntp_service_info(self) -> dict: + """ + Get NTP Service information. + + Returns + ------- + dict + NTP Service information. + + Examples + -------- + ```json + { + "data": { + "enable": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.NTP.Server' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_ntp_service_status(self) -> dict: + """ + Get NTP Service status. + + Returns + ------- + dict + NTP Service status. + + Examples + -------- + ```json + { + "data": { + "ntp_status": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.NTP' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'status' + } + return self.request_data(api_name, api_path, req_param) + + def list_timezone(self) -> dict: + """ + List available time zones. + + Returns + ------- + dict + Available time zones. + + Examples + -------- + ```json + { + "data": { + "zonedata": [ + { + "display": "(GMT-11:00) Samoa Standard Time; Midway Is.", + "offset": -39600, + "value": "Midway" + }, + { + "display": "(GMT-10:00) Hawaii Standard Time", + "offset": -36000, + "value": "Hawaii" + }, + { + "display": "(GMT-09:00) Alaska Standard Time", + "offset": -32400, + "value": "Alaska" + }, + { + "display": "(GMT-08:00) Pacific Time (US & Canada); Tijuana", + "offset": -28800, + "value": "Pacific" + }, + { + "display": "(GMT-07:00) Arizona", + "offset": -25200, + "value": "Arizona" + }, + { + "display": "(GMT-07:00) Mountain Time (US & Canada)", + "offset": -25200, + "value": "Mountain" + }, + { + "display": "(GMT-06:00) Central Time (US & Canada)", + "offset": -21600, + "value": "Central" + }, + { + "display": "(GMT-06:00) Chihuahua, Mazatlan", + "offset": -21600, + "value": "Chihuahua" + }, + { + "display": "(GMT-06:00) Central America Standard Time; Guatemala", + "offset": -21600, + "value": "Guatemala" + } + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.NTP' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['minVersion'], + 'method': 'listzone' + } + return self.request_data(api_name, api_path, req_param) + + def set_time_info(self, date_format: str, time_format: str, timezone: str, enable_ntp: str, server: str, date: str, hour: int, minute: int, second: int, change_time: bool = False) -> dict: + """ + Set Date & Time information, Time Zone and Time Settings. + + Parameters + ---------- + date_format : str + Date format, known formats are `YYYY-MM-dd`, `YYYY/MM/dd`, `YYYY.MM.dd`, `dd-MM-YYYY`, `dd/MM/YYYY`, `dd.MM.YYYY`, `MM-dd-YYYY`, `MM/dd/YYYY`, `MM.dd.YYYY`. + time_format : str + Time format, known formats are `H:i`, `h:i A`. + timezone : str + Time zone, can be get from `list_timezone` field "value". + enable_ntp : str + NTP setting ('ntp' to enable, 'manual' to disable). + server : str + NTP server address, only if `enable_ntp` is set to 'ntp'. + date : str + Date in 'YYYY/MM/DD' format, only if `enable_ntp` is set to 'manual'. + hour : int + Hour (0-23), only if `enable_ntp` is set to 'manual'. + minute : int + Minute (0-59), only if `enable_ntp` is set to 'manual'. + second : int + Second (0-59), only if `enable_ntp` is set to 'manual'. + change_time : bool, optional + Whether to change the time immediately, defaults to False. + + Returns + ------- + dict + Response from the API. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.NTP' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'date_format': date_format, + 'time_format': time_format, + 'timezone': timezone, + 'enable_ntp': enable_ntp, + 'change_time': change_time + } + if enable_ntp == 'manual': + req_param.update({ + 'date': date, + 'hour': hour, + 'minute': minute, + 'second': second + }) + elif enable_ntp == 'ntp': + # server is required in this case + req_param.update({ + 'server': server + }) + return self.request_data(api_name, api_path, req_param) + + def list_language(self) -> LanguageEnum: + """ + List available languages. + + Returns + ------- + LanguageEnum + Available languages. + """ + return LanguageEnum + + def set_language_info(self, language: LanguageEnum, maillang: LanguageEnum, codepage: LanguageEnum) -> dict: + """ + Set Language information. + + Parameters + ---------- + language : LanguageEnum + Display language, you can use the `DEFAULT` from the LanguageEnum. + maillang : LanguageEnum + Notification language, you cannot use `DEFAULT` from the LanguageEnum. + codepage : LanguageEnum + Codepage, you cannot use `DEFAULT` from the LanguageEnum. + + Returns + ------- + dict + Response from the API. + """ + api_name = 'SYNO.Core.Region.Language' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'language': language.value, + 'maillang': maillang.value, + 'codepage': codepage.value + } + return self.request_data(api_name, api_path, req_param) + + def set_ntp_service_info(self, enable: bool) -> dict: + """ + Set NTP Service information. + + Parameters + ---------- + enable : bool + Whether to enable the NTP service. + + Returns + ------- + dict + Response from the API. + + Examples + -------- + ```json + { + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Region.NTP.Server' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'set', + 'enable': enable + } + return self.request_data(api_name, api_path, req_param) From 95279a0142ba9fcc31b8d2e3a2cad7dcb8c73277 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Sep 2025 13:06:57 +0000 Subject: [PATCH 088/126] chore(deps): bump the python-packages group across 1 directory with 2 updates Bumps the python-packages group with 2 updates in the / directory: [psutil](https://github.com/giampaolo/psutil) and [cryptography](https://github.com/pyca/cryptography). Updates `psutil` from 7.0.0 to 7.1.0 - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-7.0.0...release-7.1.0) Updates `cryptography` from 45.0.7 to 46.0.1 - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/45.0.7...46.0.1) --- updated-dependencies: - dependency-name: psutil dependency-version: 7.1.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: python-packages - dependency-name: cryptography dependency-version: 46.0.1 dependency-type: direct:production update-type: version-update:semver-major dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 89610a3c..41eac1ba 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,11 +3,11 @@ requests==2.32.5 urllib3==2.5.0 requests-toolbelt==1.0.0 tqdm==4.67.1 -psutil==7.0.0 +psutil==7.1.0 docstring-extractor==0.4.0 treelib==1.8.0 PyYAML==6.0.2 cffi==2.0.0 -cryptography==45.0.7 +cryptography==46.0.1 noiseprotocol==0.3.1 pycparser==2.23 From e045c2fc8d52cbdd92f8fafc8adcb67cf2ac71aa Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 21 Sep 2025 03:21:58 +0200 Subject: [PATCH 089/126] Implementation of getters for Security tab --- synology_api/DSM/ControlPanel/Security.py | 464 +++++++++++++++++++++- 1 file changed, 463 insertions(+), 1 deletion(-) diff --git a/synology_api/DSM/ControlPanel/Security.py b/synology_api/DSM/ControlPanel/Security.py index 23c38dbd..39a49005 100644 --- a/synology_api/DSM/ControlPanel/Security.py +++ b/synology_api/DSM/ControlPanel/Security.py @@ -2,10 +2,472 @@ Security class for Synology DSM. """ from synology_api import base_api +import json class Security(base_api.BaseApi): """ Security class for Synology DSM. """ - pass + + def get_security_settings(self) -> dict: + """ + Get security settings, Security tab: General, Login Settings. + + Returns + ------- + dict + Security settings information. + + Examples + -------- + ```json + { + "data": { + "allow_stay_signed_in_option": true, + "allow_trust_device_2fa_option": true, + "csp_header_option": true, + "enable_csrf_protection": true, + "restart_clean_session": true, + "skip_ip_checking": true, + "timeout": 15 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Security.DSM' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_dsm_embedded_settings(self) -> dict: + """ + Get DSM embedded settings. + + Returns + ------- + dict + DSM embedded settings information. + + Examples + -------- + ```json + { + "data": { + "enable_block": true, + "whitelist": [ + "find.synology.com/", + "gofile.me/" + ] + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Security.DSM.Embed' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_2fa_settings(self) -> dict: + """ + Get 2-factor authentication settings, Account tab: 2-factor authentication. + + Returns + ------- + dict + 2-factor authentication settings information. + + Examples + -------- + ```json + { + "data": { + "otp_enforce_option": "custom" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.OTP.EnforcePolicy' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_amfa_settings(self) -> dict: + """ + Get AMFA (Adaptive Multi-Factor Authentication) settings, Account tab: Adaptive multi-factor authentication. + + Returns + ------- + dict + AMFA settings information. + + Examples + -------- + ```json + { + "data": { + "group_list": "", + "type": "admin", + "user_list": "" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.SecureSignIn.AMFA.Policy' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_smartblock_settings(self) -> dict: + """ + Get Smart Block settings, Login Settings tab: Smart Block. + + Returns + ------- + dict + Smart Block settings information. + + Examples + -------- + ```json + { + "data": { + "enabled": true, + "trust_lock": 30, + "trust_minute": 1, + "trust_try": 10, + "untrust_lock": 30, + "untrust_minute": 1, + "untrust_try": 5 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.SmartBlock' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_firewall_status(self) -> dict: + """ + Get firewall status, Firewall tab: Enable firewall. + + Returns + ------- + dict + Firewall status information. + + Examples + -------- + ```json + { + "data": { + "enable_firewall": true, + "profile_name": "default" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Security.Firewall' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_firewall_notifications_settings(self) -> dict: + """ + Get firewall notifications settings, Firewall tab: Enable firewall notifications. + + Returns + ------- + dict + Firewall notifications settings information. + + Examples + -------- + ```json + { + "data": { + "enable_port_check": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Security.Firewall.Conf' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_auto_block_settings(self) -> dict: + """ + Get auto block settings, Auto Block tab: Enable auto block. + + Returns + ------- + dict + Auto block settings information. + + Examples + -------- + ```json + { + "data": { + "attempts": 10, + "enable": true, + "expire_day": 0, + "within_mins": 5 + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Security.AutoBlock' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_dos_settings(self, adapter_list: list[str]) -> dict: + """ + Get DoS settings, Protect tab: Denial-of-Service (DoS) Protection. + + Parameters + ---------- + adapter_list : list[str] + List of network interfaces to get DoS settings for. Can be obtained via `Network.get_network_interface()` and get `ifname` from the response. + + Returns + ------- + dict + DoS settings information. + + Examples + -------- + ```json + { + "data": [ + { + "adapter": "ovs_eth0", + "dos_protect_enable": true + }, + { + "adapter": "ovs_eth1", + "dos_protect_enable": false + }, + { + "adapter": "pppoe", + "dos_protect_enable": false + } + ], + "success": true + } + ``` + """ + configs = [{"adapter": adapter} for adapter in adapter_list] + + api_name = 'SYNO.Core.Security.DoS' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get', + 'configs': json.dumps(configs) + } + + return self.request_data(api_name, api_path, req_param) + + def get_http_compression_settings(self) -> dict: + """ + Get HTTP compression settings, Advanced tab: HTTP compression. + + Returns + ------- + dict + HTTP compression settings information. + + Examples + -------- + ```json + { + "data": { + "http_compression": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Web.Security.HTTPCompression' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_tls_profile_settings(self) -> dict: + """ + Get TLS profile settings, Advanced tab: TLS / SSL Profile level. + + Returns + ------- + dict + TLS profile settings information. + + Examples + -------- + ```json + { + "data": { + "default-level": 1, + "services": { + "LogCenter": { + "current-level": 0, + "display-name": "Log Receiving", + "display-name-i18n": "helptoc:logcenter_server" + }, + "WebStation_4437801d-caf5-45d6-afbd-99fc2f9f91dc": { + "current-level": 0, + "display-name": "*:8080" + }, + "dsm": { + "current-level": 0, + "display-name": "DSM Desktop Service", + "display-name-i18n": "common:web_desktop" + }, + "openldap": { + "current-level": 0, + "display-name": "LDAP Server" + }, + "smbftpd": { + "current-level": 0, + "display-name": "FTPS", + "display-name-i18n": "tree:leaf_ftpes" + }, + "system_quickconnect": { + "current-level": 0, + "display-name": "QuickConnect", + "display-name-i18n": "helptoc:quickconnect" + } + } + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Web.Security.TLSProfile' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_spectre_meldown_settings(self) -> dict: + """ + Get Spectre/Meltdown settings, Advanced tab: Spectre/Meltdown Protection. + + Returns + ------- + dict + Spectre/Meltdown settings information. + + Examples + -------- + ```json + { + "data": { + "enable_spectre_meltdown_mitigation": true + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Core.Hardware.SpectreMeltdown' + info = self.core_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) + + def get_kmip_settings(self) -> dict: + """ + Get KMIP settings, KMIP tab. + + Returns + ------- + dict + KMIP settings information. + + Examples + -------- + ```json + { + "data": { + "client_cert_info": null, + "client_enable": false, + "conn_success": false, + "conn_time": "", + "kmip_conn_server_desc": "", + "kmip_conn_server_port": "5696", + "kmip_db_loc": "", + "kmip_enabled": "", + "kmip_mode": "", + "kmip_server": "", + "kmip_server_port": "5696", + "server_cert_info": null, + "server_enable": false, + "support_kmip": "yes" + }, + "success": true + } + ``` + """ + api_name = 'SYNO.Storage.CGI.KMIP' + info = self.gen_list[api_name] + api_path = info['path'] + req_param = { + 'version': info['maxVersion'], + 'method': 'get' + } + return self.request_data(api_name, api_path, req_param) From 13897cb9ee906621af310fc477d7c4ad5de6b038 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 13:07:45 +0000 Subject: [PATCH 090/126] chore(deps): bump pyyaml in the python-packages group Bumps the python-packages group with 1 update: [pyyaml](https://github.com/yaml/pyyaml). Updates `pyyaml` from 6.0.2 to 6.0.3 - [Release notes](https://github.com/yaml/pyyaml/releases) - [Changelog](https://github.com/yaml/pyyaml/blob/6.0.3/CHANGES) - [Commits](https://github.com/yaml/pyyaml/compare/6.0.2...6.0.3) --- updated-dependencies: - dependency-name: pyyaml dependency-version: 6.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 41eac1ba..7a3310bb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ tqdm==4.67.1 psutil==7.1.0 docstring-extractor==0.4.0 treelib==1.8.0 -PyYAML==6.0.2 +PyYAML==6.0.3 cffi==2.0.0 cryptography==46.0.1 noiseprotocol==0.3.1 From 97e33567ce0a1a0c6c32b71c619cc9401f4c869c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Oct 2025 13:08:14 +0000 Subject: [PATCH 091/126] chore(deps): bump cryptography in the python-packages group Bumps the python-packages group with 1 update: [cryptography](https://github.com/pyca/cryptography). Updates `cryptography` from 46.0.1 to 46.0.2 - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/46.0.1...46.0.2) --- updated-dependencies: - dependency-name: cryptography dependency-version: 46.0.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 7a3310bb..e9d9cde4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,6 @@ docstring-extractor==0.4.0 treelib==1.8.0 PyYAML==6.0.3 cffi==2.0.0 -cryptography==46.0.1 +cryptography==46.0.2 noiseprotocol==0.3.1 pycparser==2.23 From 2d91d94cfb0c91580d06d4c9dd8e5c381b12ecac Mon Sep 17 00:00:00 2001 From: joeperpetua Date: Wed, 1 Oct 2025 20:04:01 +0200 Subject: [PATCH 092/126] feat: add get_task_list & download_task_list --- synology_api/downloadstation.py | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 6d56e20e..a977a4ab 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -385,6 +385,55 @@ def tasks_source(self, task_id) -> bytes: return self.request_data(api_name, api_path, req_param, response_json=False).content + def get_task_list(self, list_id: str) -> dict[str, any]: + """Get info from a task list containing the files to be downloaded. This is to be used after creating a task, and before starting the download. + + Parameters + ---------- + list_id : str + List ID returned by create_task. + + Returns + ------- + dict[str, any] + A dictionary containing a task list information. + + Example + ---------- + ```json + { + "data" : { + "files" : [ + { + "index" : 0, + "name" : "Pulp.Fiction.1994.2160p.4K.BluRay.x265.10bit.AAC5.1-[YTS.MX].mkv", + "size" : 2391069024 + }, + { + "index" : 1, + "name" : "YTSProxies.com.txt", + "size" : 604 + }, + { + "index" : 2, + "name" : "www.YTS.MX.jpg", + "size" : 53226 + } + ], + "size" : 7835426779, + "title" : "Pulp Fiction (1994) [2160p] [4K] [BluRay] [5.1] [YTS.MX]", + "type" : "bt" + }, + } + ``` + """ + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task.List' + info = self.download_list[api_name] + api_path = info['path'] + req_param = {'version': info['maxVersion'], 'method': 'get', 'list_id': list_id} + + return self.request_data(api_name, api_path, req_param) + def create_task(self, url, destination) -> dict[str, object] | str: """ Create a new download task. @@ -512,6 +561,57 @@ def edit_task(self, task_id: str, destination: str = 'sharedfolder') -> dict[str param['id'] = ",".join(task_id) return self.request_data(api_name, api_path, param) + + def download_task_list( + self, + list_id: str, + file_indexes: list[int], + destination: str, + create_subfolder: bool = True + ) -> dict[str, object] | str: + """ + Download files from a task list. + + Parameters + ---------- + list_id : str + Task list ID. + file_indexes : list[int] + List of file indexes to download. + For example, if `get_task_list()` returns `files: [{index: 0, name: "file1.txt"}, {index: 1, name: "file2.txt"}]`, then `file_indexes = [1]` will download only file2.txt. + destination : str + Download destination, e.g. 'sharedfolder/subfolder' + create_subfolder : bool, optional + Create subfolder. Defaults to `True` + + Returns + ------- + dict[str, object] or str + A dictionary containing the task_id for the started download task. + + Example + ---------- + ```json + { + 'data': { + 'task_id': 'username/SYNODLTaskListDownload1759340338C7C39ABA' + } + } + ``` + """ + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task.List.Polling' + info = self.download_list[api_name] + api_path = info['path'] + param = { + 'version': info['maxVersion'], + 'method': 'download', + 'list_id': list_id, + 'file_indexes': ",".join(map(str, file_indexes)), + 'destination': destination, + 'create_subfolder': create_subfolder + } + + return self.request_data(api_name, api_path, param) def get_statistic_info(self) -> dict[str, object] | str: """ From 89ed4cd64aebf5d15a4f7f03e67d226f7da80b48 Mon Sep 17 00:00:00 2001 From: joeperpetua Date: Wed, 1 Oct 2025 20:36:37 +0200 Subject: [PATCH 093/126] chore: fix docstrings --- synology_api/downloadstation.py | 89 +++++++++++++++++---------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index a977a4ab..8cfb7a40 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -386,46 +386,49 @@ def tasks_source(self, task_id) -> bytes: return self.request_data(api_name, api_path, req_param, response_json=False).content def get_task_list(self, list_id: str) -> dict[str, any]: - """Get info from a task list containing the files to be downloaded. This is to be used after creating a task, and before starting the download. - - Parameters - ---------- - list_id : str - List ID returned by create_task. - - Returns - ------- - dict[str, any] - A dictionary containing a task list information. - - Example - ---------- - ```json - { - "data" : { - "files" : [ - { - "index" : 0, - "name" : "Pulp.Fiction.1994.2160p.4K.BluRay.x265.10bit.AAC5.1-[YTS.MX].mkv", - "size" : 2391069024 - }, - { - "index" : 1, - "name" : "YTSProxies.com.txt", - "size" : 604 - }, - { - "index" : 2, - "name" : "www.YTS.MX.jpg", - "size" : 53226 - } - ], - "size" : 7835426779, - "title" : "Pulp Fiction (1994) [2160p] [4K] [BluRay] [5.1] [YTS.MX]", - "type" : "bt" - }, - } - ``` + """ + Get info from a task list containing the files to be downloaded. + + This is to be used after creating a task, and before starting the download. + + Parameters + ---------- + list_id : str + List ID returned by create_task. + + Returns + ------- + dict[str, any] + A dictionary containing a task list information. + + Examples + -------- + ```json + { + "data" : { + "files" : [ + { + "index" : 0, + "name" : "Pulp.Fiction.1994.2160p.4K.BluRay.x265.10bit.AAC5.1-[YTS.MX].mkv", + "size" : 2391069024 + }, + { + "index" : 1, + "name" : "YTSProxies.com.txt", + "size" : 604 + }, + { + "index" : 2, + "name" : "www.YTS.MX.jpg", + "size" : 53226 + } + ], + "size" : 7835426779, + "title" : "Pulp Fiction (1994) [2160p] [4K] [BluRay] [5.1] [YTS.MX]", + "type" : "bt" + }, + } + ``` """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task.List' info = self.download_list[api_name] @@ -577,7 +580,7 @@ def download_task_list( list_id : str Task list ID. file_indexes : list[int] - List of file indexes to download. + List of file indexes to download. For example, if `get_task_list()` returns `files: [{index: 0, name: "file1.txt"}, {index: 1, name: "file2.txt"}]`, then `file_indexes = [1]` will download only file2.txt. destination : str Download destination, e.g. 'sharedfolder/subfolder' @@ -589,8 +592,8 @@ def download_task_list( dict[str, object] or str A dictionary containing the task_id for the started download task. - Example - ---------- + Examples + -------- ```json { 'data': { From 01261634ddba5e2ead35c9901bbb7e68cff6d545 Mon Sep 17 00:00:00 2001 From: joeperpetua Date: Wed, 1 Oct 2025 20:39:01 +0200 Subject: [PATCH 094/126] chore: run docs parser Lots of changes, I guess something changed on the parser. Most changes from what I could see are indentation and whitespaces. --- documentation/docs/apis/classes/abm.md | 990 +- .../docs/apis/classes/audiostation.md | 154 +- documentation/docs/apis/classes/cloud_sync.md | 957 +- .../docs/apis/classes/core_active_backup.md | 1095 +- .../docs/apis/classes/core_backup.md | 287 +- .../docs/apis/classes/core_certificate.md | 139 +- documentation/docs/apis/classes/core_group.md | 176 +- .../docs/apis/classes/core_package.md | 391 +- documentation/docs/apis/classes/core_share.md | 177 +- .../docs/apis/classes/core_sys_info.md | 1619 ++- documentation/docs/apis/classes/core_user.md | 80 +- .../docs/apis/classes/dhcp_server.md | 128 + .../docs/apis/classes/directory_server.md | 278 +- documentation/docs/apis/classes/docker_api.md | 1831 ++- .../docs/apis/classes/downloadstation.md | 623 +- .../docs/apis/classes/drive_admin_console.md | 246 + .../docs/apis/classes/event_scheduler.md | 210 +- .../docs/apis/classes/filestation.md | 1294 +- documentation/docs/apis/classes/log_center.md | 107 + .../docs/apis/classes/notestation.md | 127 + documentation/docs/apis/classes/oauth.md | 71 + documentation/docs/apis/classes/photos.md | 481 +- .../docs/apis/classes/security_advisor.md | 91 + documentation/docs/apis/classes/snapshot.md | 130 +- .../docs/apis/classes/surveillancestation.md | 10139 +++++++++++++++- .../docs/apis/classes/task_scheduler.md | 747 +- .../docs/apis/classes/universal_search.md | 22 + documentation/docs/apis/classes/usb_copy.md | 160 +- .../docs/apis/classes/virtualization.md | 370 +- documentation/docs/apis/classes/vpn.md | 186 + documentation/docs/apis/readme.md | 10 +- 31 files changed, 19022 insertions(+), 4294 deletions(-) diff --git a/documentation/docs/apis/classes/abm.md b/documentation/docs/apis/classes/abm.md index e5f0b4af..d9b4812e 100644 --- a/documentation/docs/apis/classes/abm.md +++ b/documentation/docs/apis/classes/abm.md @@ -9,27 +9,27 @@ title: ✅ ActiveBackupMicrosoft # ActiveBackupMicrosoft ## Overview -Active Backup for Microsoft 365 Implementation. - -### Supported methods - -- **Getters** : - - Get all tasks info - - Get task settings - - Get task logs - - Get package logs - - Get worker settings - -- **Setters** : - - Set worker settings - - Set task schedule policy - - Set task retention policy - -- **Actions** : - - Run backup - - Cancel backup - - Delete task - - Relink task +Active Backup for Microsoft 365 Implementation. + + ### Supported methods + + - **Getters** : + - Get all tasks info + - Get task settings + - Get task logs + - Get package logs + - Get worker settings + + - **Setters** : + - Set worker settings + - Set task schedule policy + - Set task retention policy + + - **Actions** : + - Run backup + - Cancel backup + - Delete task + - Relink task ## Methods ### `get_tasks` Retrieve all tasks. @@ -49,202 +49,202 @@ A dictionary containing the list of tasks.
Click to expand ```json -{ - "data": { - event_log: [ - { - "description": "Backup task [test] completed.", - "error_code": 0, - "last_execution_time": 1733794236, - "log_type": 0, - "task_execution_id": 1, - "task_id": 1, - "timestamp": 1733794236 - }, - ], - service_usage: [ - { - "service_type": 0, - "storage_usage": 319196921578 - }, - { - "service_type": 1, - "storage_usage": 1211160588 - }, - { - "service_type": 4, - "storage_usage": 9704366035 - }, - { - "service_type": 2, - "storage_usage": 259976 - }, - { - "service_type": 3, - "storage_usage": 2561252 - }, - { - "service_type": 5, - "storage_usage": 21544726 - }, - { - "service_type": 8, - "storage_usage": 0 - }, - { - "service_type": 6, - "storage_usage": 0 - }, - { - "service_type": 7, - "storage_usage": 0 - }, - { - "service_type": 9, - "storage_usage": 46484 - } - ], - tasks: [ - { - "archive_mail_used_storage": 9704366035, - "attention_count": 0, - "backup_policy": 1, - "calendar_used_storage": 2561252, - "contact_used_storage": 259976, - "drive_used_storage": 319196921578, - "duration": 22553, - "enable_archive_mail": 1, - "enable_calendar": 1, - "enable_contact": 1, - "enable_drive": 1, - "enable_exchange": 1, - "enable_group": 0, - "enable_group_calendar": 0, - "enable_group_mail": 0, - "enable_mail": 1, - "enable_mysite": 0, - "enable_schedule": false, - "enable_site": 1, - "enable_teams": 1, - "error_archive_mail": 0, - "error_calendar": 0, - "error_contact": 0, - "error_drive": 0, - "error_group_calendar": 0, - "error_group_mail": 0, - "error_mail": 0, - "error_site": 0, - "error_teams": 0, - "group_calendar_used_storage": 0, - "group_mail_used_storage": 0, - "job_id": 0, - "last_execution_time": 1733794235, - "mail_used_storage": 1211160588, - "mysite_used_storage": 0, - "processed_archive_mail": 1, - "processed_calendar": 1, - "processed_contact": 1, - "processed_drive": 1, - "processed_group_calendar": 0, - "processed_group_mail": 0, - "processed_mail": 1, - "processed_site": 1, - "processed_teams": 1, - "progress_list": [], - "region": 0, - "schedule": { - "date": "2025/1/26", - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "minute": 0, - "monthly_week": [], - "repeat_date": 0, - "repeat_hour": 0, - "repeat_hour_store_config": null, - "repeat_min": 0, - "repeat_min_store_config": null, - "week_day": "0,1,2,3,4,5,6" + { + "data": { + event_log: [ + { + "description": "Backup task [test] completed.", + "error_code": 0, + "last_execution_time": 1733794236, + "log_type": 0, + "task_execution_id": 1, + "task_id": 1, + "timestamp": 1733794236 }, - "schedule_id": 4, - "site_used_storage": 21544726, - "status": 1, - "status_archive_mail": 1, - "status_calendar": 1, - "status_contact": 1, - "status_drive": 1, - "status_group_calendar": 0, - "status_group_mail": 0, - "status_mail": 1, - "status_site": 1, - "status_teams": 1, - "success_count": 3, - "task_execution_id": 1, - "task_id": 1, - "task_name": "test", - "task_status": 2, - "task_status_error_code": 0, - "teams_used_storage": 46484, - "transferred_size_archive_mail": 9704366035, - "transferred_size_calendar": 2561252, - "transferred_size_contact": 259976, - "transferred_size_drive": 319196921578, - "transferred_size_group_calendar": 0, - "transferred_size_group_mail": 0, - "transferred_size_mail": 1211160588, - "transferred_size_site": 21544726, - "transferred_size_teams": 46484, - "upgrade_progress": 0, - "warning_archive_mail": 0, - "warning_calendar": 0, - "warning_contact": 0, - "warning_drive": 0, - "warning_group_calendar": 0, - "warning_group_mail": 0, - "warning_mail": 0, - "warning_site": 0, - "warning_teams": 0 - } - ], - users: [ - { - "display_name": "username", - "original_name": "username@xxxx.onmicrosoft.com", - "service_list": [ - 0, - 1, - 4, - 2, - 3 - ], - "task_name": "test", - "type": 0, - "usage_percentage": 99.99345992145251, - "usage_total": 330115269429 - }, - { - "display_name": "sharepoint site", - "original_name": "https://xxx.sharepoint.com/sites/sharepointsite", - "service_list": [], - "task_name": "test", - "type": 1, - "usage_percentage": 0.006525998326360428, - "usage_total": 21544726 - }, - { - "display_name": "test team", - "original_name": "https://teams.microsoft.com/l/team/xxxx", - "service_list": [], - "task_name": "test", - "type": 4, - "usage_percentage": 0.000014080221127088742, - "usage_total": 46484 - } - ] - }, - "success": true -} -``` + ], + service_usage: [ + { + "service_type": 0, + "storage_usage": 319196921578 + }, + { + "service_type": 1, + "storage_usage": 1211160588 + }, + { + "service_type": 4, + "storage_usage": 9704366035 + }, + { + "service_type": 2, + "storage_usage": 259976 + }, + { + "service_type": 3, + "storage_usage": 2561252 + }, + { + "service_type": 5, + "storage_usage": 21544726 + }, + { + "service_type": 8, + "storage_usage": 0 + }, + { + "service_type": 6, + "storage_usage": 0 + }, + { + "service_type": 7, + "storage_usage": 0 + }, + { + "service_type": 9, + "storage_usage": 46484 + } + ], + tasks: [ + { + "archive_mail_used_storage": 9704366035, + "attention_count": 0, + "backup_policy": 1, + "calendar_used_storage": 2561252, + "contact_used_storage": 259976, + "drive_used_storage": 319196921578, + "duration": 22553, + "enable_archive_mail": 1, + "enable_calendar": 1, + "enable_contact": 1, + "enable_drive": 1, + "enable_exchange": 1, + "enable_group": 0, + "enable_group_calendar": 0, + "enable_group_mail": 0, + "enable_mail": 1, + "enable_mysite": 0, + "enable_schedule": false, + "enable_site": 1, + "enable_teams": 1, + "error_archive_mail": 0, + "error_calendar": 0, + "error_contact": 0, + "error_drive": 0, + "error_group_calendar": 0, + "error_group_mail": 0, + "error_mail": 0, + "error_site": 0, + "error_teams": 0, + "group_calendar_used_storage": 0, + "group_mail_used_storage": 0, + "job_id": 0, + "last_execution_time": 1733794235, + "mail_used_storage": 1211160588, + "mysite_used_storage": 0, + "processed_archive_mail": 1, + "processed_calendar": 1, + "processed_contact": 1, + "processed_drive": 1, + "processed_group_calendar": 0, + "processed_group_mail": 0, + "processed_mail": 1, + "processed_site": 1, + "processed_teams": 1, + "progress_list": [], + "region": 0, + "schedule": { + "date": "2025/1/26", + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "minute": 0, + "monthly_week": [], + "repeat_date": 0, + "repeat_hour": 0, + "repeat_hour_store_config": null, + "repeat_min": 0, + "repeat_min_store_config": null, + "week_day": "0,1,2,3,4,5,6" + }, + "schedule_id": 4, + "site_used_storage": 21544726, + "status": 1, + "status_archive_mail": 1, + "status_calendar": 1, + "status_contact": 1, + "status_drive": 1, + "status_group_calendar": 0, + "status_group_mail": 0, + "status_mail": 1, + "status_site": 1, + "status_teams": 1, + "success_count": 3, + "task_execution_id": 1, + "task_id": 1, + "task_name": "test", + "task_status": 2, + "task_status_error_code": 0, + "teams_used_storage": 46484, + "transferred_size_archive_mail": 9704366035, + "transferred_size_calendar": 2561252, + "transferred_size_contact": 259976, + "transferred_size_drive": 319196921578, + "transferred_size_group_calendar": 0, + "transferred_size_group_mail": 0, + "transferred_size_mail": 1211160588, + "transferred_size_site": 21544726, + "transferred_size_teams": 46484, + "upgrade_progress": 0, + "warning_archive_mail": 0, + "warning_calendar": 0, + "warning_contact": 0, + "warning_drive": 0, + "warning_group_calendar": 0, + "warning_group_mail": 0, + "warning_mail": 0, + "warning_site": 0, + "warning_teams": 0 + } + ], + users: [ + { + "display_name": "username", + "original_name": "username@xxxx.onmicrosoft.com", + "service_list": [ + 0, + 1, + 4, + 2, + 3 + ], + "task_name": "test", + "type": 0, + "usage_percentage": 99.99345992145251, + "usage_total": 330115269429 + }, + { + "display_name": "sharepoint site", + "original_name": "https://xxx.sharepoint.com/sites/sharepointsite", + "service_list": [], + "task_name": "test", + "type": 1, + "usage_percentage": 0.006525998326360428, + "usage_total": 21544726 + }, + { + "display_name": "test team", + "original_name": "https://teams.microsoft.com/l/team/xxxx", + "service_list": [], + "task_name": "test", + "type": 4, + "usage_percentage": 0.000014080221127088742, + "usage_total": 46484 + } + ] + }, + "success": true + } + ```
@@ -280,45 +280,45 @@ A dictionary containing the list of logs.
Click to expand ```json -{ - "data": { - "logs": [ - { - "category": 0, - "description": "Backup task [test] completed.", - "error_code": 0, - "log_type": 0, - "storage_remove_id": 0, - "task_execution_id": 1, - "task_id": 1, - "timestamp": 1733794236 - }, - { - "category": 3, - "description": "[user] ran backup task [test].", - "error_code": 0, - "log_type": 0, - "storage_remove_id": 0, - "task_execution_id": 0, - "task_id": 1, - "timestamp": 1733771681 - }, - { - "category": 3, - "description": "[user] created task [test].", - "error_code": 0, - "log_type": 0, - "storage_remove_id": 0, - "task_execution_id": 0, - "task_id": 1, - "timestamp": 1733771267 - } - ], - "offset": 0 - }, - "success": true -} -``` + { + "data": { + "logs": [ + { + "category": 0, + "description": "Backup task [test] completed.", + "error_code": 0, + "log_type": 0, + "storage_remove_id": 0, + "task_execution_id": 1, + "task_id": 1, + "timestamp": 1733794236 + }, + { + "category": 3, + "description": "[user] ran backup task [test].", + "error_code": 0, + "log_type": 0, + "storage_remove_id": 0, + "task_execution_id": 0, + "task_id": 1, + "timestamp": 1733771681 + }, + { + "category": 3, + "description": "[user] created task [test].", + "error_code": 0, + "log_type": 0, + "storage_remove_id": 0, + "task_execution_id": 0, + "task_id": 1, + "timestamp": 1733771267 + } + ], + "offset": 0 + }, + "success": true + } + ```
@@ -360,39 +360,39 @@ A dictionary containing the list of logs.
Click to expand ```json -{ - "data": { - "logs": [ - { - "description": "User [username@xxxx.onmicrosoft.com]'s OneDrive data was backed up (success: 34177; warning: 0; error: 0).", - "error_code": 0, - "log_type": 0, - "task_execution_id": 1, - "task_id": 1, - "timestamp": 1733780274 - }, - { - "description": "The data of site [test site] was backed up (List: success: 6, warning: 0, error: 0; Document library: success: 13, warning: 0, error: 0; Document library item: success: 288, warning: 0, error: 0).", - "error_code": 0, - "log_type": 0, - "task_execution_id": 1, - "task_id": 1, - "timestamp": 1733771918 - }, - { - "description": "The data of team [test team] was backed up (Channel: success: 3, warning: 0, error: 0; Post: success: 18, warning: 0, error: 0).", - "error_code": 0, - "log_type": 0, - "task_execution_id": 1, - "task_id": 1, - "timestamp": 1733771786 - } - ], - "offset": 0 - }, - "success": true -} -``` + { + "data": { + "logs": [ + { + "description": "User [username@xxxx.onmicrosoft.com]'s OneDrive data was backed up (success: 34177; warning: 0; error: 0).", + "error_code": 0, + "log_type": 0, + "task_execution_id": 1, + "task_id": 1, + "timestamp": 1733780274 + }, + { + "description": "The data of site [test site] was backed up (List: success: 6, warning: 0, error: 0; Document library: success: 13, warning: 0, error: 0; Document library item: success: 288, warning: 0, error: 0).", + "error_code": 0, + "log_type": 0, + "task_execution_id": 1, + "task_id": 1, + "timestamp": 1733771918 + }, + { + "description": "The data of team [test team] was backed up (Channel: success: 3, warning: 0, error: 0; Post: success: 18, warning: 0, error: 0).", + "error_code": 0, + "log_type": 0, + "task_execution_id": 1, + "task_id": 1, + "timestamp": 1733771786 + } + ], + "offset": 0 + }, + "success": true + } + ```
@@ -410,7 +410,7 @@ Retrieve the settings of a task. #### Parameters
-**_task_id_** `int ` +**_task_id_** `int` The ID of the task. @@ -425,150 +425,150 @@ A dictionary containing the settings of the task.
Click to expand ```json -{ - "data": { - "task_info": { - "administrator_account_email": "username@xxxx.onmicrosoft.com", - "app_permissions": [...], - "application_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "backup_policy": 1, - "enable_auto_add_archive_mail": false, - "enable_auto_add_calendar": false, - "enable_auto_add_contact": false, - "enable_auto_add_drive": false, - "enable_auto_add_mail": false, - "enable_auto_discover_external_account": true, - "enable_auto_discover_general_site": false, - "enable_auto_discover_group_alias_archive_mail": false, - "enable_auto_discover_group_alias_calendar": false, - "enable_auto_discover_group_alias_contact": false, - "enable_auto_discover_group_alias_drive": false, - "enable_auto_discover_group_alias_mail": false, - "enable_auto_discover_group_calendar": false, - "enable_auto_discover_group_mail": false, - "enable_auto_discover_my_site": false, - "enable_auto_discover_teams": false, - "enable_auto_discover_unlicensed_account": true, - "enable_schedule": false, - "enable_user_restore": true, - "is_customized_app": true, - "is_team_list_ready": true, - "local_path": "/datastore/ActiveBackupForMicrosoft365/task_1", - "preserve_day_number": 30, - "region": 0, - "rotation_policy": 0, - "schedule": { - "date": "2025/1/26", - "date_type": 0, - "hour": 0, - "last_work_hour": 0, - "minute": 0, - "monthly_week": [], - "repeat_date": 0, - "repeat_hour": 0, - "repeat_hour_store_config": null, - "repeat_min": 0, - "repeat_min_store_config": null, - "week_day": "0,1,2,3,4,5,6" - }, - "schedule_id": 4, - "site_domain": "https://xxxx.sharepoint.com", - "task_id": 1, - "task_name": "test", - "task_status": 2, - "task_status_error_code": 0, - "tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "user_list": [ - { - "account_status": 1, - "account_type": 2, - "email": "username@xxxx.onmicrosoft.com", - "enable_archive_mail": false, - "enable_calendar": false, - "enable_contact": false, - "enable_drive": false, - "enable_mail": false, - "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "local_used_storage": 0, - "smtp_mail": "", - "user_name": "username" - } - ], - "group_list": [ - { - "description": "test group", - "display_name": "test group", - "enable_calendar": false, - "enable_group_alias_archive_mail": false, - "enable_group_alias_calendar": false, - "enable_group_alias_contact": false, - "enable_group_alias_drive": false, - "enable_group_alias_mail": false, - "enable_mail": false, - "group_status": 1, - "group_type": 0, - "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "local_used_storage": 0, - "mail": "test_group@xxxx.onmicrosoft.com", - "mail_nickname": "test group", - "owners": [], - "title": "test group", - "visibility": "Private" - }, - ], - "team_list": [ - { - "description": "test team", - "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "local_used_storage": 0, - "name": "test team", - "selected": false, - "team_status": 1, - "visibility": 0, - "web_url": "https://teams.microsoft.com/l/team/xxxx" - }, - ], - "my_site_list": [ - { - "description": "", - "id": 313, - "local_used_storage": 0, - "owner_type": 0, - "parent_id": "", - "primary_admin": "username@xxxx.onmicrosoft.com", - "selected": false, - "site_collection_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "site_name": "username", - "site_root": "https://xxxx-my.sharepoint.com", - "site_status": 1, - "site_type": 1, - "url": "https://xxxx-my.sharepoint.com/personal/username" - }, - ], - "general_site_list": [ - { - "description": "", - "id": 1, - "local_used_storage": 0, - "owner_type": 0, - "parent_id": "", - "primary_admin": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "selected": false, - "site_collection_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", - "site_name": "test sharepoint", - "site_root": "https://xxxx.sharepoint.com", - "site_status": 1, - "site_type": 0, - "url": "https://xxxx.sharepoint.com" + { + "data": { + "task_info": { + "administrator_account_email": "username@xxxx.onmicrosoft.com", + "app_permissions": [...], + "application_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "backup_policy": 1, + "enable_auto_add_archive_mail": false, + "enable_auto_add_calendar": false, + "enable_auto_add_contact": false, + "enable_auto_add_drive": false, + "enable_auto_add_mail": false, + "enable_auto_discover_external_account": true, + "enable_auto_discover_general_site": false, + "enable_auto_discover_group_alias_archive_mail": false, + "enable_auto_discover_group_alias_calendar": false, + "enable_auto_discover_group_alias_contact": false, + "enable_auto_discover_group_alias_drive": false, + "enable_auto_discover_group_alias_mail": false, + "enable_auto_discover_group_calendar": false, + "enable_auto_discover_group_mail": false, + "enable_auto_discover_my_site": false, + "enable_auto_discover_teams": false, + "enable_auto_discover_unlicensed_account": true, + "enable_schedule": false, + "enable_user_restore": true, + "is_customized_app": true, + "is_team_list_ready": true, + "local_path": "/datastore/ActiveBackupForMicrosoft365/task_1", + "preserve_day_number": 30, + "region": 0, + "rotation_policy": 0, + "schedule": { + "date": "2025/1/26", + "date_type": 0, + "hour": 0, + "last_work_hour": 0, + "minute": 0, + "monthly_week": [], + "repeat_date": 0, + "repeat_hour": 0, + "repeat_hour_store_config": null, + "repeat_min": 0, + "repeat_min_store_config": null, + "week_day": "0,1,2,3,4,5,6" }, - ], + "schedule_id": 4, + "site_domain": "https://xxxx.sharepoint.com", + "task_id": 1, + "task_name": "test", + "task_status": 2, + "task_status_error_code": 0, + "tenant_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "user_list": [ + { + "account_status": 1, + "account_type": 2, + "email": "username@xxxx.onmicrosoft.com", + "enable_archive_mail": false, + "enable_calendar": false, + "enable_contact": false, + "enable_drive": false, + "enable_mail": false, + "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "local_used_storage": 0, + "smtp_mail": "", + "user_name": "username" + } + ], + "group_list": [ + { + "description": "test group", + "display_name": "test group", + "enable_calendar": false, + "enable_group_alias_archive_mail": false, + "enable_group_alias_calendar": false, + "enable_group_alias_contact": false, + "enable_group_alias_drive": false, + "enable_group_alias_mail": false, + "enable_mail": false, + "group_status": 1, + "group_type": 0, + "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "local_used_storage": 0, + "mail": "test_group@xxxx.onmicrosoft.com", + "mail_nickname": "test group", + "owners": [], + "title": "test group", + "visibility": "Private" + }, + ], + "team_list": [ + { + "description": "test team", + "id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "local_used_storage": 0, + "name": "test team", + "selected": false, + "team_status": 1, + "visibility": 0, + "web_url": "https://teams.microsoft.com/l/team/xxxx" + }, + ], + "my_site_list": [ + { + "description": "", + "id": 313, + "local_used_storage": 0, + "owner_type": 0, + "parent_id": "", + "primary_admin": "username@xxxx.onmicrosoft.com", + "selected": false, + "site_collection_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "site_name": "username", + "site_root": "https://xxxx-my.sharepoint.com", + "site_status": 1, + "site_type": 1, + "url": "https://xxxx-my.sharepoint.com/personal/username" + }, + ], + "general_site_list": [ + { + "description": "", + "id": 1, + "local_used_storage": 0, + "owner_type": 0, + "parent_id": "", + "primary_admin": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "selected": false, + "site_collection_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "site_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx", + "site_name": "test sharepoint", + "site_root": "https://xxxx.sharepoint.com", + "site_status": 1, + "site_type": 0, + "url": "https://xxxx.sharepoint.com" + }, + ], + }, }, - }, - "success": true -} -``` + "success": true + } + ```
@@ -594,16 +594,16 @@ A dictionary containing the number of workers.
Click to expand ```json -{ - "data": { - "backup_job_worker_count": 40, - "event_worker_count": 40, - "max_backup_job_worker_count": 40, - "max_event_worker_count": 40 - }, - "success": true -} -``` + { + "data": { + "backup_job_worker_count": 40, + "event_worker_count": 40, + "max_backup_job_worker_count": 40, + "max_event_worker_count": 40 + }, + "success": true + } + ```
@@ -621,10 +621,10 @@ Set the number of workers for the Active Backup for Microsoft 365 package. #### Parameters
-**_backup_job_workers_** `int ` +**_backup_job_workers_** `int` Maximum number of concurrent backup accounts. Defaults to `40`. -**_event_workers_** `int ` +**_event_workers_** `int` Maximum number of concurrent backup files. Defaults to `40`. @@ -639,10 +639,10 @@ A dictionary containing the result of the worker count update.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -651,7 +651,7 @@ A dictionary containing the result of the worker count update. ### `set_task_schedule` -Set the schedule for a given task. +Set the schedule for a given task. #### Internal API
@@ -664,27 +664,27 @@ Set the schedule for a given task. The ID of the task. **_policy_** `int` -The schedule policy. -Possible values: -- 0 = continuous -- 1 = manual -- 2 = scheduled +The schedule policy. +Possible values: +- 0 = continuous +- 1 = manual +- 2 = scheduled. **_schedule_** `dict` -A dictionary containing the schedule settings. +A dictionary containing the schedule settings. Possible values: - `start_hour` (int): The start hour of the schedule. - `start_minute` (int): The start minute of the schedule. - `last_run_hour` (int): The last run hour of the schedule. - `repeat_every_hours` (int): Run the backup every X hours. -- `run_days` (list[int]): Run the backup at the specified days (Sunday = 0, Morning = 1, and so on...). +- `run_days` (list[int]): Run the backup at the specified days (Sunday = 0, Morning = 1, and so on...). :::note If `repeat_every_hours` is set to 0, the backup will run once a day. ::: -Example, to run the backup every day hourly starting at 08:30 until 23:30. +Examples, to run the backup every day hourly starting at 08:30 until 23:30. ```json { "start_hour": 8, @@ -706,11 +706,11 @@ A dictionary containing the result of the schedule update. #### Example return
Click to expand -```json -{ - "success": true -} -``` +```json + { + "success": true + } + ```
@@ -745,11 +745,11 @@ A dictionary containing the result of the rotation policy update. #### Example return
Click to expand -```json -{ - "success": true -} -``` +```json + { + "success": true + } + ```
@@ -782,10 +782,10 @@ A dictionary containing the result of the backup task.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -817,11 +817,11 @@ A dictionary containing the result of the task cancellation. #### Example return
Click to expand -```json -{ - "success": true -} -``` +```json + { + "success": true + } + ```
@@ -867,11 +867,11 @@ A dictionary containing the result of the task deletion. #### Example return
Click to expand -```json -{ - "success": true -} -``` +```json + { + "success": true + } + ```
@@ -892,19 +892,19 @@ Relink a task. **_task_name_** `str` The name of the task. -**_shared_folder_** `str` -The name of the shared folder where the task is stored. -Example: `ActiveBackupforBusiness` +**_local_shared_** `str` +The name of the shared folder where the task is stored. +Examples: `ActiveBackupforBusiness`. -**_task_path_** `str` -The relative path from the the shared folder where the task is stored. -Example: `/ActiveBackupForMicrosoft365/task_1` +**_local_path_** `str` +The relative path from the shared folder where the task is stored. +Examples: `/ActiveBackupForMicrosoft365/task_1`. **_admin_email_** `str` The email of the Microsoft 365 administrator. **_region_** `str` -The region of the Microsoft 365 account. Defaults to `Microsoft 365` +The region of the Microsoft 365 account. Defaults to `Microsoft 365`.
@@ -917,14 +917,14 @@ A dictionary containing the result of the task relinking. #### Example return
Click to expand -```json -{ - "data": { - "task_id": 3 - }, - "success": true -} -``` +```json + { + "data": { + "task_id": 3 + }, + "success": true + } + ```
diff --git a/documentation/docs/apis/classes/audiostation.md b/documentation/docs/apis/classes/audiostation.md index 4c0d220d..f90322fd 100644 --- a/documentation/docs/apis/classes/audiostation.md +++ b/documentation/docs/apis/classes/audiostation.md @@ -14,9 +14,22 @@ This API is not documented yet. ::: ## Overview - +A class to interact with Synology AudioStation API. ## Methods ### `get_info` +Retrieve general information about the AudioStation service. + +#### Internal API +
+`SYNO.AudioStation.Info` +
+ +#### Returns +
+`dict[str, object]` +A dictionary containing the service information or a string in case of an error. + +
@@ -24,6 +37,19 @@ This API is not documented yet. ### `get_playlist_info` +Retrieve information about playlists in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.Playlist` +
+ +#### Returns +
+`dict[str, object]` +A dictionary containing playlist information or a string in case of an error. + +
@@ -31,6 +57,19 @@ This API is not documented yet. ### `list_remote_player` +Retrieve a list of remote players available in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.RemotePlayer` +
+ +#### Returns +
+`dict[str, object]` +A dictionary containing information about remote players, or a string in case of an error. + +
@@ -38,6 +77,19 @@ This API is not documented yet. ### `list_pinned_song` +Retrieve a list of pinned songs in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.Pin` +
+ +#### Returns +
+`dict[str, object]` +A dictionary containing information about pinned songs, or a string in case of an error. + +
@@ -45,6 +97,26 @@ This API is not documented yet. ### `device_id` +Retrieve the playlist for a specific remote device in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.RemotePlayer` +
+ +#### Parameters +
+**_device_** `str` +The ID of the remote device. + + +
+#### Returns +
+`dict[str, object]` +A dictionary containing the playlist information for the specified device. + +
@@ -52,6 +124,26 @@ This API is not documented yet. ### `remote_play` +Start playback on a specified remote device in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.RemotePlayer` +
+ +#### Parameters +
+**_device_** `str` +The ID of the remote device on which to start playback. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the playback status or a string in case of an error. + +
@@ -59,6 +151,26 @@ This API is not documented yet. ### `remote_stop` +Stop playback on a specified remote device in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.RemotePlayer` +
+ +#### Parameters +
+**_device_** `str` +The ID of the remote device on which to stop playback. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the stop status or a string in case of an error. + +
@@ -66,6 +178,26 @@ This API is not documented yet. ### `remote_next` +Skip to the next track on a specified remote device in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.RemotePlayer` +
+ +#### Parameters +
+**_device_** `str` +The ID of the remote device on which to skip to the next track. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the status of the operation or a string in case of an error. + +
@@ -73,6 +205,26 @@ This API is not documented yet. ### `remote_prev` +Skip to the previous track on a specified remote device in AudioStation. + +#### Internal API +
+`SYNO.AudioStation.RemotePlayer` +
+ +#### Parameters +
+**_device_** `str` +The ID of the remote device on which to skip to the previous track. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the status of the operation or a string in case of an error. + +
diff --git a/documentation/docs/apis/classes/cloud_sync.md b/documentation/docs/apis/classes/cloud_sync.md index 3e6cf811..acf9795e 100644 --- a/documentation/docs/apis/classes/cloud_sync.md +++ b/documentation/docs/apis/classes/cloud_sync.md @@ -11,45 +11,44 @@ title: ✅ CloudSync ## Overview Cloud Sync API implementation. -This API provides the functionality to get information related to the package settings and current connections and tasks. -It also provides functionalities to set most of the settings for tasks and package configuration, as well as manage the current syncing processes. - -Due to the vast amount of public clouds available in the project, the API was not tested for every cloud scenario, so some params request may be missing in specific not tested clouds. - -The tested clouds so far are: -- Google Drive -- OneDrive -- DropBox -- Amazon S3 (task creation) - -### Supported methods - - - **Getters** : - - Get package settings - - Get connections - - Get connections settings - - Get connection information - - Get connection auth information - - Get connection logs - - Get connection tasks - - Get task filters - - Get task synced remote directories - - Get recently modified & currently syncing files - - **Setters** : - - Set package settings - - Set relink behavior - - Set connection settings - - Set connection schedule settings - - Set task settings - - Set task filters - - **Actions** : - - Pause connection - - Resume connection - - Delete connection - - Delete task - - Validate task settings - - Create S3 task - + This API provides the functionality to get information related to the package settings and current connections and tasks. + It also provides functionalities to set most of the settings for tasks and package configuration, as well as manage the current syncing processes. + + Due to the vast amount of public clouds available in the project, the API was not tested for every cloud scenario, so some params request may be missing in specific not tested clouds. + + The tested clouds so far are: + - Google Drive + - OneDrive + - DropBox + - Amazon S3 (task creation) + + ### Supported methods + + - **Getters** : + - Get package settings + - Get connections + - Get connections settings + - Get connection information + - Get connection auth information + - Get connection logs + - Get connection tasks + - Get task filters + - Get task synced remote directories + - Get recently modified & currently syncing files + - **Setters** : + - Set package settings + - Set relink behavior + - Set connection settings + - Set connection schedule settings + - Set task settings + - Set task filters + - **Actions** : + - Pause connection + - Resume connection + - Delete connection + - Delete task + - Validate task settings + - Create S3 task ## Methods ### `get_pkg_config` Retrieve package settings. @@ -69,38 +68,38 @@ A dictionary containing the result of package settings.
Click to expand ```json -{ - "data": { - "admin_mode": "enable", - "log_count": 20000, - "repo_vol_path": "/volume2", - "sync_mode": false, - "volume_count": 2, - "volume_list": [ - { - "desc": "", - "display": "Volume 1 (Available capacity: 715.84 GB )", - "mount_point": "/volume1", - "size_free": "768625090560", - "size_total": "955458760704", - "value": "1", - "vol_desc": "" - }, - { - "desc": "", - "display": "Volume 2 (Available capacity: 1841.73 GB )", - "mount_point": "/volume2", - "size_free": "1977547526144", - "size_total": "3835577597952", - "value": "2", - "vol_desc": "" - } - ], - "worker_count": 20 - }, - "success": true -} -``` + { + "data": { + "admin_mode": "enable", + "log_count": 20000, + "repo_vol_path": "/volume2", + "sync_mode": false, + "volume_count": 2, + "volume_list": [ + { + "desc": "", + "display": "Volume 1 (Available capacity: 715.84 GB )", + "mount_point": "/volume1", + "size_free": "768625090560", + "size_total": "955458760704", + "value": "1", + "vol_desc": "" + }, + { + "desc": "", + "display": "Volume 2 (Available capacity: 1841.73 GB )", + "mount_point": "/volume2", + "size_free": "1977547526144", + "size_total": "3835577597952", + "value": "2", + "vol_desc": "" + } + ], + "worker_count": 20 + }, + "success": true + } + ```
@@ -118,8 +117,8 @@ Retrieve a list of current cloud connections. #### Parameters
-**_group_by_** `str, optional ` -How to group the connection list, by user or cloud type. Defaults to `"group_by_user"`. +**_group_by_** `str` +How to group the connection list, by user or cloud type. Defaults to `"group_by_user"`. Possible values: - `group_by_user`: Group connection by owner user. - `group_by_cloud_type`: Group connections by cloud provider. @@ -136,45 +135,45 @@ A dictionary containing the list of cloud connections.
Click to expand ```json -{ - "data": { - "conn": [ - { - "id": 3, - "link_status": 1, - "resource": "", - "status": "uptodate", - "task_display_name": "Dropbox", - "task_name": "Dropbox", - "type": "db", - "type_id": 2, - "unfinished_files": 0, - "user_id": "dbid:xxxxxxxxxxxxxxxxxx", - "user_name": "username" - }, - { - "id": 2, - "link_status": 1, - "resource": "", - "status": "syncing", - "task_display_name": "Microsoft OneDrive", - "task_name": "Microsoft OneDrive", - "type": "od_v1", - "type_id": 22, - "unfinished_files": 2, - "user_id": "xxxxxx", - "user_name": "username" - } - ], - "is_admin_mode": true, - "is_pause": false, - "notification": null, - "total": 2, - "tray_status": "syncing" - }, - "success": true -} -``` + { + "data": { + "conn": [ + { + "id": 3, + "link_status": 1, + "resource": "", + "status": "uptodate", + "task_display_name": "Dropbox", + "task_name": "Dropbox", + "type": "db", + "type_id": 2, + "unfinished_files": 0, + "user_id": "dbid:xxxxxxxxxxxxxxxxxx", + "user_name": "username" + }, + { + "id": 2, + "link_status": 1, + "resource": "", + "status": "syncing", + "task_display_name": "Microsoft OneDrive", + "task_name": "Microsoft OneDrive", + "type": "od_v1", + "type_id": 22, + "unfinished_files": 2, + "user_id": "xxxxxx", + "user_name": "username" + } + ], + "is_admin_mode": true, + "is_pause": false, + "notification": null, + "total": 2, + "tray_status": "syncing" + }, + "success": true + } + ```
@@ -192,7 +191,7 @@ Retrieve settings for a specific connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. @@ -207,22 +206,22 @@ A dictionary containing the connection settings.
Click to expand ```json -{ - "data": { - "client_type": "db", - "isSSE": false, - "is_enabled_schedule": false, - "max_download_speed": 0, - "max_upload_speed": 0, - "part_size": 0, - "pull_event_period": 60, - "schedule_info": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", - "storage_class": "", - "task_name": "Dropbox" - }, - "success": true -} -``` + { + "data": { + "client_type": "db", + "isSSE": false, + "is_enabled_schedule": false, + "max_download_speed": 0, + "max_upload_speed": 0, + "part_size": 0, + "pull_event_period": 60, + "schedule_info": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "storage_class": "", + "task_name": "Dropbox" + }, + "success": true + } + ```
@@ -240,7 +239,7 @@ Retrieve cloud information for a specific connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. @@ -255,26 +254,26 @@ A dictionary containing cloud information.
Click to expand ```json -{ - "data": { - "auth_version": "", - "bucket_name": "", - "container_name": "", - "project_id": "", - "public_url": "", - "quota_total": 2147483648, - "quota_used": 423330996, - "region": "", - "server_addr": "", - "shared_drive_name": "", - "storage_class": "", - "type": "db", - "type_id": 2, - "user_name": "username" - }, - "success": true -} -``` + { + "data": { + "auth_version": "", + "bucket_name": "", + "container_name": "", + "project_id": "", + "public_url": "", + "quota_total": 2147483648, + "quota_used": 423330996, + "region": "", + "server_addr": "", + "shared_drive_name": "", + "storage_class": "", + "type": "db", + "type_id": 2, + "user_name": "username" + }, + "success": true + } + ```
@@ -292,7 +291,7 @@ Retrieve authentication information for a specific connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. @@ -307,45 +306,45 @@ A dictionary containing the connection authentication details.
Click to expand ```json -{ - "data": { - "access_key": "", - "access_token": "xxxxxxxx", - "auth_pass": "", - "auth_scheme": 0, - "auth_user": "", - "bucket_id": "", - "bucket_name": "", - "client_id": "xxxxxxxx", - "client_type": "db", - "conn_id": 3, - "container_name": "", - "download_url": "", - "openstack_api_key": "", - "openstack_domain_id": "", - "openstack_domain_name": "", - "openstack_identity_service_url": "", - "openstack_identity_service_version": "", - "openstack_password": "", - "openstack_proj_id": "", - "openstack_region": "", - "openstack_tenant_id": "", - "openstack_tenant_name": "", - "openstack_token": "", - "public_url": "", - "refresh_token": "xxxxxxxx", - "resource": "", - "root_folder_id": "", - "root_folder_path": "/", - "secret_key": "", - "server_addr": "", - "service_host": "", - "unique_id": "dbid:xxxxxxxx", - "user_name": "username" - }, - "success": true -} -``` + { + "data": { + "access_key": "", + "access_token": "xxxxxxxx", + "auth_pass": "", + "auth_scheme": 0, + "auth_user": "", + "bucket_id": "", + "bucket_name": "", + "client_id": "xxxxxxxx", + "client_type": "db", + "conn_id": 3, + "container_name": "", + "download_url": "", + "openstack_api_key": "", + "openstack_domain_id": "", + "openstack_domain_name": "", + "openstack_identity_service_url": "", + "openstack_identity_service_version": "", + "openstack_password": "", + "openstack_proj_id": "", + "openstack_region": "", + "openstack_tenant_id": "", + "openstack_tenant_name": "", + "openstack_token": "", + "public_url": "", + "refresh_token": "xxxxxxxx", + "resource": "", + "root_folder_id": "", + "root_folder_path": "/", + "secret_key": "", + "server_addr": "", + "service_host": "", + "unique_id": "dbid:xxxxxxxx", + "user_name": "username" + }, + "success": true + } + ```
@@ -363,28 +362,28 @@ Retrieve logs for a specific connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. -**_keyword_** `str, optional ` +**_keyword_** `str` A keyword to filter logs. Defaults to `''`. -**_date_from_** `int, optional ` +**_date_from_** `int` The starting date in epoch format. Defaults to `0`. -**_date_to_** `int, optional ` +**_date_to_** `int` The ending date in epoch format. Defaults to `0`. **_log_level_** `int` -Log level filter. Defaults to `-1`. +Log level filter. Defaults to `-1`. Possible values: - `-1`: All - `0`: Info - `1`: Warning - `2`: Error -**_action_** `int, optional ` -Action filter. Defaults to `-1`. +**_action_** `int` +Action filter. Defaults to `-1`. Possible values: - `-1`: All - `0`: Delete Remote @@ -395,10 +394,10 @@ Possible values: - `8`: Merge - `9`: Merge Deletion -**_offset_** `int, optional ` +**_offset_** `int` Log offset for pagination. Defaults to `0`. -**_limit_** `int, optional ` +**_limit_** `int` Number of logs to retrieve. Defaults to `200`. @@ -413,35 +412,35 @@ A dictionary containing the connection logs.
Click to expand ```json -{ - "data": { - "items": [ - { - "action": 1, - "error_code": -36, - "file_name": "OCR Japanese extension.paper", - "file_type": "file", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/OCR Japanese extension.paper", - "session_id": 4, - "time": 1724418508 - }, - { - "action": 1, - "error_code": -36, - "file_name": "OCR Japanese extension.paper", - "file_type": "file", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/OCR Japanese extension.paper", - "session_id": 4, - "time": 1724418119 - } - ], - "total": 2 - }, - "success": true -} -``` + { + "data": { + "items": [ + { + "action": 1, + "error_code": -36, + "file_name": "OCR Japanese extension.paper", + "file_type": "file", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/OCR Japanese extension.paper", + "session_id": 4, + "time": 1724418508 + }, + { + "action": 1, + "error_code": -36, + "file_name": "OCR Japanese extension.paper", + "file_type": "file", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/OCR Japanese extension.paper", + "session_id": 4, + "time": 1724418119 + } + ], + "total": 2 + }, + "success": true + } + ```
@@ -459,7 +458,7 @@ Retrieve a list of tasks related to a specific connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. @@ -474,28 +473,28 @@ A dictionary containing the list of tasks.
Click to expand ```json -{ - "data": { - "sess": [ - { - "cloud_type_str": "db", - "conn_id": 3, - "error": 0, - "error_desc": "", - "link_status": 1, - "local_sync_path": "/test_share/WebDAV test/subfolder", - "remote_folder_id": "id:xxxx", - "remote_sync_path": "/docs", - "sess_id": 4, - "sync_direction": "ONLY_DOWNLOAD", - "sync_status": "uptodate" - } - ], - "total": 1 - }, - "success": true -} -``` + { + "data": { + "sess": [ + { + "cloud_type_str": "db", + "conn_id": 3, + "error": 0, + "error_desc": "", + "link_status": 1, + "local_sync_path": "/test_share/WebDAV test/subfolder", + "remote_folder_id": "id:xxxx", + "remote_sync_path": "/docs", + "sess_id": 4, + "sync_direction": "ONLY_DOWNLOAD", + "sync_status": "uptodate" + } + ], + "total": 1 + }, + "success": true + } + ```
@@ -513,7 +512,7 @@ Retrieve filter information for a specific task. #### Parameters
-**_sess_id_** `int ` +**_sess_id_** `int` The ID of the task, obtained from `get_tasks()`. @@ -528,31 +527,31 @@ A dictionary containing task filter information.
Click to expand ```json -{ - "data": { - "filtered_extensions": [ - "wbmp", - "webdoc", - "x3f", - "xbm" - ], - "filtered_max_upload_size": 1048576, - "filtered_names": [ - "test" - ], - "filtered_paths": [ - "/subfolder_1" - ], - "user_defined_extensions": [ - "iso" - ], - "user_defined_names": [ - "test" - ] - }, - "success": true -} -``` + { + "data": { + "filtered_extensions": [ + "wbmp", + "webdoc", + "x3f", + "xbm" + ], + "filtered_max_upload_size": 1048576, + "filtered_names": [ + "test" + ], + "filtered_paths": [ + "/subfolder_1" + ], + "user_defined_extensions": [ + "iso" + ], + "user_defined_names": [ + "test" + ] + }, + "success": true + } + ```
@@ -570,13 +569,13 @@ Retrieve a list of children directories in the cloud for a specific task. #### Parameters
-**_sess_id_** `int ` +**_sess_id_** `int` The ID of the task, obtained from `get_tasks()`. -**_remote_folder_id_** `str ` +**_remote_folder_id_** `str` The ID of the remote folder, obtained from `get_tasks()`. -**_path_** `str, optional ` +**_path_** `str` The folder path to retrieve the child directories from. Defaults to root `'/'`. @@ -591,38 +590,38 @@ A dictionary containing the list of children directories.
Click to expand ```json -{ - "data": { - "children": [ - { - "exists_type": 1, - "file_id": "", - "path": "/subfolder_1", - "text": "subfolder_1" - }, - { - "exists_type": 1, - "file_id": "", - "path": "/new folder", - "text": "new folder" - }, - { - "exists_type": 3, - "file_id": "id:xxxx", - "path": "/test1", - "text": "test1" - }, - { - "exists_type": 3, - "file_id": "id:xxxx", - "path": "/test2", - "text": "test2" - } - ] - }, - "success": true -} -``` + { + "data": { + "children": [ + { + "exists_type": 1, + "file_id": "", + "path": "/subfolder_1", + "text": "subfolder_1" + }, + { + "exists_type": 1, + "file_id": "", + "path": "/new folder", + "text": "new folder" + }, + { + "exists_type": 3, + "file_id": "id:xxxx", + "path": "/test1", + "text": "test1" + }, + { + "exists_type": 3, + "file_id": "id:xxxx", + "path": "/test2", + "text": "test2" + } + ] + }, + "success": true + } + ```
@@ -648,78 +647,78 @@ A dictionary containing the recently modified files.
Click to expand ```json -{ - "data": { - "history_items": [ - { - "action": 1, - "base_name": "test_file.paper", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/test_file.paper", - "session_id": 4, - "syncfolder_basename": "subfolder" - }, - { - "action": 1, - "base_name": "perfect plan.paper", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/perfect plan.paper", - "session_id": 4, - "syncfolder_basename": "subfolder" - }, - { - "action": 1, - "base_name": "Untitled.paper", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/Untitled.paper", - "session_id": 4, - "syncfolder_basename": "subfolder" - }, - { - "action": 1, - "base_name": "translation hw.paper", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/translation hw.paper", - "session_id": 4, - "syncfolder_basename": "subfolder" - }, - { - "action": 1, - "base_name": "The Tao of Harp.paper", - "log_level": 2, - "path": "/test_share/WebDAV test/subfolder/song ideas/The Tao of Harp.paper", - "session_id": 4, - "syncfolder_basename": "subfolder" - } - ], - "is_admin_mode": true, - "processing_items": [ - { - "base_name": "1111111111111111111111125.jpg", - "bit_rate": 2114, - "current_size": 65535, - "path": "/test_share/WebDAV test/subfolder/test1/asd/1111111111111111.jpg", - "session_id": 3, - "status": "uploading", - "total_size": 295493, - "user_name": "username" - }, - { - "base_name": "ans1.3.png", - "bit_rate": 1047, - "current_size": 358122, - "path": "/test_share/WebDAV test/subfolder/test2/ans1.3.png", - "session_id": 3, - "status": "uploading", - "total_size": 358122, - "user_name": "username" - } - ], - "server_merge_items": [] - }, - "success": true -} -``` + { + "data": { + "history_items": [ + { + "action": 1, + "base_name": "test_file.paper", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/test_file.paper", + "session_id": 4, + "syncfolder_basename": "subfolder" + }, + { + "action": 1, + "base_name": "perfect plan.paper", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/perfect plan.paper", + "session_id": 4, + "syncfolder_basename": "subfolder" + }, + { + "action": 1, + "base_name": "Untitled.paper", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/Untitled.paper", + "session_id": 4, + "syncfolder_basename": "subfolder" + }, + { + "action": 1, + "base_name": "translation hw.paper", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/translation hw.paper", + "session_id": 4, + "syncfolder_basename": "subfolder" + }, + { + "action": 1, + "base_name": "The Tao of Harp.paper", + "log_level": 2, + "path": "/test_share/WebDAV test/subfolder/song ideas/The Tao of Harp.paper", + "session_id": 4, + "syncfolder_basename": "subfolder" + } + ], + "is_admin_mode": true, + "processing_items": [ + { + "base_name": "1111111111111111111111125.jpg", + "bit_rate": 2114, + "current_size": 65535, + "path": "/test_share/WebDAV test/subfolder/test1/asd/1111111111111111.jpg", + "session_id": 3, + "status": "uploading", + "total_size": 295493, + "user_name": "username" + }, + { + "base_name": "ans1.3.png", + "bit_rate": 1047, + "current_size": 358122, + "path": "/test_share/WebDAV test/subfolder/test2/ans1.3.png", + "session_id": 3, + "status": "uploading", + "total_size": 358122, + "user_name": "username" + } + ], + "server_merge_items": [] + }, + "success": true + } + ```
@@ -737,16 +736,16 @@ Set package configuration settings. #### Parameters
-**_pkg_volume_** `str ` +**_pkg_volume_** `str` The volume path where the package data will be stored (e.g., `/volume1`). -**_log_count_** `int, optional ` +**_log_count_** `int` Maximum number of logs retained per connection. Defaults to `20000`, max is `100000`. -**_workers_** `int, optional ` +**_workers_** `int` Number of concurrent uploads allowed. Defaults to `3`, max is `20`. -**_admin_mode_** `bool, optional ` +**_admin_mode_** `bool` Whether all users' tasks are retrieved or not. Defaults to `True`. @@ -761,10 +760,10 @@ A dictionary containing the result of the configuration update.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -787,7 +786,7 @@ Set the relinking behavior for personal user accounts. #### Parameters
-**_delete_from_cloud_** `bool ` +**_delete_from_cloud_** `bool` Set to `False` for "locally deleted files will be re-fetched from the cloud". Set to `True` for "locally deleted files will also be removed from the cloud". @@ -803,10 +802,10 @@ A dictionary containing the result of the relink behavior update.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -824,28 +823,28 @@ Set settings for a specific cloud connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. -**_task_name_** `str ` +**_task_name_** `str` The name of the cloud sync task. -**_pull_event_period_** `int, optional ` +**_pull_event_period_** `int` Frequency (in seconds) to pull event updates. Defaults to `60`. -**_max_upload_speed_** `int, optional ` +**_max_upload_speed_** `int` Maximum upload speed in bytes. Defaults to `0` (unlimited). -**_max_download_speed_** `int, optional ` +**_max_download_speed_** `int` Maximum download speed in bytes. Defaults to `0` (unlimited). -**_storage_class_** `str, optional ` +**_storage_class_** `str` Cloud-specific storage class. Defaults to `''`. -**_isSSE_** `bool, optional ` +**_isSSE_** `bool` Enable Security Service Edge (SSE) for compatible cloud storage. Defaults to `False`. -**_part_size_** `int, optional ` +**_part_size_** `int` Part size for file uploads, in megabytes. Defaults to `128`. @@ -860,10 +859,10 @@ A dictionary containing the updated connection settings.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -881,13 +880,13 @@ Set the schedule for a specific connection. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection, obtained from `get_connections()`. -**_enable_** `bool ` +**_enable_** `bool` Whether the scheduling is enabled (`True`) or disabled (`False`). -**_schedule_info_** `list[str], optional ` +**_schedule_info_** `list[str]` A list of 7 strings where each string represents a day of the week, going from Sunday to Saturday. Each string is composed of 24 characters, where each character is either '1' (enabled) or '0' (disabled) for the respective hour of the day. The default value (if `schedule_info` is not provided) enables all days and hours. @@ -918,10 +917,10 @@ A dictionary containing the schedule settings.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -939,23 +938,23 @@ Set the task settings for a specific session. #### Parameters
-**_sess_id_** `int ` +**_sess_id_** `int` The ID of the task, obtained from `get_tasks()`. -**_sync_direction_** `str ` -The synchronization direction. +**_sync_direction_** `str` +The synchronization direction. Possible values: - `ONLY_UPLOAD`: Upload local changes only. - `BIDIRECTION`: Sync both ways (upload and download). - `ONLY_DOWNLOAD`: Download remote changes only. -**_consistency_check_** `bool, optional ` +**_consistency_check_** `bool` If True, enables advanced consistency check (requires more resources). Defaults to `True`. -**_no_delete_on_cloud_** `bool, optional ` +**_no_delete_on_cloud_** `bool` If `True`, prevents deletion of files in the remote folder when removed from the local directory. Defaults to `True`. -**_convert_gd_** `bool, optional ` +**_convert_gd_** `bool` If `True`, converts Google Drive Online documents to Microsoft Office format. Defaults to `False`. @@ -970,10 +969,10 @@ A dictionary containing the result of the task settings configuration.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -991,19 +990,19 @@ Set task filters for selective synchronization in a specific session. #### Parameters
-**_sess_id_** `int ` +**_sess_id_** `int` The ID of the session, obtained from `get_tasks()`. -**_filtered_paths_** `list[str], optional ` +**_filtered_paths_** `list[str]` A list of paths (directories / subdirectories) to exclude from the synchronization process, e.g, `['/images', '/videos/movies']`. Defaults to `[]`. -**_filtered_filenames_** `list[str], optional ` +**_filtered_filenames_** `list[str]` A list of filenames to exclude from synchronization. Defaults to `[]`. -**_filtered_extensions_** `list[str], optional ` +**_filtered_extensions_** `list[str]` A list of file extensions to exclude from synchronization, e.g., `['mp3', 'iso', 'mkv']`. Defaults to `[]`. -**_max_upload_size_** `int, optional ` +**_max_upload_size_** `int` The maximum file size for uploads, in bytes. Files larger than this size will be excluded from synchronization. Defaults to `0` (no size limit). @@ -1018,10 +1017,10 @@ A dictionary containing the result of the task filters configuration.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1039,7 +1038,7 @@ Pause one or all connections. #### Parameters
-**_conn_id_** `int, optional ` +**_conn_id_** `int` The ID of the connection to pause. If not specified or set to `-1`, all connections will be paused. @@ -1054,10 +1053,10 @@ A dictionary containing the result of the pause action.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1075,7 +1074,7 @@ Resume one or all connections. #### Parameters
-**_conn_id_** `int, optional ` +**_conn_id_** `int` The ID of the connection to resume. If not specified or set to `-1`, all connections will be resumed. @@ -1090,10 +1089,10 @@ A dictionary containing the result of the resume action.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1111,7 +1110,7 @@ The data will remain in both the local and remote directories. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection to be removed, obtained from `get_connections()`. @@ -1126,10 +1125,10 @@ A dictionary containing the result of the remove action.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1147,10 +1146,10 @@ The data will remain in both the local and remote directories. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection associated with the task, obtained from `get_connections()`. -**_sess_id_** `int ` +**_sess_id_** `int` The ID of the task to be removed, obtained from `get_tasks()`. @@ -1165,10 +1164,10 @@ A dictionary containing the result of the task removal.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1176,8 +1175,8 @@ A dictionary containing the result of the task removal. --- -### `test_task_setting` -Test the task settings make sure they are valid. +### `create_sync_task_s3` +Add a new synchronization task. #### Internal API
@@ -1186,36 +1185,36 @@ Test the task settings make sure they are valid. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection. -**_local_path_** `str ` +**_local_path_** `str` The local path to sync. -**_cloud_path_** `str ` +**_cloud_path_** `str` The cloud path to sync. -**_sync_direction_** `str, optional ` +**_sync_direction_** `str` The synchronization direction. Defaults to `'BIDIRECTION'`. -**_storage_class_** `str, optional ` +**_storage_class_** `str` The storage class. Defaults to `'STANDARD'`. -**_file_filter_** `list[str], optional ` +**_file_filter_** `list[str]` List of file extensions to filter. Defaults to `[]`. -**_filter_max_upload_size_** `int, optional ` +**_filter_max_upload_size_** `int` Maximum upload size for files. Defaults to `0`. -**_filter_names_** `list[str], optional ` +**_filter_names_** `list[str]` List of file names to filter. Defaults to `[]`.
#### Returns
-`tuple[bool, dict[str, object] | str]` -A tuple containing a boolean indicating success, and a dictionary or string with the result. +`tuple[bool, Any]` +A tuple containing the result of the task creation.
@@ -1224,8 +1223,8 @@ A tuple containing a boolean indicating success, and a dictionary or string with --- -### `create_sync_task_s3` -Add a new synchronization task. +### `test_task_setting` +Test the task settings make sure they are valid. #### Internal API
@@ -1234,36 +1233,36 @@ Add a new synchronization task. #### Parameters
-**_conn_id_** `int ` +**_conn_id_** `int` The ID of the connection. -**_local_path_** `str ` +**_local_path_** `str` The local path to sync. -**_cloud_path_** `str ` +**_cloud_path_** `str` The cloud path to sync. -**_sync_direction_** `str, optional ` +**_sync_direction_** `str` The synchronization direction. Defaults to `'BIDIRECTION'`. -**_storage_class_** `str, optional ` +**_storage_class_** `str` The storage class. Defaults to `'STANDARD'`. -**_file_filter_** `list[str], optional ` +**_file_filter_** `list[str]` List of file extensions to filter. Defaults to `[]`. **_filter_max_upload_size_** `int` Maximum upload size for files. Defaults to `0`. -**_filter_names_** `list[str], optional ` +**_filter_names_** `list[str]` List of file names to filter. Defaults to `[]`.
#### Returns
-`tuple[bool, Any]` -A tuple containing the result of the task creation. +`tuple[bool, dict[str, object] | str]` +A tuple containing a boolean indicating success, and a dictionary or string with the result.
diff --git a/documentation/docs/apis/classes/core_active_backup.md b/documentation/docs/apis/classes/core_active_backup.md index 502304f6..5929019e 100644 --- a/documentation/docs/apis/classes/core_active_backup.md +++ b/documentation/docs/apis/classes/core_active_backup.md @@ -11,31 +11,31 @@ title: ✅ ActiveBackupBusiness ## Overview Active Backup for Business API Implementation. -This class provides methods to interact with the Active Backup for Business package. - -### Supported methods - - - **Getters** : - - Get package settings - - Get tasks information - - Get tasks versions information - - Get devices information - - Get devices transfer size - - Get hypervisors information - - Get package / devices / tasks logs - - Get task history - - Get task result details - - Get storage information - - **Setters** : - - Set maximum concurrent devices - - Set retention policy execution time - - Set bandwidth control - - Set use package certificate - - **Actions** : - - Run backup - - Cancel backup - - Remove task - - Remove version + This class provides methods to interact with the Active Backup for Business package. + + ### Supported methods + + - **Getters** : + - Get package settings + - Get tasks information + - Get tasks versions information + - Get devices information + - Get devices transfer size + - Get hypervisors information + - Get package / devices / tasks logs + - Get task history + - Get task result details + - Get storage information + - **Setters** : + - Set maximum concurrent devices + - Set retention policy execution time + - Set bandwidth control + - Set use package certificate + - **Actions** : + - Run backup + - Cancel backup + - Remove task + - Remove version ## Methods ### `get_settings` Get the package settings including certificate information. @@ -55,77 +55,77 @@ A dictionary containing the current settings.
Click to expand ```json -{ - "data": { - "cert_info": { - "cert_from_dsm": { - "cert_common_name": "xxxxx.myds.me", - "cert_issuer": "R10", - "cert_san": [ - "*.xxxxx.myds.me", - "xxxxx.myds.me" - ], - "cert_tillTime": "May 29 18:54:13 2025 GMT" - }, - "cert_from_package": { - "cert_common_name": "Active Backup for Business", - "cert_issuer": "Synology Active Backup for Business", - "cert_san": [ - "Active Backup for Business" - ], - "cert_tillTime": "Apr 17 19:14:52 2034 GMT" + { + "data": { + "cert_info": { + "cert_from_dsm": { + "cert_common_name": "xxxxx.myds.me", + "cert_issuer": "R10", + "cert_san": [ + "*.xxxxx.myds.me", + "xxxxx.myds.me" + ], + "cert_tillTime": "May 29 18:54:13 2025 GMT" + }, + "cert_from_package": { + "cert_common_name": "Active Backup for Business", + "cert_issuer": "Synology Active Backup for Business", + "cert_san": [ + "Active Backup for Business" + ], + "cert_tillTime": "Apr 17 19:14:52 2034 GMT" + }, + "cert_use_package": true }, - "cert_use_package": true + "settings": [ + { + "id": 1, + "name": "max_concurrent_devices", + "value": "5" + }, + { + "id": 2, + "name": "memory_usage_limit_percentage", + "value": "75" + }, + { + "id": 3, + "name": "package_cert_id", + "value": "dyAaL7" + }, + { + "id": 4, + "name": "enable_global_bandwidth_control", + "value": "false" + }, + { + "id": 5, + "name": "global_backup_bandwidth_number", + "value": "0" + }, + { + "id": 6, + "name": "enable_ip_range_bandwidth_control", + "value": "false" + }, + { + "id": 7, + "name": "full_backup_task_ids", + "value": "2" + }, + { + "name": "retention_run_hour", + "value": "14" + }, + { + "name": "retention_run_min", + "value": "50" + } + ] }, - "settings": [ - { - "id": 1, - "name": "max_concurrent_devices", - "value": "5" - }, - { - "id": 2, - "name": "memory_usage_limit_percentage", - "value": "75" - }, - { - "id": 3, - "name": "package_cert_id", - "value": "dyAaL7" - }, - { - "id": 4, - "name": "enable_global_bandwidth_control", - "value": "false" - }, - { - "id": 5, - "name": "global_backup_bandwidth_number", - "value": "0" - }, - { - "id": 6, - "name": "enable_ip_range_bandwidth_control", - "value": "false" - }, - { - "id": 7, - "name": "full_backup_task_ids", - "value": "2" - }, - { - "name": "retention_run_hour", - "value": "14" - }, - { - "name": "retention_run_min", - "value": "50" - } - ] - }, - "success": true -} -``` + "success": true + } + ```
@@ -169,10 +169,10 @@ A dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -194,7 +194,7 @@ Set the time of day when the retention policy will be executed. Hour in 24-hour format (0 - 23) when the retention policy will be executed. **_minute_** `int` -Minute (0 - 59) when the retention policy will be executed +Minute (0 - 59) when the retention policy will be executed.
@@ -208,10 +208,10 @@ A dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -223,7 +223,7 @@ A dictionary containing the result of the operation. Set the global bandwidth control and IP range bandwidth control. :::note - Applies only to PC, Physical Server and NAS devices. + Applies only to PC, Physical Server and NAS devices. ::: @@ -241,15 +241,15 @@ Set the global bandwidth control and IP range bandwidth control. #### Parameters
**_traffic_control_** `dict[str, object]` -Traffic control settings. +Traffic control settings. Defaults to `{ 'enable': False, 'bandwidth': 0 }` (disable traffic throttling). Bandwidth should be specified in MB/s. **_ip_range_** `list[str]` -If specified, traffic control will only be applied to this IP range. +If specified, traffic control will only be applied to this IP range. Defaults to `["", ""]` (disable IP range bandwidth control). First index should contain the IP range start, second index the IP range end. Only supports IPv4 format. -Example: +Example: ```python ["192.168.0.1", "192.168.0.10"] ``` @@ -266,10 +266,10 @@ A dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -302,10 +302,10 @@ A dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -361,107 +361,107 @@ A dictionary containing a list of devices and their transfer size.
Click to expand ```json -{ - "data" : { - "device_list" : [ - { - "device" : { - "agent_token" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", - "agentless_auth_policy" : 0, - "auto_discovery" : false, - "backup_type" : 2, - "create_time" : 1709413484, - "device_id" : 5, - "device_uuid" : "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx", - "dsm_model" : "", - "dsm_unique" : "", - "host_ip" : "192.168.0.63", - "host_name" : "xxxxx", - "host_port" : 0, - "hypervisor_id" : "", - "inventory_id" : 0, - "login_password" : "", - "login_time" : 1709413493, - "login_user" : "xxxx", - "login_user_id" : 1026, - "os_name" : "Windows 11(64-bit)", - "vm_moid_path" : "" - }, - "transfer_list" : [ - { - "config_device_id" : 5, - "device_name" : "xxxxx", - "device_result_id" : 342, - "processed_bytes" : 0, - "result_id" : 587, - "status" : 5, - "time_end" : 1741895385, - "time_start" : 1741894511, - "transfered_bytes" : 1523580928 - }, - { - "config_device_id" : 5, - "device_name" : "xxxxx", - "device_result_id" : 343, - "processed_bytes" : 0, - "result_id" : 589, - "status" : 5, - "time_end" : 1741896408, - "time_start" : 1741896176, - "transfered_bytes" : 6909067264 - }, - { - "config_device_id" : 5, - "device_name" : "xxxxx", - "device_result_id" : 344, - "processed_bytes" : 0, - "result_id" : 590, - "status" : 5, - "time_end" : 1741896716, - "time_start" : 1741896624, - "transfered_bytes" : 444596224 + { + "data" : { + "device_list" : [ + { + "device" : { + "agent_token" : "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + "agentless_auth_policy" : 0, + "auto_discovery" : false, + "backup_type" : 2, + "create_time" : 1709413484, + "device_id" : 5, + "device_uuid" : "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx", + "dsm_model" : "", + "dsm_unique" : "", + "host_ip" : "192.168.0.63", + "host_name" : "xxxxx", + "host_port" : 0, + "hypervisor_id" : "", + "inventory_id" : 0, + "login_password" : "", + "login_time" : 1709413493, + "login_user" : "xxxx", + "login_user_id" : 1026, + "os_name" : "Windows 11(64-bit)", + "vm_moid_path" : "" }, - { - "config_device_id" : 5, - "device_name" : "xxxxx", - "device_result_id" : 346, - "processed_bytes" : 0, - "result_id" : 591, - "status" : 2, - "time_end" : 1741901184, - "time_start" : 1741896737, - "transfered_bytes" : 482689236992 - }, - { - "config_device_id" : 5, - "device_name" : "xxxxx", - "device_result_id" : 347, - "processed_bytes" : 0, - "result_id" : 593, - "status" : 2, - "time_end" : 1741946439, - "time_start" : 1741946267, - "transfered_bytes" : 2122801152 - }, - { - "config_device_id" : 5, - "device_name" : "xxxxx", - "device_result_id" : 348, - "processed_bytes" : 0, - "result_id" : 595, - "status" : 2, - "time_end" : 1741972250, - "time_start" : 1741971826, - "transfered_bytes" : 8208736256 - } - ] - }, - ], - "total" : 1 - }, - "success" : true -} -``` + "transfer_list" : [ + { + "config_device_id" : 5, + "device_name" : "xxxxx", + "device_result_id" : 342, + "processed_bytes" : 0, + "result_id" : 587, + "status" : 5, + "time_end" : 1741895385, + "time_start" : 1741894511, + "transfered_bytes" : 1523580928 + }, + { + "config_device_id" : 5, + "device_name" : "xxxxx", + "device_result_id" : 343, + "processed_bytes" : 0, + "result_id" : 589, + "status" : 5, + "time_end" : 1741896408, + "time_start" : 1741896176, + "transfered_bytes" : 6909067264 + }, + { + "config_device_id" : 5, + "device_name" : "xxxxx", + "device_result_id" : 344, + "processed_bytes" : 0, + "result_id" : 590, + "status" : 5, + "time_end" : 1741896716, + "time_start" : 1741896624, + "transfered_bytes" : 444596224 + }, + { + "config_device_id" : 5, + "device_name" : "xxxxx", + "device_result_id" : 346, + "processed_bytes" : 0, + "result_id" : 591, + "status" : 2, + "time_end" : 1741901184, + "time_start" : 1741896737, + "transfered_bytes" : 482689236992 + }, + { + "config_device_id" : 5, + "device_name" : "xxxxx", + "device_result_id" : 347, + "processed_bytes" : 0, + "result_id" : 593, + "status" : 2, + "time_end" : 1741946439, + "time_start" : 1741946267, + "transfered_bytes" : 2122801152 + }, + { + "config_device_id" : 5, + "device_name" : "xxxxx", + "device_result_id" : 348, + "processed_bytes" : 0, + "result_id" : 595, + "status" : 2, + "time_end" : 1741972250, + "time_start" : 1741971826, + "transfered_bytes" : 8208736256 + } + ] + }, + ], + "total" : 1 + }, + "success" : true + } + ```
@@ -470,7 +470,7 @@ A dictionary containing a list of devices and their transfer size. ### `list_tasks` -Get information of one or all tasks. +Get information of one or all tasks. #### Internal API
@@ -480,7 +480,7 @@ Get information of one or all tasks. #### Parameters
**_task_id_** `int` -Get information of specific task. Defaults to `-1` (all tasks) +Get information of specific task. Defaults to `-1` (all tasks). **_backup_type_** `str` Return only tasks matching the device type provided. Defaults to `""` (all device types). @@ -490,8 +490,7 @@ Possible values: - `"physical_server"` - `"file_server"` - `"nas"` - -Note that values are different when returned by the API. +Note that values are different when returned by the API. Return values mappings: - `1` -> `vm` - `2` -> `pc` @@ -528,181 +527,181 @@ Dictionary containing a list of tasks.
Click to expand ```json -{ - "data": { - "has_devices": true, - "has_dsm_agent": false, - "has_hyperv_inventories": false, - "has_linux_agent": false, - "has_mac_agent": false, - "has_vmware_inventories": false, - "has_windows_agent": true, - "tasks": [{ - "agentless_backup_path" : "", - "agentless_backup_policy" : 0, - "agentless_enable_block_transfer" : false, - "agentless_enable_dedup" : false, - "agentless_enable_windows_vss" : false, - "allow_manual_backup" : true, - "backup_cache_content" : { - "cached_enabled" : false - }, - "backup_external" : false, - "backup_type" : 2, - "bandwidth" : 0, - "bandwidth_content" : { - "backup_bandwidth_base" : 0, - "backup_bandwidth_number" : 0, - "enable" : false - }, - "cbt_enable_mode" : 1, - "connection_timeout" : 0, - "custom_volume" : [], - "datastore_reserved_percentage" : 0, - "dedup_api_restore" : true, - "dedup_path" : "", - "device_count" : 1, - "devices" : [{ - "agent_can_backup" : true, - "agent_driver_status" : "enable", - "agent_status" : "online", - "agent_token" : "xxxxxxxxxxxxxxx", - "agentless_auth_policy" : 0, - "auto_discovery" : false, - "backup_type" : 2, - "create_time" : 1709413484, - "device_id" : 5, - "device_uuid" : "xxxxxxxxxxxx", - "driver_status" : null, - "dsm_model" : "", - "dsm_unique" : "", - "host_ip" : "192.168.0.63", - "host_name" : "xxxxxxxxx", - "host_port" : 0, - "hypervisor_id" : "", - "inventory_id" : 0, - "login_password" : "", - "login_time" : 1709413493, - "login_user" : "xxxx", - "login_user_id" : 1026, - "os_name" : "Windows 11(64-bit)", - "platform_type" : 1, - "vm_moid_path" : "" - }], - "enable_app_aware_bkp" : false, - "enable_compress_transfer" : true, - "enable_datastore_aware" : false, - "enable_dedup" : true, - "enable_encrypt_transfer" : true, - "enable_notify" : false, - "enable_shutdown_after_complete" : false, - "enable_verification" : false, - "enable_wake_up" : false, - "enable_windows_working_state" : false, - "last_result" : { + { + "data": { + "has_devices": true, + "has_dsm_agent": false, + "has_hyperv_inventories": false, + "has_linux_agent": false, + "has_mac_agent": false, + "has_vmware_inventories": false, + "has_windows_agent": true, + "tasks": [{ + "agentless_backup_path" : "", + "agentless_backup_policy" : 0, + "agentless_enable_block_transfer" : false, + "agentless_enable_dedup" : false, + "agentless_enable_windows_vss" : false, + "allow_manual_backup" : true, + "backup_cache_content" : { + "cached_enabled" : false + }, + "backup_external" : false, "backup_type" : 2, - "detail_path" : "", - "error_count" : 0, - "job_action" : 1, - "none_count" : 0, - "result_id" : 593, - "status" : 2, - "success_count" : 0, - "task_config" : { - "device_list" : [ - { - "device_id" : 5, - "host_name" : "xxxxxxxxxx" - } - ] + "bandwidth" : 0, + "bandwidth_content" : { + "backup_bandwidth_base" : 0, + "backup_bandwidth_number" : 0, + "enable" : false }, + "cbt_enable_mode" : 1, + "connection_timeout" : 0, + "custom_volume" : [], + "datastore_reserved_percentage" : 0, + "dedup_api_restore" : true, + "dedup_path" : "", + "device_count" : 1, + "devices" : [{ + "agent_can_backup" : true, + "agent_driver_status" : "enable", + "agent_status" : "online", + "agent_token" : "xxxxxxxxxxxxxxx", + "agentless_auth_policy" : 0, + "auto_discovery" : false, + "backup_type" : 2, + "create_time" : 1709413484, + "device_id" : 5, + "device_uuid" : "xxxxxxxxxxxx", + "driver_status" : null, + "dsm_model" : "", + "dsm_unique" : "", + "host_ip" : "192.168.0.63", + "host_name" : "xxxxxxxxx", + "host_port" : 0, + "hypervisor_id" : "", + "inventory_id" : 0, + "login_password" : "", + "login_time" : 1709413493, + "login_user" : "xxxx", + "login_user_id" : 1026, + "os_name" : "Windows 11(64-bit)", + "platform_type" : 1, + "vm_moid_path" : "" + }], + "enable_app_aware_bkp" : false, + "enable_compress_transfer" : true, + "enable_datastore_aware" : false, + "enable_dedup" : true, + "enable_encrypt_transfer" : true, + "enable_notify" : false, + "enable_shutdown_after_complete" : false, + "enable_verification" : false, + "enable_wake_up" : false, + "enable_windows_working_state" : false, + "last_result" : { + "backup_type" : 2, + "detail_path" : "", + "error_count" : 0, + "job_action" : 1, + "none_count" : 0, + "result_id" : 593, + "status" : 2, + "success_count" : 0, + "task_config" : { + "device_list" : [ + { + "device_id" : 5, + "host_name" : "xxxxxxxxxx" + } + ] + }, + "task_id" : 5, + "task_name" : "xxxxxxxxxxx", + "time_end" : 1741946439, + "time_start" : 1741946267, + "transfered_bytes" : 2122801152, + "warning_count" : 0 + }, + "last_version_id" : 163, + "max_concurrent_devices" : 0, + "next_trigger_time" : 1742176800, + "pre_post_script_setting" : { + "post_script_path" : "", + "pre_script_path" : "", + "script_exec_mode" : 0 + }, + "repo_dir" : "@ActiveBackup", + "retention_policy" : { + "gfs_days" : "7", + "gfs_months" : "12", + "gfs_weeks" : "4", + "gfs_years" : "3", + "keep_all" : false, + "keep_versions" : 10 + }, + "sched_content" : { + "backup_window" : "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "enable_backup_window" : false, + "is_continuous_paused" : false, + "repeat_hour" : 0, + "repeat_type" : "Weekly", + "run_hour" : 3, + "run_min" : 0, + "run_weekday" : [ 1, 2, 3, 4, 5 ], + "schedule_setting_type" : 1, + "start_day" : 0, + "start_month" : 0, + "start_year" : 0 + }, + "sched_id" : 0, + "sched_modify_time" : 1709413646, + "share_compressed" : false, + "share_name" : "ActiveBackupforBusiness", + "source_type" : 2, + "storage_compress_algorithm" : 0, + "storage_encrypt_algorithm" : 0, + "storage_id" : 1, + "target_dir" : "xxxxxxxxxxx", + "target_status" : "online", "task_id" : 5, - "task_name" : "xxxxxxxxxxx", - "time_end" : 1741946439, - "time_start" : 1741946267, - "transfered_bytes" : 2122801152, - "warning_count" : 0 - }, - "last_version_id" : 163, - "max_concurrent_devices" : 0, - "next_trigger_time" : 1742176800, - "pre_post_script_setting" : { - "post_script_path" : "", - "pre_script_path" : "", - "script_exec_mode" : 0 - }, - "repo_dir" : "@ActiveBackup", - "retention_policy" : { - "gfs_days" : "7", - "gfs_months" : "12", - "gfs_weeks" : "4", - "gfs_years" : "3", - "keep_all" : false, - "keep_versions" : 10 - }, - "sched_content" : { - "backup_window" : "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", - "enable_backup_window" : false, - "is_continuous_paused" : false, - "repeat_hour" : 0, - "repeat_type" : "Weekly", - "run_hour" : 3, - "run_min" : 0, - "run_weekday" : [ 1, 2, 3, 4, 5 ], - "schedule_setting_type" : 1, - "start_day" : 0, - "start_month" : 0, - "start_year" : 0 - }, - "sched_id" : 0, - "sched_modify_time" : 1709413646, - "share_compressed" : false, - "share_name" : "ActiveBackupforBusiness", - "source_type" : 2, - "storage_compress_algorithm" : 0, - "storage_encrypt_algorithm" : 0, - "storage_id" : 1, - "target_dir" : "xxxxxxxxxxx", - "target_status" : "online", - "task_id" : 5, - "task_name" : "xxx", - "unikey" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", - "verification_policy" : 120, - "version_count" : 2, - "versions" : [ - { - "crypto_key_id" : 0, - "data_format" : 1, - "folder_name" : "ActiveBackup_2025-03-14_105745", - "is_snapshot" : true, - "locked" : false, - "status" : 3, - "time_end" : 1741946439, - "time_start" : 1741946267, - "used_size" : 0, - "version_id" : 163 - }, - { - "crypto_key_id" : 0, - "data_format" : 1, - "folder_name" : "ActiveBackup_2025-03-13_211215", - "is_snapshot" : true, - "locked" : false, - "status" : 3, - "time_end" : 1741901184, - "time_start" : 1741896737, - "used_size" : 0, - "version_id" : 162 - }, - ], - "view_type" : "", - "vm_folder" : null - }], - "total": 1 - }, - "success": true -} -``` + "task_name" : "xxx", + "unikey" : "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + "verification_policy" : 120, + "version_count" : 2, + "versions" : [ + { + "crypto_key_id" : 0, + "data_format" : 1, + "folder_name" : "ActiveBackup_2025-03-14_105745", + "is_snapshot" : true, + "locked" : false, + "status" : 3, + "time_end" : 1741946439, + "time_start" : 1741946267, + "used_size" : 0, + "version_id" : 163 + }, + { + "crypto_key_id" : 0, + "data_format" : 1, + "folder_name" : "ActiveBackup_2025-03-13_211215", + "is_snapshot" : true, + "locked" : false, + "status" : 3, + "time_end" : 1741901184, + "time_start" : 1741896737, + "used_size" : 0, + "version_id" : 162 + }, + ], + "view_type" : "", + "vm_folder" : null + }], + "total": 1 + }, + "success": true + } + ```
@@ -711,89 +710,48 @@ Dictionary containing a list of tasks. ### `list_logs` -Get logs from the package, tasks and devices. From `[Activities -> Log]` screen in ABB. -For specific task logs `[Task List -> Details -> Log]`, specify `task_id` parameter. +Get logs from the package, tasks and devices. + #### Internal API
`SYNO.ActiveBackup.Log`
-#### Parameters -
-**_task_id_** `int` -Get logs of specific task. Defaults to `-1` (all logs - package/tasks/devices) - -**_log_level_** `str` -Type of logs to return. Defaults to `""` (all types). -Possible values: -- `"error"` -- `"warning"` -- `"information"` - -Note that values are different when returned by the API. -Return values mappings: -- 0 -> `error` -- 1 -> `warning` -- 2 -> `information` - -**_keyword_** `str` -Keyword used to filter the results. Defaults to `""`. - -**_from_date_** `int` -Date from which the results will start. Format must be epoch date in seconds. Defaults to `0` (no time limit). - -**_to_date_** `int` -Date until which the results will start. Format must be epoch date in seconds. Defaults to `0` (no time limit). - -**_offset_** `int` -Offset results by this value. Defaults to `0`. - -**_limit_** `int` -Amount of results to be returned. Defaults to `200`. - - -
-#### Returns -
-`dict[str, object]` -Dictionary containing a list of logs. - -
#### Example return
Click to expand ```json -{ - "count": 1, - "logs": [ - { - "backup_type": 4, - "device_id": 6, - "device_name": "xxxx", - "error_code": 0, - "log_id": 5525, - "log_level": 0, - "log_time": 1741897498, - "log_type": 1104, - "other_params": { + { + "count": 1, + "logs": [ + { "backup_type": 4, "device_id": 6, "device_name": "xxxx", - "platform_type": 0, + "error_code": 0, + "log_id": 5525, + "log_level": 0, + "log_time": 1741897498, + "log_type": 1104, + "other_params": { + "backup_type": 4, + "device_id": 6, + "device_name": "xxxx", + "platform_type": 0, + "task_id": 8, + "task_name": "xxxxxxxx", + "user_id": 0, + "user_name": "" + }, + "result_id": 592, "task_id": 8, "task_name": "xxxxxxxx", "user_id": 0, "user_name": "" - }, - "result_id": 592, - "task_id": 8, - "task_name": "xxxxxxxx", - "user_id": 0, - "user_name": "" - } - ] -} -``` + } + ] + } + ```
@@ -812,33 +770,34 @@ Return the history of task execution. #### Parameters
**_task_id_** `int` -Get logs of specific task. Defaults to `-1` (all tasks) +Get logs of specific task. Defaults to `-1` (all tasks). **_status_** `str` Return only tasks matching the status provided. Defaults to `""` (all status). -Possible values: +Possible values: - `"success"` - `"partial_success"` - `"fail"` - `"cancel"` - -Note that values are different when returned by the API. +Note that values are different when returned by the API. Return values mappings: - `2` -> `success` - `3` -> `partial_success` - `4` -> `fail` - `5` -> `cancel` +**_keyword_** `str` +Keyword used to filter the results. Defaults to `""`. + **_backup_type_** `str` Return only tasks matching the device type provided. Defaults to `""` (all device types). -Possible values: +Possible values: - `"vm"` - `"pc"` - `"physical_server"` - `"file_server"` - `"nas"` - -Note that values are different when returned by the API. +Note that values are different when returned by the API. Return values mappings: - `1` -> `vm` - `2` -> `pc` @@ -848,7 +807,7 @@ Return values mappings: **_action_type_** `str` Return only tasks matching the task type provided. Defaults to `""` (all task types). -Possible values: +Possible values: - `"backup"` - `"dedup_data"` - `"restore"` @@ -858,8 +817,7 @@ Possible values: - `"delete_host"` - `"relink"` - `"create_task"` - -Note that values are different when returned by the API. +Note that values are different when returned by the API. Return values mappings: - `1` -> `backup` - `1048576` -> `dedup_data` @@ -871,9 +829,6 @@ Return values mappings: - `2097152` -> `relink` - `268435456` -> `create_task` -**_keyword_** `str` -Keyword used to filter the results. Defaults to `""`. - **_from_date_** `int` Date from which the results will start. Format must be epoch date in seconds. Defaults to `0` (no time limit). @@ -898,37 +853,37 @@ Dictionary containing a list of results.
Click to expand ```json -{ - "data": { - "count": 1, - "results": [ - { - "backup_type": 2, - "detail_path": "", - "error_count": 0, - "job_action": 131072, - "none_count": 0, - "result_id": 594, - "status": 2, - "success_count": 1, - "task_config": { - "device_list": [ - { - "host_name": "xxxxxxx" - } - ] + { + "data": { + "count": 1, + "results": [ + { + "backup_type": 2, + "detail_path": "", + "error_count": 0, + "job_action": 131072, + "none_count": 0, + "result_id": 594, + "status": 2, + "success_count": 1, + "task_config": { + "device_list": [ + { + "host_name": "xxxxxxx" + } + ] + }, + "task_id": 5, + "task_name": "xxxxxxxxxxx", + "time_end": 1741952422, + "time_start": 1741952402, + "warning_count": 0 }, - "task_id": 5, - "task_name": "xxxxxxxxxxx", - "time_end": 1741952422, - "time_start": 1741952402, - "warning_count": 0 - }, - ] - }, - "success": true -} -``` + ] + }, + "success": true + } + ```
@@ -937,7 +892,7 @@ Dictionary containing a list of results. ### `result_details` -Get details of a task result log. `result_id` can be retrieved from `list_logs()` function. +Get details of a task result log. #### Internal API
@@ -988,7 +943,7 @@ Dictionary containing a list of result details. "other_params": { "fs_error": -65, "os_name": "smb", - "path": "/D", + "path": "abc", "task_id": 8 }, "result_detail_id": 9526, @@ -1038,53 +993,53 @@ A dictionary containing a list of storage devices.
Click to expand ```json -{ - "data" : { - "storages" : [ - { - "automount_iv" : "", - "automount_location" : "", - "backup_tasks" : [], - "compacting" : false, - "compacting_percentage" : 0, - "compressed_size" : 0, - "dedup_size" : 1617010274304, - "delete_tasks" : [], - "delete_versions" : [], - "device_count" : 4, - "device_info" : { - "agentless_count" : 1, - "agentless_size" : 0, - "dsm_count" : 0, - "dsm_size" : 0, - "pc_count" : 2, - "pc_size" : 6128863440896, - "server_count" : 1, - "server_size" : 0, - "vm_count" : 0, - "vm_size" : 0 - }, - "fs_name" : "btrfs", - "fs_type" : 3, - "mounted" : true, - "relink_state" : { - "alive" : false, - "owner" : true, - "state" : 0 - }, - "repo_dir" : "@ActiveBackup", - "share_name" : "ActiveBackupforBusiness", - "storage_compress_algorithm" : 0, - "storage_encrypt_algorithm" : 0, - "storage_id" : 1, - "vol_name" : "Volume 3", - "volume_path" : "/volume3" - } - ] - }, - "success" : true - } -``` + { + "data" : { + "storages" : [ + { + "automount_iv" : "", + "automount_location" : "", + "backup_tasks" : [], + "compacting" : false, + "compacting_percentage" : 0, + "compressed_size" : 0, + "dedup_size" : 1617010274304, + "delete_tasks" : [], + "delete_versions" : [], + "device_count" : 4, + "device_info" : { + "agentless_count" : 1, + "agentless_size" : 0, + "dsm_count" : 0, + "dsm_size" : 0, + "pc_count" : 2, + "pc_size" : 6128863440896, + "server_count" : 1, + "server_size" : 0, + "vm_count" : 0, + "vm_size" : 0 + }, + "fs_name" : "btrfs", + "fs_type" : 3, + "mounted" : true, + "relink_state" : { + "alive" : false, + "owner" : true, + "state" : 0 + }, + "repo_dir" : "@ActiveBackup", + "share_name" : "ActiveBackupforBusiness", + "storage_compress_algorithm" : 0, + "storage_encrypt_algorithm" : 0, + "storage_id" : 1, + "vol_name" : "Volume 3", + "volume_path" : "/volume3" + } + ] + }, + "success" : true + } + ```
@@ -1093,7 +1048,7 @@ A dictionary containing a list of storage devices. ### `backup_task_run` -Trigger a backup event for the given tasks. +Trigger a backup event for the given tasks. #### Internal API
@@ -1103,7 +1058,7 @@ Trigger a backup event for the given tasks. #### Parameters
**_task_ids_** `list[int]` -List of task IDs to trigger the backup event. +List of task IDs to trigger the backup event. Even if only one task is specified, a list has to be passed as argument. @@ -1118,10 +1073,10 @@ Dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1140,7 +1095,7 @@ Cancel specified ongoing task. #### Parameters
**_task_ids_** `list[int]` -List of task IDs to trigger the cancellation event. +List of task IDs to trigger the cancellation event. Even if only one task is specified, a list has to be passed as argument. @@ -1155,10 +1110,10 @@ Dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1182,7 +1137,7 @@ Remove the given tasks from ABB. #### Parameters
**_task_ids_** `list[int]` -List of task IDs to remove. +List of task IDs to remove. Even if only one task is specified, a list has to be passed as argument. @@ -1197,10 +1152,10 @@ Dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -1241,10 +1196,10 @@ Dictionary containing the result of the operation.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
diff --git a/documentation/docs/apis/classes/core_backup.md b/documentation/docs/apis/classes/core_backup.md index 49c03d7b..246bd16c 100644 --- a/documentation/docs/apis/classes/core_backup.md +++ b/documentation/docs/apis/classes/core_backup.md @@ -14,16 +14,29 @@ This API is partially documented or under construction. ::: ## Overview - +Synology Hyper Backup API. ## Methods ### `backup_repository_get` -Get repository information for given task. +Get repository information for a given task. #### Internal API
`SYNO.Backup.Repository`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +Repository information. + +
@@ -38,6 +51,12 @@ Get a list of all present repositories in Hyper Backup. `SYNO.Backup.Repository`
+#### Returns +
+`dict[str, object] or str` +List of repositories. + +
@@ -52,6 +71,12 @@ Get current restoring information and a list of present tasks in Hyper Backup. `SYNO.Backup.Task`
+#### Returns +
+`dict[str, object] or str` +List of tasks and restoring information. + +
@@ -59,13 +84,26 @@ Get current restoring information and a list of present tasks in Hyper Backup. ### `backup_task_status` -Get status and state of task. +Get status and state of a task. #### Internal API
`SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +Status and state information. + +
@@ -73,13 +111,26 @@ Get status and state of task. ### `backup_task_get` -Get detailed task information. +Get detailed task information. #### Internal API
`SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +Task information. + +
@@ -94,6 +145,19 @@ Get last result summary information of a task. `SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +Last result summary. + +
@@ -108,6 +172,19 @@ If the task is not in backupable state, the API will return an error, usually 44 `SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -122,6 +199,19 @@ If the task is not running, the API will return an error, usually 44xx. `SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -136,6 +226,19 @@ If the task is not running or not yet suspendable, the API will return an error, `SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -150,6 +253,19 @@ If the task is not suspended, the request will not fail, and will fail to discar `SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -157,13 +273,26 @@ If the task is not suspended, the request will not fail, and will fail to discar ### `backup_task_resume` -Discard currently suspended backup task. +Resume currently suspended backup task. If the task is not suspended, the request will not fail, and will fail to resume the task, leaving the task state as "Failed". #### Internal API
`SYNO.Backup.Task`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -174,12 +303,25 @@ If the task is not suspended, the request will not fail, and will fail to resume Remove one or more backup tasks. Data in destination will not be removed. It is still possible to relink the task using the original .hbk file. The API requires an array of tasks to remove, it should be passed as a string with the following format: -`task_id_list = '[29]'` || `task_id_list = '[29,15]'` +`task_id_list = '[29]'` or `task_id_list = '[29,15]'` #### Internal API
`SYNO.Backup.Task`
+#### Parameters +
+**_task_id_list_** `str` +List of task IDs as a string. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -188,12 +330,25 @@ The API requires an array of tasks to remove, it should be passed as a string wi ### `integrity_check_run` Run integrity check for backup task. -If the task is running, the request will not fail, and will fail to perform the integrity check due to target is busy. +If the task is running, the request will not fail, and will fail to perform the integrity check due to target being busy. #### Internal API
`SYNO.Backup.Target`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -208,6 +363,19 @@ If integrity check is not running, the API will return an error, usually 44xx. `SYNO.Backup.Target`
+#### Parameters +
+**_task_id_** `str` +Task ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -222,6 +390,31 @@ Get Hyper Backup UI logs. `SYNO.SDS.Backup.Client.Common.Log`
+#### Parameters +
+**_limit_** `int` +Maximum number of logs to return (default is 1000). + +**_offset_** `int` +Offset for pagination (default is 0). + +**_filter_keyword_** `str` +Keyword to filter logs (default is ''). + +**_filter_date_from_** `int` +Start date in epoch format (default is 0). + +**_filter_date_to_** `int` +End date in epoch format (default is 0). + + +
+#### Returns +
+`dict[str, object] or str` +Logs information. + +
@@ -236,6 +429,12 @@ List all available targets in Vault. `SYNO.Backup.Service.VersionBackup.Target`
+#### Returns +
+`dict[str, object]` +List of available targets. + +
@@ -243,13 +442,19 @@ List all available targets in Vault. ### `vault_concurrency_get` -Get number of concurrent tasks allowed to run in HB Vault. Default value is 2. +Get number of concurrent tasks allowed to run in HB Vault. #### Internal API
`SYNO.Backup.Service.VersionBackup.Config`
+#### Returns +
+`dict[str, object]` +Number of concurrent tasks (default is 2). + +
@@ -257,13 +462,26 @@ Get number of concurrent tasks allowed to run in HB Vault. Default value is 2. ### `vault_concurrency_set` -Set number of concurrent tasks allowed to run in HB Vault. Default value is 2. +Set number of concurrent tasks allowed to run in HB Vault. #### Internal API
`SYNO.Backup.Service.VersionBackup.Config`
+#### Parameters +
+**_parallel_backup_limit_** `int` +Number of concurrent tasks (default is 2). + + +
+#### Returns +
+`dict[str, object]` +API response. + +
@@ -271,13 +489,26 @@ Set number of concurrent tasks allowed to run in HB Vault. Default value is 2. ### `vault_target_settings_get` -Get settings of target. +Get settings of a target. #### Internal API
`SYNO.Backup.Service.VersionBackup.Target`
+#### Parameters +
+**_target_id_** `int` +Target ID. + + +
+#### Returns +
+`dict[str, object]` +Target settings. + +
@@ -285,13 +516,26 @@ Get settings of target. ### `vault_task_statistics_get` -Get statistics for given task. +Get statistics for a given task. #### Internal API
`SYNO.SDS.Backup.Server.Common.Statistic`
+#### Parameters +
+**_task_id_** `int` +Task ID. + + +
+#### Returns +
+`dict[str, object]` +Task statistics. + +
@@ -299,13 +543,32 @@ Get statistics for given task. ### `vault_target_logs_get` -Get logs for given task. +Get logs for a given target. #### Internal API
`SYNO.SDS.Backup.Server.Common.Log`
+#### Parameters +
+**_target_id_** `int` +Target ID. + +**_limit_** `int` +Maximum number of logs to return (default is 1000). + +**_offset_** `int` +Offset for pagination (default is 0). + + +
+#### Returns +
+`dict[str, object]` +Logs information. + +
diff --git a/documentation/docs/apis/classes/core_certificate.md b/documentation/docs/apis/classes/core_certificate.md index db61e70e..736729ef 100644 --- a/documentation/docs/apis/classes/core_certificate.md +++ b/documentation/docs/apis/classes/core_certificate.md @@ -14,9 +14,46 @@ This API is not documented yet. ::: ## Overview - +Synology DSM Core Certificate API Wrapper. + +This class provides methods to interact with the Synology DSM Core Certificate API, +allowing management of SSL certificates on a Synology NAS. + +Parameters +---------- +ip_address : str + IP address or hostname of the Synology NAS. +port : str + Port number to connect to. +username : str + Username for authentication. +password : str + Password for authentication. +secure : bool, optional + Use HTTPS if True, HTTP if False (default is False). +cert_verify : bool, optional + Verify SSL certificates (default is False). +dsm_version : int, optional + DSM version (default is 7). +debug : bool, optional + Enable debug output (default is True). +otp_code : Optional[str], optional + One-time password for 2FA (default is None). ## Methods ### `list_cert` +List all certificates. + +#### Internal API +
+`SYNO.Core.Certificate` +
+ +#### Returns +
+`dict[str, object]` +List of certificates. + +
@@ -24,6 +61,26 @@ This API is not documented yet. ### `set_default_cert` +Set a certificate as the default. + +#### Internal API +
+`SYNO.Core.Certificate` +
+ +#### Parameters +
+**_cert_id_** `str` +Certificate ID to set as default. + + +
+#### Returns +
+`dict[str, object]` +API response. + +
@@ -31,6 +88,26 @@ This API is not documented yet. ### `delete_certificate` +Delete one or more certificates. + +#### Internal API +
+`SYNO.Core.Certificate` +
+ +#### Parameters +
+**_ids_** `str or list[str]` +Certificate ID or list of IDs to delete. + + +
+#### Returns +
+`dict[str, object]` +API response. + +
@@ -38,6 +115,41 @@ This API is not documented yet. ### `upload_cert` +Upload a certificate to the Synology NAS. + +#### Internal API +
+`SYNO.Core.Certificate` +
+ +#### Parameters +
+**_serv_key_** `str` +Path to the server key file (default is "server.key"). + +**_ser_cert_** `str` +Path to the server certificate file (default is "server.crt"). + +**_ca_cert_** `Optional[str]` +Path to the CA certificate file (default is None). + +**_set_as_default_** `bool` +Set as default certificate after upload (default is True). + +**_cert_id_** `Optional[str]` +Certificate ID to update (default is None). + +**_desc_** `Optional[str]` +Description for the certificate (default is None). + + +
+#### Returns +
+`tuple[int, dict[str, object]]` +HTTP status code and API response. + +
@@ -45,6 +157,29 @@ This API is not documented yet. ### `set_certificate_for_service` +Set a certificate for a specific DSM service. + +#### Internal API +
+`SYNO.Core.Certificate.Service` +
+ +#### Parameters +
+**_cert_id_** `str` +Certificate ID to assign. + +**_service_name_** `str` +Name of the service (default is "DSM Desktop Service"). + + +
+#### Returns +
+`tuple[int, dict[str, object]]` +HTTP status code and API response. + +
@@ -69,7 +204,7 @@ The certificate ID to export. This can be found in the list_cert() method. #### Returns
`Optional[BytesIO]` -A BytesIO object containing the certificate archive. +A BytesIO object containing the certificate archive, or None if export fails.
diff --git a/documentation/docs/apis/classes/core_group.md b/documentation/docs/apis/classes/core_group.md index 7b8edfe8..5f777696 100644 --- a/documentation/docs/apis/classes/core_group.md +++ b/documentation/docs/apis/classes/core_group.md @@ -9,28 +9,42 @@ title: ✅ Group # Group ## Overview -Core Group API implementation. - -### Supported methods - - - **Getters** : - - Get all groups - - Get group members - - Get group shares permissions - - Get group shares quota - - Get group services speed limits - - - **Setters** : - - Set group name/description - - Set group share permissions - - Set group share quotas - - Set group service speed limit - - - **Actions** : - - Create new group - - Delete groups - - Add users to a group - - Remove users from a group +Core Group API implementation for Synology NAS. + +This class provides methods to manage groups, including: +- Retrieving group information, members, permissions, quotas, and speed limits. +- Modifying group name, description, share permissions, quotas, and speed limits. +- Creating and deleting groups. +- Adding and removing users from groups. + +Methods +------- +get_groups(offset=0, limit=-1, name_only=False) + Retrieve groups information. +get_users(group, in_group=True) + Retrieve users who are members or not members of a group. +get_speed_limits(group) + Retrieve bandwidth control settings for a group. +get_quota(group) + Retrieve quota settings for a group. +get_permissions(group) + Retrieve share permissions for a group. +set_group_info(group, new_name="", new_description="") + Change group name and/or description. +set_share_quota(group, share_quotas) + Set group quota for a given share. +set_share_permissions(group, permissions) + Set group permissions for a given share. +set_speed_limit(group, upload_limit, download_limit, protocol) + Set speed limit for a given share. +add_users(group, users) + Add users to a group. +remove_users(group, users) + Remove users from a group. +create(name, description="") + Create a new group. +delete(groups) + Delete specified groups. ## Methods ### `get_groups` Retrieve groups information. @@ -43,13 +57,13 @@ Retrieve groups information. #### Parameters
**_offset_** `int` -The offset of the groups to retrieve. Defaults to `0`. +The offset of the groups to retrieve. Defaults to 0. **_limit_** `int` -The maximum number of groups to retrieve. Defaults to `-1` (all groups). +The maximum number of groups to retrieve. Defaults to -1 (all groups). **_name_only_** `bool` -If `True`, returns only group names. If `False`, returns full group information. Defaults to `False`. +If True, returns only group names. If False, returns full group information. Defaults to False.
@@ -101,7 +115,7 @@ A dictionary containing the groups information. ### `get_users` -Retrieve users members or not of a group. +Retrieve users who are members or not members of a group. #### Internal API
@@ -114,9 +128,8 @@ Retrieve users members or not of a group. The group to list users from. **_in_group_** `bool` -Defaults to `True`. -If `True`, retrieves users who are members of the specified group. -If `False`, retrieves users who are not members of the group. +If True, retrieves users who are members of the specified group. +If False, retrieves users who are not members of the group. Defaults to True.
@@ -172,7 +185,7 @@ Retrieve bandwidth control settings for a given group. #### Parameters
-**_group_** `str ` +**_group_** `str` The group to retrieve settings for. @@ -183,6 +196,31 @@ The group to retrieve settings for. A dictionary containing the result of the request.
+#### Example return +
+Click to expand +```json +{ + "data": { + "bandwidths": [ + { + "download_limit_1": 0, + "download_limit_2": 0, + "name": "group_name", + "owner_type": "local_group", + "policy": "notexist", + "protocol": "FTP", + "protocol_ui": "FTP", + "schedule_plan": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", + "upload_limit_1": 0, + "upload_limit_2": 0 + }, + ] + }, + "success": true +} +``` +
@@ -199,14 +237,14 @@ Retrieve quota settings for a given group. #### Parameters
-**_group_** `str ` +**_group_** `str` The group to retrieve quota settings for.
#### Returns
-`dict[str, object] ` +`dict[str, object]` A dictionary containing the result of the request.
@@ -286,7 +324,7 @@ A dictionary containing the result of the request. "total": 1 }, "success": true -} +} ``` @@ -318,7 +356,7 @@ The new description of the group. Defaults to current value.
#### Returns
-`dict[str, object] ` +`dict[str, object]` A dictionary containing the result of the request.
@@ -354,27 +392,14 @@ Set group quota for a given share. **_group_** `str` The group to set the quota for. -**_share_quotas (list[dict[str, Any]])_** `` +**_share_quotas_** `list of dict` The quotas to set for the group. -Example: -```python -[ - { - "share": "web", - "quota": 1024, # in MB - }, - { - "share": "photo", - "quota": 5120, # in MB - } -] -```
#### Returns
-`dict[str, object] ` +`dict[str, object]` A dictionary containing the result of the request.
@@ -407,25 +432,8 @@ Set group permissions for a given share. **_group_** `str` The group to set the permissions for. -**_permissions_** `list[dict[str, object]]:` +**_permissions_** `list of dict` The permissions to set for the group. -Example: -```python -[ - { - "name": "web", - "is_readonly": False, - "is_writable": False, - "is_deny": True - }, - { - "name": "ActiveBackupforBusiness", - "is_readonly": False, - "is_writable": True, - "is_deny": False - } -] -```
@@ -451,13 +459,8 @@ A dictionary containing the result of the request. ### `set_speed_limit` -Set speed limit for a given share. -:::info - - Doesn't support **scheduled** speed limits, only on/off. - -::: - +Set speed limit for a given share. + #### Internal API
`SYNO.Core.BandwidthControl` @@ -475,13 +478,8 @@ The maximum upload speed in KB/s. The maximum download speed in KB/s. **_protocol_** `str` -The protocol to set the speed limit for. -Possible values: -- FileStation -- WebDAV -- FTP -- NetworkBackup (Rsync) -- CloudStation (Synology Drive) +The protocol to set the speed limit for. Possible values: +FileStation, WebDAV, FTP, NetworkBackup (Rsync), CloudStation (Synology Drive).
@@ -521,10 +519,10 @@ Add users to a group. #### Parameters
-**_group_** `str ` +**_group_** `str` The group to add users to. -**_users_** `list[str]` +**_users_** `list of str` The users to add to the group. @@ -561,10 +559,10 @@ Remove users from a group. #### Parameters
-**_group_** `str ` +**_group_** `str` The group to remove users from. -**_users_** `list[str]` +**_users_** `list of str` The users to remove from the group. @@ -592,7 +590,7 @@ A dictionary containing the result of the request. ### `create` -Create group. +Create a new group. #### Internal API
@@ -611,7 +609,7 @@ Description to assign to the group. Defaults to empty string.
#### Returns
-`dict[str, object] ` +`dict[str, object]` A dictionary containing the result of the request.
@@ -644,14 +642,14 @@ Delete specified groups. #### Parameters
-**_groups_** `list[str]` +**_groups_** `list of str` The groups to delete.
#### Returns
-`dict[str, object] ` +`dict[str, object]` A dictionary containing the result of the request.
diff --git a/documentation/docs/apis/classes/core_package.md b/documentation/docs/apis/classes/core_package.md index 1e558c9d..f9ce9635 100644 --- a/documentation/docs/apis/classes/core_package.md +++ b/documentation/docs/apis/classes/core_package.md @@ -14,10 +14,53 @@ This API is partially documented or under construction. ::: ## Overview -Core Package API implementation. +Core Package API implementation for Synology NAS. + +This class provides methods to manage packages, including: +- Listing installed and installable packages. +- Installing, upgrading, and uninstalling packages. +- Uploading package files. +- Configuring package center settings. + +Methods +------- +get_package(package_id, additional) + Get information about a package. +list_installed(additional, ignore_hidden) + List installed packages. +list_installable() + List installable packages. +get_package_center_settings() + Get package center settings. +set_package_center_settings(...) + Set package center settings. +get_package_center_infos() + Get package center information. +feasibility_check_install(packages) + Check if installation is possible. +download_package(url, package_id, checksum, filesize) + Start download of a package. +get_dowload_package_status(task_id) + Get current download status of a package. +check_installation_from_download(task_id) + Get info about downloaded package file. +upload_package_file(file_path, verify, progress_bar, additional) + Upload a file for installing a package. +get_default_install_volume() + Get default install volume for packages. +check_installation(...) + Check installation of a package. +upgrade_package(...) + Upgrade an existing package. +install_package(...) + Install a package that is already downloaded. +uninstall_package(package_id) + Uninstall a package. +easy_install(package_id, volume_path, install_dependencies) + Execute an easy installation process of a package. ## Methods ### `get_package` -Get infos of a package +Get infos of a package. #### Internal API
@@ -27,19 +70,19 @@ Get infos of a package #### Parameters
**_package_id_** `str` -Package ID +Package ID. **_additional_** `List[str]` -Additional field to retrieves. Defaults to `[]` +Additional field to retrieves. Defaults to `[]`. All filed known are: -`["status","dsm_apps"]` +`["status","dsm_apps"]`.
#### Returns
`dict` -Informations about the package +Informations about the package.
#### Example return @@ -71,7 +114,7 @@ Informations about the package ### `list_installed` -List installed packages +List installed packages. #### Internal API
@@ -82,7 +125,7 @@ List installed packages
**_additional_** `list[str]` Additional fields to retrieve. Defaults to `[]`. -All fields known are: +All fields known are: `["description", "description_enu", "dependent_packages", "beta", "distributor", "distributor_url", "maintainer", "maintainer_url", "dsm_apps", "dsm_app_page", "dsm_app_launch_name","report_beta_url", "support_center", "startable", "installed_info", "support_url", "is_uninstall_pages","install_type", @@ -90,14 +133,14 @@ All fields known are: "url","available_operation"]`. **_ignore_hidden_** `bool` -TODO: Write description +Whether to ignore hidden packages.
#### Returns
`dict` -List of packages installed on the NAS +List of packages installed on the NAS.
#### Example return @@ -110,13 +153,13 @@ List of packages installed on the NAS { "additional": { "install_type": "" - }, - "id": "ActiveBackup-Office365", - "name": "Active Backup for Microsoft 365", - "timestamp": 1738880043640, - "version": "2.5.5-14034" - } - ] + }, + "id": "ActiveBackup-Office365", + "name": "Active Backup for Microsoft 365", + "timestamp": 1738880043640, + "version": "2.5.5-14034" + } + } }, "success": true } @@ -129,7 +172,7 @@ List of packages installed on the NAS ### `list_installable` -List installable packages +List installable packages. #### Internal API
@@ -139,7 +182,7 @@ List installable packages #### Returns
`dict` -List of beta_package, categories and packages available +List of beta_package, categories and packages available.
#### Example return @@ -164,7 +207,7 @@ List of beta_package, categories and packages available ### `get_package_center_settings` -Get package center settings +Get package center settings. #### Internal API
@@ -174,7 +217,7 @@ Get package center settings #### Returns
`dict` -List settings of the Package center +List settings of the Package center.
#### Example return @@ -225,7 +268,7 @@ List settings of the Package center ### `set_package_center_settings` -Set settings of the package center +Set settings of the package center. #### Internal API
@@ -235,33 +278,33 @@ Set settings of the package center #### Parameters
**_enable_email_** `bool` -Enable email notification +Enable email notification. -**_enable_dsm_** `bool ` -Enable desktop notification +**_enable_dsm_** `bool` +Enable desktop notification. **_enable_autoupdate_** `bool` -Update packages automatically +Update packages automatically. **_autoupdateall_** `bool` -Auto update all packages +Auto update all packages. **_autoupdateimportant_** `bool` -Auto update "important" packages +Auto update "important" packages. **_default_vol_** `str` -Default volume for installation, all your volumes or `"no_default_vol" = Always ask me` +Default volume for installation, all your volumes or `"no_default_vol" = Always ask me`. -**_udpate_channel_** `str` -"stable" => Disable beta packages -"beta" => Enable beta packages +**_update_channel_** `str` +"stable" => Disable beta packages. +"beta" => Enable beta packages.
#### Returns
`dict` -Return some settings +Return some settings.
#### Example return @@ -285,7 +328,7 @@ Return some settings ### `get_package_center_infos` -Get package center informations +Get package center informations. #### Internal API
@@ -295,9 +338,44 @@ Get package center informations #### Returns
`dict` -List of configs +List of configs.
+#### Example return +
+Click to expand +```json +{ + "data": { + "config": { + "auth_key": "------------------------------", + "blBetaChannel": false, + "blOtherServer": false, + "def_void": "", + "ds_build": "72806", + "ds_major": "7", + "ds_minor": "2", + "ds_timezone": "Amsterdam", + "ds_unique": "synology_r1000_723+", + "myPayBaseURL": "https://payment.synology.com", + "myds_id": "7886858", + "serial": "2260TPR7X30E6", + "success": true + }, + "prerelease": { + "agreed": true, + "success": true + }, + "term": { + "agreed_term_version": "0003", + "curr_term_version": "0003", + "success": true + } + }, + "success": true +} +``` +
@@ -305,7 +383,7 @@ List of configs ### `feasibility_check_install` -Check if installation is possible +Check if installation is possible. #### Internal API
@@ -315,14 +393,14 @@ Check if installation is possible #### Parameters
**_packages_** `List[str]` -List of package IDs to check for feasibility +List of package IDs to check for feasibility.
#### Returns
`dict` -_description_ +Feasibility check result.
#### Example return @@ -344,7 +422,7 @@ _description_ ### `download_package` -Start download of the package, return a taskId for check status +Start download of the package, return a taskId for check status. #### Internal API
@@ -354,23 +432,23 @@ Start download of the package, return a taskId for check status #### Parameters
**_url_** `str` -Url that can be retrieve from package info using `get_installable` function, in the `link` field +Url that can be retrieve from package info using `get_installable` function, in the `link` field. **_package_id_** `str` -Package ID that can be retrieve from package info using `get_installable` function, in the `id` field +Package ID that can be retrieve from package info using `get_installable` function, in the `id` field. **_checksum_** `str` -Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field +Checksum that can be retrieve from package info using `get_installable` function, in the `md5` field. **_filesize_** `str` -Filesize that can be retrieve from package info using `get_installable` function, in the `size` field +Filesize that can be retrieve from package info using `get_installable` function, in the `size` field.
#### Returns
`dict` -Retreive first progress of the download and the taskid used to check download status with `get_dowload_package_status` function +Retrieve first progress of the download and the taskid used to check download status with `get_dowload_package_status` function.
#### Example return @@ -393,7 +471,7 @@ Retreive first progress of the download and the taskid used to check download st ### `get_dowload_package_status` -Get current download status of the package +Get current download status of the package. #### Internal API
@@ -403,14 +481,14 @@ Get current download status of the package #### Parameters
**_task_id_** `str` -task ID retrieve from response of `download_package` function +Task ID retrieved from response of `download_package` function.
#### Returns
`dict` -Retrieve informations about the download, important info is the `progress` field +Retrieve informations about the download, important info is the `progress` field.
#### Example return @@ -444,7 +522,7 @@ Retrieve informations about the download, important info is the `progress` field ### `check_installation_from_download` -Get info about downloaded package file, response field is used for `check_installation` and `install_package` function +Get info about downloaded package file, response field is used for `check_installation` and `install_package` function. #### Internal API
@@ -454,14 +532,14 @@ Get info about downloaded package file, response field is used for `check_instal #### Parameters
**_task_id_** `str` -task ID retrieve from response of `download_package` function +Task ID retrieved from response of `download_package` function.
#### Returns
`dict` -Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function +Retrieve information about downloaded package installation file, response field is used for `check_installation` and `install_package` function.
#### Example return @@ -498,7 +576,7 @@ Retrieve information about downloaded package installation file, response field ### `upload_package_file` -Upload a file for install a package +Upload a file for install a package. #### Internal API
@@ -508,16 +586,16 @@ Upload a file for install a package #### Parameters
**_file_path_** `str` -File path +File path. **_verify_** `bool` -Use https. Defaults to `False` +Use https. Defaults to `False`. **_progress_bar_** `bool` -Enable progress bar in the terminal. Defaults to `True` +Enable progress bar in the terminal. Defaults to `True`. **_additional_** `list` -Additional field to retrieves. Defaults to `[]` +Additional field to retrieves. Defaults to `[]`. All fields know are: `["description","maintainer","distributor","startable","dsm_apps","status","install_reboot", "install_type","install_on_cold_storage","break_pkgs","replace_pkgs"]`. @@ -527,7 +605,7 @@ All fields know are: #### Returns
`dict` -Informations about the uploaded file for installation +Informations about the uploaded file for installation.
#### Example return @@ -569,7 +647,7 @@ Informations about the uploaded file for installation ### `get_default_install_volume` -Get default install volume for package +Get default install volume for package. #### Internal API
@@ -579,7 +657,7 @@ Get default install volume for package #### Returns
`dict` -Return default volume, if default volume is set to `Always ask me` it return error 4501 +Return default volume, if default volume is set to `Always ask me` it return error 4501.
#### Example return @@ -601,7 +679,7 @@ Return default volume, if default volume is set to `Always ask me` it return err ### `check_installation` -Check installation of the package on the default volume +Check installation of the package on the default volume. #### Internal API
@@ -611,26 +689,26 @@ Check installation of the package on the default volume #### Parameters
**_package_id_** `str` -Id of the package to install +Id of the package to install. **_install_type_** `str, optionnal` -Installation type, Defaults to `""`. TODO: Add description and possible types +Installation type, Defaults to `""`. TODO: Add description and possible types. **_install_on_cold_storage_** `bool` -Defaults to `False`. TODO: Add description +Defaults to `False`. TODO: Add description. **_blCheckDep_** `bool` -Defaults to `False`. TODO: Add description +Defaults to `False`. TODO: Add description. **_replacepkgs_** `dict` -Defaults to `{}`. TODO: Add description +Defaults to `{}`. TODO: Add description.
#### Returns
`dict` -List of usefull informations about volumes +List of usefull informations about volumes.
#### Example return @@ -674,69 +752,52 @@ List of usefull informations about volumes ### `upgrade_package` -Upgrade an existing package -Parameters - ---------- - task_id : str - Task id of the download or the upload file - check_codesign : bool, optional - Check signature of the source code of the package (is it a Synology one). Defaults to `False` - force : bool, optional - Force installation. Defaults to `False` - installrunpackage : bool, optional - Run package after installation. Defaults to `True` - extra_values : dict, optional - Extra values due to some package installation. Defaults to `{}` - All known extra values are: - - Surveillance station - ```json - { - "chkSVS_Alias": true, - "strSVS_Alias": "cam", - "chkSVS_HTTP": true, - "strSVS_HTTP": "9900", - "chkSVS_HTTPS": true, - "strSVS_HTTPS": "9901" - } - ``` - - Returns - ------- - dict - Message and some info about installation - - Example return - ---------- - ```json - { - "data": { - "message": "

Installation Successful!

-

:::note - - If Plex cannot access your media, verify user PlexMediaServer is granted permission in Control Panel.


- -::: - -Set access to your media share(s) by performing the following steps:

-1. Open Control Panel and select Shared Folder
-2. Select the share which contains your media and click Edit
-3. Click the Permissions tab
-4. Change the dropdown from Local Users to System internal user
-5. Check the Read/Write checkbox for the PlexMediaServer user
-6. Click Save to confirm the new permissions
-7. Repeat steps 2-6 for each share you want Plex Media Server to access
-", - "packageName": "Plex Media Server", - "worker_message": [] - }, - "success": true, - } - ``` +Upgrade an existing package. + #### Internal API
`SYNO.Core.Package.Installation`
+#### Parameters +
+**_task_id_** `str` +Task id of the download or the upload file. + +**_check_codesign_** `bool` +Check signature of the source code of the package (is it a Synology one). Defaults to `False`. + +**_force_** `bool` +Force installation. Defaults to `False`. + +**_installrunpackage_** `bool` +Run package after installation. Defaults to `True`. + +**_extra_values_** `dict` +Extra values due to some package installation. Defaults to `{}`. + + +
+#### Returns +
+`dict` +Message and some info about installation. + +
+#### Example return +
+Click to expand +```json +{ + "data": { + "message": "message", + "packageName": "Plex Media Server", + "worker_message": [] + }, + "success": true, +} +``` +
@@ -744,7 +805,7 @@ Set access to your media share(s) by performing the following steps:

### `install_package` -Install a package that is already downloaded +Install a package that is already downloaded. #### Internal API
@@ -754,44 +815,32 @@ Install a package that is already downloaded #### Parameters
**_package_id_** `str` -Id of the package to install +Id of the package to install. **_volume_path_** `str` -Volume path of the installation, can get from `check_installation` function +Volume path of the installation, can get from `check_installation` function. **_file_path_** `str` -File path of the installation, can get from `check_installation_from_download` function +File path of the installation, can get from `check_installation_from_download` function. **_check_codesign_** `bool` -Check signature of the source code of the package (is it a Synology one). Defaults to `False` +Check signature of the source code of the package (is it a Synology one). Defaults to `False`. **_force_** `bool` -Force installation. Defaults to `False` +Force installation. Defaults to `False`. **_installrunpackage_** `bool` -Run package after installation. Defaults to `True` +Run package after installation. Defaults to `True`. **_extra_values_** `dict` -Extra values due to some package installation. Defaults to `{}` -All known extra values are: -- Surveillance station -```json - { - "chkSVS_Alias": true, - "strSVS_Alias": "cam", - "chkSVS_HTTP": true, - "strSVS_HTTP": "9900", - "chkSVS_HTTPS": true, - "strSVS_HTTPS": "9901" - } -``` +Extra values due to some package installation. Defaults to `{}`.
#### Returns
`dict` -Message and some info about installation +Message and some info about installation.
#### Example return @@ -838,14 +887,14 @@ Message and some info about installation "data": { "packageName": "Text Editor", "worker_message": [] - }, - "method": "install", - "success": true, - "version": 1 - } - ] - }, - "success": true + }, + "method": "install", + "success": true, + "version": 1 + } + ] +}, +"success": true } ``` @@ -856,7 +905,7 @@ Message and some info about installation ### `uninstall_package` -Uninstall a package +Uninstall a package. #### Internal API
@@ -866,14 +915,14 @@ Uninstall a package #### Parameters
**_package_id_** `str` -Id of the package to uninstall +Id of the package to uninstall.
#### Returns
`dict` -Possible message to the user +Possible message to the user.
#### Example return @@ -896,26 +945,30 @@ Possible message to the user ### `easy_install` -Execute an "easy" installation process of the package +Execute an easy installation process of the package. +#### Internal API +
+`hotfix` +
#### Parameters
**_package_id_** `str` -Package ID to install +Package ID to install. **_volume_path_** `str` -Volume path where you want to install the package +Volume path where you want to install the package. **_install_dependencies_** `bool` -If you want to install dependencies. Defaults to `True` +If you want to install dependencies. Defaults to True.
#### Returns
-`dict` -Information about installation, same as `install_package` function +`dict[str, object]` +Information about installation, same as install_package function.
#### Example return @@ -962,14 +1015,14 @@ Information about installation, same as `install_package` function "data": { "packageName": "Text Editor", "worker_message": [] - }, - "method": "install", - "success": true, - "version": 1 - } - ] - }, - "success": true + }, + "method": "install", + "success": true, + "version": 1 + } + ] +}, +"success": true } ``` diff --git a/documentation/docs/apis/classes/core_share.md b/documentation/docs/apis/classes/core_share.md index f6c3acdc..763ee207 100644 --- a/documentation/docs/apis/classes/core_share.md +++ b/documentation/docs/apis/classes/core_share.md @@ -26,7 +26,7 @@ This API is partially documented or under construction. Core Share API implementation. ## Methods ### `validate_set` -Validate set of parameter for a new / modified shared folder +Validate set of parameter for a new / modified shared folder. #### Internal API
@@ -80,7 +80,7 @@ Success. ### `list_folders` -List all folders informations +List all folders informations. #### Internal API
@@ -138,7 +138,7 @@ A dictionary containing the shared folders information. ### `get_folder` -Get a folder by name +Get a folder by name. #### Internal API
@@ -189,7 +189,7 @@ A dictionary containing the shared folder information. ### `create_folder` -Create a new shared folder +Create a new shared folder. #### Internal API
@@ -225,18 +225,24 @@ Enable share cow. Defaults to `False`. **_enable_share_compress_** `bool` Enable share compress. Defaults to `False`. -**_share_quota_** `int, optional ` +**_share_quota_** `int` Share quota. Defaults to `0`. -**_name_org_** `str, optional ` +**_name_org_** `str` Defaults to `""`. +**_encryption_** `bool` +Enable encryption. Defaults to `False`. + +**_enc_passwd_** `str` +Encrypted password. Defaults to `""`. +
#### Returns
`dict` -Name of the created shared folder +Name of the created shared folder.
#### Example return @@ -257,7 +263,7 @@ Name of the created shared folder ### `delete_folders` -Delete folder(s) by name(s) +Delete folder(s) by name(s). #### Internal API
@@ -340,7 +346,7 @@ Share quota. Defaults to `0`. #### Returns
`dict` -Name of the created shared folder +Name of the created shared folder.
#### Example return @@ -357,6 +363,81 @@ Name of the created shared folder +--- + + +### `decrypt_folder` +Decrypt a given share. + +#### Internal API +
+`SYNO.Core.Share.Crypto` +
+ +#### Parameters +
+**_name_** `str` +The share name to decrypt. + +**_password_** `str` +The password to use for decrypting the share. + + +
+#### Returns +
+`dict` +Success. + +
+#### Example return +
+Click to expand +```json + { + "success": true + } + ``` +
+ + + +--- + + +### `encrypt_folder` +Encrypt a given share. + +#### Internal API +
+`SYNO.Core.Share.Crypto` +
+ +#### Parameters +
+**_name_** `str` +The share name to encrypt. + + +
+#### Returns +
+`dict` +Success. + +
+#### Example return +
+Click to expand +```json + { + "success": true + } + ``` +
+ + + --- @@ -365,7 +446,7 @@ Name of the created shared folder Core Share Permission API implementation. ## Methods ### `get_folder_permission_by_name` -Retrieve share permissions for a given folder filtered by permission name (sub string) +Retrieve share permissions for a given folder filtered by permission name (sub string). #### Internal API
@@ -400,8 +481,8 @@ All known values are: `["system", "local_user", "local_group", "ldap_user", "lda
#### Returns
-`dict ` -List of permission(s) on the folder +`dict` +List of permission(s) on the folder.
#### Example return @@ -467,7 +548,7 @@ All known values are: `["system", "local_user", "local_group", "ldap_user", "lda #### Returns
`dict` -All permissions on the folder +All permissions on the folder.
#### Example return @@ -544,26 +625,14 @@ The type of user group to set permissions for. All known values are: `["system", "local_user", "local_group", "ldap_user", "ldap_group"]`. **_permissions_** `dict` -The permissions to set for the folder. -Example: -```json -[ - { - "name":"guest", - "is_readonly":false, - "is_writable":true, - "is_deny":false, - "is_custom":false - } -] -``` +The permissions to set for the folder.
#### Returns
-`dict ` -Success +`dict` +Success.
#### Example return @@ -599,7 +668,7 @@ The group to list permissions for. #### Returns
`dict` -Permissions of a group on Shared folders +Permissions of a group on Shared folders.
#### Example return @@ -625,7 +694,7 @@ Permissions of a group on Shared folders "total": 1 }, "success": true -} +} ``` @@ -648,31 +717,14 @@ Set group permissions for a given share. The group to set the permissions for. **_permissions_** `list[dict[str, Any]]` -The permissions to set for the group. -Example: -``` -[ - { - "name": "web", - "is_readonly": False, - "is_writable": False, - "is_deny": True - }, - { - "name": "ActiveBackupforBusiness", - "is_readonly": False, - "is_writable": True, - "is_deny": False - } -] -``` +The permissions to set for the group.
#### Returns
`dict` -Success +Success.
#### Example return @@ -702,6 +754,12 @@ Initialize KeyManagerStore API. `SYNO.Core.Share.KeyManager.Store`
+#### Returns +
+`dict` +Not implemented yet. + +
@@ -709,6 +767,19 @@ Initialize KeyManagerStore API. ### `verify` +Not implemented yet. + +#### Internal API +
+`SYNO.Core.Share.KeyManager.Store` +
+ +#### Returns +
+`dict` +Not implemented yet. + +
@@ -716,8 +787,8 @@ Initialize KeyManagerStore API. ### `explore` -Explore KeyManagerStore API. Get list of existing stores - +Explore KeyManagerStore API. +Get list of existing stores. #### Internal API
`SYNO.Core.Share.KeyManager.Store` @@ -726,7 +797,7 @@ Explore KeyManagerStore API. Get list of existing stores #### Returns
`dict` -List of stores existing on the NAS +List of stores existing on the NAS.
#### Example return @@ -762,7 +833,7 @@ List KeyManagerStore API. #### Returns
`dict` -List of keys in the manager +List of keys in the manager.
#### Example return diff --git a/documentation/docs/apis/classes/core_sys_info.md b/documentation/docs/apis/classes/core_sys_info.md index da2ac1f0..c56fc982 100644 --- a/documentation/docs/apis/classes/core_sys_info.md +++ b/documentation/docs/apis/classes/core_sys_info.md @@ -14,9 +14,25 @@ This API is not documented yet. ::: ## Overview +Core System Information API implementation for Synology NAS. +This class provides methods to retrieve and manage system, network, hardware, +service, and package information from a Synology NAS. ## Methods ### `fileserv_smb` +Get SMB file service status. + +#### Internal API +
+`SYNO.Core.FileServ.SMB` +
+ +#### Returns +
+`dict[str, object] or str` +SMB file service status. + +
@@ -24,6 +40,19 @@ This API is not documented yet. ### `fileserv_afp` +Get AFP file service status. + +#### Internal API +
+`SYNO.Core.FileServ.AFP` +
+ +#### Returns +
+`dict[str, object] or str` +AFP file service status. + +
@@ -31,6 +60,19 @@ This API is not documented yet. ### `fileserv_nfs` +Get NFS file service status. + +#### Internal API +
+`SYNO.Core.FileServ.NFS` +
+ +#### Returns +
+`dict[str, object] or str` +NFS file service status. + +
@@ -38,6 +80,19 @@ This API is not documented yet. ### `fileserv_ftp` +Get FTP file service status. + +#### Internal API +
+`SYNO.Core.FileServ.FTP` +
+ +#### Returns +
+`dict[str, object] or str` +FTP file service status. + +
@@ -45,6 +100,19 @@ This API is not documented yet. ### `fileserv_sftp` +Get SFTP file service status. + +#### Internal API +
+`SYNO.Core.FileServ.FTP.SFTP` +
+ +#### Returns +
+`dict[str, object] or str` +SFTP file service status. + +
@@ -52,6 +120,19 @@ This API is not documented yet. ### `network_backup_info` +Get network backup service information. + +#### Internal API +
+`SYNO.Backup.Service.NetworkBackup` +
+ +#### Returns +
+`dict[str, object] or str` +Network backup service information. + +
@@ -59,6 +140,19 @@ This API is not documented yet. ### `bandwidth_control_protocol` +Get bandwidth control protocol information. + +#### Internal API +
+`SYNO.Core.BandwidthControl.Protocol` +
+ +#### Returns +
+`dict[str, object] or str` +Bandwidth control protocol information. + +
@@ -66,6 +160,19 @@ This API is not documented yet. ### `shared_folders_info` +Get shared folders information. + +#### Internal API +
+`SYNO.Core.Share` +
+ +#### Returns +
+`dict[str, object] or str` +Shared folders information. + +
@@ -73,6 +180,19 @@ This API is not documented yet. ### `services_status` +Get status of core services. + +#### Internal API +
+`SYNO.Core.Service` +
+ +#### Returns +
+`dict[str, object] or str` +Status of core services. + +
@@ -80,6 +200,19 @@ This API is not documented yet. ### `services_discovery` +Get service discovery information. + +#### Internal API +
+`SYNO.Core.FileServ.ServiceDiscovery` +
+ +#### Returns +
+`dict[str, object] or str` +Service discovery information. + +
@@ -87,6 +220,19 @@ This API is not documented yet. ### `file_transfer_status` +Get file transfer status. + +#### Internal API +
+`SYNO.Core.SyslogClient.FileTransfer` +
+ +#### Returns +
+`dict[str, object] or str` +File transfer status. + +
@@ -94,6 +240,19 @@ This API is not documented yet. ### `network_status` +Get network status. + +#### Internal API +
+`SYNO.Core.Network` +
+ +#### Returns +
+`dict[str, object] or str` +Network status. + +
@@ -101,6 +260,19 @@ This API is not documented yet. ### `web_status` +Get DSM web status. + +#### Internal API +
+`SYNO.Core.Web.DSM` +
+ +#### Returns +
+`dict[str, object] or str` +DSM web status. + +
@@ -108,6 +280,19 @@ This API is not documented yet. ### `current_connection` +Get current connection information. + +#### Internal API +
+`SYNO.Core.CurrentConnection` +
+ +#### Returns +
+`dict[str, object] or str` +Current connection information. + +
@@ -115,6 +300,19 @@ This API is not documented yet. ### `bandwidth_control_status` +Get bandwidth control status. + +#### Internal API +
+`SYNO.Core.BandwidthControl.Status` +
+ +#### Returns +
+`dict[str, object] or str` +Bandwidth control status. + +
@@ -122,6 +320,19 @@ This API is not documented yet. ### `sys_status` +Get system status. + +#### Internal API +
+`SYNO.Core.System.Status` +
+ +#### Returns +
+`dict[str, object] or str` +System status. + +
@@ -129,6 +340,19 @@ This API is not documented yet. ### `latest_logs` +Get latest system logs. + +#### Internal API +
+`SYNO.Core.SyslogClient.Status` +
+ +#### Returns +
+`dict[str, object] or str` +Latest system logs. + +
@@ -136,6 +360,19 @@ This API is not documented yet. ### `client_notify_settings_status` +Get client notification settings status. + +#### Internal API +
+`SYNO.Core.SyslogClient.Setting.Notify` +
+ +#### Returns +
+`dict[str, object] or str` +Client notification settings status. + +
@@ -143,6 +380,19 @@ This API is not documented yet. ### `get_security_scan_info` +Get security scan configuration. + +#### Internal API +
+`SYNO.Core.SecurityScan.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +Security scan configuration. + +
@@ -150,6 +400,19 @@ This API is not documented yet. ### `get_security_scan_rules` +Get security scan rules. + +#### Internal API +
+`SYNO.Core.SecurityScan.Status` +
+ +#### Returns +
+`dict[str, object] or str` +Security scan rules. + +
@@ -157,6 +420,19 @@ This API is not documented yet. ### `get_security_scan_status` +Get security scan status. + +#### Internal API +
+`SYNO.Core.SecurityScan.Status` +
+ +#### Returns +
+`dict[str, object] or str` +Security scan status. + +
@@ -164,6 +440,19 @@ This API is not documented yet. ### `get_user_list` +Get user list. + +#### Internal API +
+`SYNO.Core.User` +
+ +#### Returns +
+`dict[str, object] or str` +User list. + +
@@ -171,6 +460,19 @@ This API is not documented yet. ### `quickconnect_info` +Get QuickConnect configuration. + +#### Internal API +
+`SYNO.Core.QuickConnect` +
+ +#### Returns +
+`dict[str, object] or str` +QuickConnect configuration. + +
@@ -178,6 +480,19 @@ This API is not documented yet. ### `quickconnect_permissions` +Get QuickConnect permissions. + +#### Internal API +
+`SYNO.Core.QuickConnect.Permission` +
+ +#### Returns +
+`dict[str, object] or str` +QuickConnect permissions. + +
@@ -185,6 +500,19 @@ This API is not documented yet. ### `network_topology` +Get network topology. + +#### Internal API +
+`SYNO.Core.Network.Router.Topology` +
+ +#### Returns +
+`dict[str, object] or str` +Network topology. + +
@@ -192,6 +520,19 @@ This API is not documented yet. ### `network_wifi_client` +Get WiFi client information. + +#### Internal API +
+`SYNO.Core.Network.Wifi.Client` +
+ +#### Returns +
+`dict[str, object] or str` +WiFi client information. + +
@@ -199,6 +540,19 @@ This API is not documented yet. ### `network_bond` +Get network bond information. + +#### Internal API +
+`SYNO.Core.Network.Bond` +
+ +#### Returns +
+`dict[str, object] or str` +Network bond information. + +
@@ -206,6 +560,19 @@ This API is not documented yet. ### `network_bridge` +Get network bridge information. + +#### Internal API +
+`SYNO.Core.Network.Bridge` +
+ +#### Returns +
+`dict[str, object] or str` +Network bridge information. + +
@@ -213,6 +580,19 @@ This API is not documented yet. ### `network_ethernet` +Get network ethernet information. + +#### Internal API +
+`SYNO.Core.Network.Ethernet` +
+ +#### Returns +
+`dict[str, object] or str` +Network ethernet information. + +
@@ -220,6 +600,19 @@ This API is not documented yet. ### `network_local_bridge` +Get local network bridge information. + +#### Internal API +
+`SYNO.Core.Network.LocalBridge` +
+ +#### Returns +
+`dict[str, object] or str` +Local network bridge information. + +
@@ -227,6 +620,19 @@ This API is not documented yet. ### `network_usb_modem` +Get USB modem information. + +#### Internal API +
+`SYNO.Core.Network.USBModem` +
+ +#### Returns +
+`dict[str, object] or str` +USB modem information. + +
@@ -234,6 +640,19 @@ This API is not documented yet. ### `network_pppoe` +Get PPPoE information. + +#### Internal API +
+`SYNO.Core.Network.PPPoE` +
+ +#### Returns +
+`dict[str, object] or str` +PPPoE information. + +
@@ -241,6 +660,19 @@ This API is not documented yet. ### `network_ipv6tunnel` +Get IPv6 tunnel information. + +#### Internal API +
+`SYNO.Core.Network.IPv6Tunnel` +
+ +#### Returns +
+`dict[str, object] or str` +IPv6 tunnel information. + +
@@ -248,6 +680,19 @@ This API is not documented yet. ### `network_vpn_pptp` +Get VPN PPTP information. + +#### Internal API +
+`SYNO.Core.Network.VPN.PPTP` +
+ +#### Returns +
+`dict[str, object] or str` +VPN PPTP information. + +
@@ -255,6 +700,19 @@ This API is not documented yet. ### `network_openvpn` +Get OpenVPN information. + +#### Internal API +
+`SYNO.Core.Network.VPN.OpenVPN` +
+ +#### Returns +
+`dict[str, object] or str` +OpenVPN information. + +
@@ -262,6 +720,19 @@ This API is not documented yet. ### `network_vpn_l2tp` +Get VPN L2TP information. + +#### Internal API +
+`SYNO.Core.Network.VPN.L2TP` +
+ +#### Returns +
+`dict[str, object] or str` +VPN L2TP information. + +
@@ -269,6 +740,19 @@ This API is not documented yet. ### `domain_schedule` +Get domain schedule. + +#### Internal API +
+`SYNO.Core.Directory.Domain.Schedule` +
+ +#### Returns +
+`dict[str, object] or str` +Domain schedule. + +
@@ -276,6 +760,19 @@ This API is not documented yet. ### `client_ldap` +Get LDAP client information. + +#### Internal API +
+`SYNO.Core.Directory.LDAP` +
+ +#### Returns +
+`dict[str, object] or str` +LDAP client information. + +
@@ -283,6 +780,19 @@ This API is not documented yet. ### `client_sso` +Get SSO client information. + +#### Internal API +
+`SYNO.Core.Directory.SSO` +
+ +#### Returns +
+`dict[str, object] or str` +SSO client information. + +
@@ -290,6 +800,19 @@ This API is not documented yet. ### `sys_upgrade_check` +Check for system upgrades. + +#### Internal API +
+`SYNO.Core.Upgrade.Server` +
+ +#### Returns +
+`dict[str, object] or str` +System upgrade check result. + +
@@ -297,6 +820,19 @@ This API is not documented yet. ### `sys_upgrade_download` +Get system upgrade download progress. + +#### Internal API +
+`SYNO.Core.Upgrade.Server.Download` +
+ +#### Returns +
+`dict[str, object] or str` +System upgrade download progress. + +
@@ -304,6 +840,19 @@ This API is not documented yet. ### `sys_upgrade_setting` +Get system upgrade settings. + +#### Internal API +
+`SYNO.Core.Upgrade.Setting` +
+ +#### Returns +
+`dict[str, object] or str` +System upgrade settings. + +
@@ -311,6 +860,19 @@ This API is not documented yet. ### `notification_sms_conf` +Get SMS notification configuration. + +#### Internal API +
+`SYNO.Core.Notification.SMS.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +SMS notification configuration. + +
@@ -318,6 +880,19 @@ This API is not documented yet. ### `notification_mail_conf` +Get mail notification configuration. + +#### Internal API +
+`SYNO.Core.Notification.Mail.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +Mail notification configuration. + +
@@ -325,6 +900,19 @@ This API is not documented yet. ### `notification_push_mail` +Get push mail notification configuration. + +#### Internal API +
+`SYNO.Core.Notification.Push.Mail` +
+ +#### Returns +
+`dict[str, object] or str` +Push mail notification configuration. + +
@@ -332,6 +920,19 @@ This API is not documented yet. ### `notification_push_conf` +Get push notification configuration. + +#### Internal API +
+`SYNO.Core.Notification.Push.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +Push notification configuration. + +
@@ -339,6 +940,19 @@ This API is not documented yet. ### `hardware_beep_control` +Get hardware beep control status. + +#### Internal API +
+`SYNO.Core.Hardware.BeepControl` +
+ +#### Returns +
+`dict[str, object] or str` +Hardware beep control status. + +
@@ -346,6 +960,19 @@ This API is not documented yet. ### `hardware_fan_speed` +Get hardware fan speed. + +#### Internal API +
+`SYNO.Core.Hardware.FanSpeed` +
+ +#### Returns +
+`dict[str, object] or str` +Hardware fan speed. + +
@@ -353,6 +980,26 @@ This API is not documented yet. ### `set_fan_speed` +Set hardware fan speed. + +#### Internal API +
+`SYNO.Core.Hardware.FanSpeed` +
+ +#### Parameters +
+**_fan_speed_** `str` +Fan speed mode (e.g., 'quietfan', 'coolfan', 'fullfan'). Defaults to 'quietfan'. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -360,6 +1007,26 @@ This API is not documented yet. ### `enable_zram` +Enable or disable ZRAM. + +#### Internal API +
+`SYNO.Core.Hardware.ZRAM` +
+ +#### Parameters +
+**_enable_zram_** `bool` +Enable ZRAM if True, disable if False. Defaults to True. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -367,6 +1034,29 @@ This API is not documented yet. ### `enable_power_recovery` +Enable power recovery options. + +#### Internal API +
+`SYNO.Core.Hardware.PowerRecovery` +
+ +#### Parameters +
+**_restart_auto_after_issue_** `bool` +Restart automatically after issue. Defaults to True. + +**_wake_on_lan_** `bool` +Enable Wake-on-LAN. Defaults to False. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -374,6 +1064,35 @@ This API is not documented yet. ### `enable_beep_control` +Enable or disable beep control options. + +#### Internal API +
+`SYNO.Core.Hardware.BeepControl` +
+ +#### Parameters +
+**_fan_fail_** `bool` +Enable beep on fan failure. + +**_volume_crash_** `bool` +Enable beep on volume crash. + +**_poweron_beep_** `bool` +Enable beep on power on. + +**_poweroff_beep_** `bool` +Enable beep on power off. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -381,6 +1100,26 @@ This API is not documented yet. ### `set_led_control` +Set LED brightness. + +#### Internal API +
+`SYNO.Core.Led.Brightness` +
+ +#### Parameters +
+**_led_brightness_** `int` +LED brightness level. Defaults to 2. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -388,6 +1127,29 @@ This API is not documented yet. ### `set_hibernation` +Set hibernation times. + +#### Internal API +
+`SYNO.Core.Hardware.Hibernation` +
+ +#### Parameters +
+**_internal_hd_idletime_** `int` +Idle time for internal hard drives. Defaults to 0. + +**_usb_idletime_** `int` +Idle time for USB devices. Defaults to 0. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -395,6 +1157,38 @@ This API is not documented yet. ### `enable_external_ups` +Enable or configure external UPS. + +#### Internal API +
+`SYNO.Core.ExternalDevice.UPS` +
+ +#### Parameters +
+**_enable_** `bool` +Enable external UPS. Defaults to False. + +**_mode_** `str` +UPS mode. Defaults to 'SLAVE'. + +**_delay_time_** `int` +Delay time. Defaults to 1. + +**_snmp_auth_key_dirty_** `bool` +SNMP auth key dirty flag. Defaults to False. + +**_snmp_privacy_key_dirty_** `bool` +SNMP privacy key dirty flag. Defaults to False. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -402,6 +1196,19 @@ This API is not documented yet. ### `get_system_info` +Get system information. + +#### Internal API +
+`SYNO.Core.System` +
+ +#### Returns +
+`dict[str, object] or str` +System information. + +
@@ -409,6 +1216,19 @@ This API is not documented yet. ### `get_cpu_temp` +Get CPU temperature. + +#### Internal API +
+`SYNO.Core.System` +
+ +#### Returns +
+`str` +CPU temperature. + +
@@ -416,6 +1236,19 @@ This API is not documented yet. ### `get_all_system_utilization` +Get all system utilization statistics. + +#### Internal API +
+`SYNO.Core.System.Utilization` +
+ +#### Returns +
+`str` +System utilization statistics. + +
@@ -423,6 +1256,19 @@ This API is not documented yet. ### `get_cpu_utilization` +Get CPU utilization statistics. + +#### Internal API +
+`SYNO.Core.System.Utilization` +
+ +#### Returns +
+`str` +CPU utilization statistics. + +
@@ -430,6 +1276,19 @@ This API is not documented yet. ### `get_disk_utilization` +Get disk utilization statistics. + +#### Internal API +
+`SYNO.Core.System.Utilization` +
+ +#### Returns +
+`str` +Disk utilization statistics. + +
@@ -437,6 +1296,19 @@ This API is not documented yet. ### `get_memory_utilization` +Get memory utilization statistics. + +#### Internal API +
+`SYNO.Core.System.Utilization` +
+ +#### Returns +
+`str` +Memory utilization statistics. + +
@@ -444,6 +1316,26 @@ This API is not documented yet. ### `shutdown` +Shutdown the system. + +#### Internal API +
+`SYNO.Core.System` +
+ +#### Parameters +
+**_version_** `str` +API version to use. Defaults to None. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -451,6 +1343,19 @@ This API is not documented yet. ### `reboot` +Reboot the system. + +#### Internal API +
+`SYNO.Core.System` +
+ +#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -458,6 +1363,19 @@ This API is not documented yet. ### `dsm_info` +Get DSM information. + +#### Internal API +
+`SYNO.DSM.Info` +
+ +#### Returns +
+`dict[str, object] or str` +DSM information. + +
@@ -465,6 +1383,19 @@ This API is not documented yet. ### `get_network_info` +Get network information. + +#### Internal API +
+`SYNO.Core.System` +
+ +#### Returns +
+`dict[str, object] or str` +Network information. + +
@@ -472,6 +1403,19 @@ This API is not documented yet. ### `get_volume_info` +Get volume information. + +#### Internal API +
+`SYNO.Core.System` +
+ +#### Returns +
+`dict[str, object] or str` +Volume information. + +
@@ -479,6 +1423,19 @@ This API is not documented yet. ### `hardware_hibernation` +Get hardware hibernation status. + +#### Internal API +
+`SYNO.Core.Hardware.Hibernation` +
+ +#### Returns +
+`dict[str, object] or str` +Hardware hibernation status. + +
@@ -486,13 +1443,19 @@ This API is not documented yet. ### `hardware_ups` +Get hardware UPS status. + +#### Internal API +
+`SYNO.Core.ExternalDevice.UPS` +
+ +#### Returns +
+`dict[str, object] or str` +Hardware UPS status. - - ---- - - -### `hardware_power_schedule` +
@@ -500,6 +1463,19 @@ This API is not documented yet. ### `terminal_info` +Get terminal information. + +#### Internal API +
+`SYNO.Core.Terminal` +
+ +#### Returns +
+`dict[str, object] or str` +Terminal information. + +
@@ -507,6 +1483,19 @@ This API is not documented yet. ### `snmp_info` +Get SNMP information. + +#### Internal API +
+`SYNO.Core.SNMP` +
+ +#### Returns +
+`dict[str, object] or str` +SNMP information. + +
@@ -514,6 +1503,19 @@ This API is not documented yet. ### `process` +Get system process information. + +#### Internal API +
+`SYNO.Core.System.Process` +
+ +#### Returns +
+`dict[str, object] or str` +System process information. + +
@@ -521,6 +1523,19 @@ This API is not documented yet. ### `storage` +Get storage information. + +#### Internal API +
+`SYNO.Storage.CGI.Storage` +
+ +#### Returns +
+`dict[str, object] or str` +Storage information. + +
@@ -528,6 +1543,19 @@ This API is not documented yet. ### `external_device_storage_usb` +Get USB storage device information. + +#### Internal API +
+`SYNO.Core.ExternalDevice.Storage.USB` +
+ +#### Returns +
+`dict[str, object] or str` +USB storage device information. + +
@@ -535,6 +1563,19 @@ This API is not documented yet. ### `external_device_storage_esata` +Get eSATA storage device information. + +#### Internal API +
+`SYNO.Core.ExternalDevice.Storage.eSATA` +
+ +#### Returns +
+`dict[str, object] or str` +eSATA storage device information. + +
@@ -542,6 +1583,19 @@ This API is not documented yet. ### `file_index_resource` +Get file indexing status. + +#### Internal API +
+`SYNO.Finder.FileIndexing.Status` +
+ +#### Returns +
+`dict[str, object] or str` +File indexing status. + +
@@ -549,6 +1603,19 @@ This API is not documented yet. ### `cms_info` +Get CMS information. + +#### Internal API +
+`SYNO.Core.CMS.Info` +
+ +#### Returns +
+`dict[str, object] or str` +CMS information. + +
@@ -556,6 +1623,19 @@ This API is not documented yet. ### `port_forwarding_rules` +Get port forwarding rules. + +#### Internal API +
+`SYNO.Core.PortForwarding.Rules` +
+ +#### Returns +
+`dict[str, object] or str` +Port forwarding rules. + +
@@ -563,6 +1643,19 @@ This API is not documented yet. ### `port_forwarding_router_conf` +Get port forwarding router configuration. + +#### Internal API +
+`SYNO.Core.PortForwarding.RouterConf` +
+ +#### Returns +
+`dict[str, object] or str` +Port forwarding router configuration. + +
@@ -570,6 +1663,19 @@ This API is not documented yet. ### `disk_list` +Get disk list. + +#### Internal API +
+`SYNO.Core.Polling.Data` +
+ +#### Returns +
+`dict[str, object] or str` +Disk list. + +
@@ -577,6 +1683,19 @@ This API is not documented yet. ### `ddns_provider_info` +Get DDNS provider information. + +#### Internal API +
+`SYNO.Core.DDNS.Provider` +
+ +#### Returns +
+`dict[str, object] or str` +DDNS provider information. + +
@@ -584,6 +1703,19 @@ This API is not documented yet. ### `ddns_record_info` +Get DDNS record information. + +#### Internal API +
+`SYNO.Core.DDNS.Record` +
+ +#### Returns +
+`dict[str, object] or str` +DDNS record information. + +
@@ -591,6 +1723,19 @@ This API is not documented yet. ### `ddns_external_ip` +Get DDNS external IP. + +#### Internal API +
+`SYNO.Core.DDNS.ExtIP` +
+ +#### Returns +
+`dict[str, object] or str` +DDNS external IP. + +
@@ -598,6 +1743,19 @@ This API is not documented yet. ### `ddns_synology` +Get Synology DDNS information. + +#### Internal API +
+`SYNO.Core.DDNS.Synology` +
+ +#### Returns +
+`dict[str, object] or str` +Synology DDNS information. + +
@@ -605,6 +1763,19 @@ This API is not documented yet. ### `iscsi_lun_info` +Get iSCSI LUN information. + +#### Internal API +
+`SYNO.Core.ISCSI.LUN` +
+ +#### Returns +
+`dict[str, object] or str` +iSCSI LUN information. + +
@@ -612,6 +1783,19 @@ This API is not documented yet. ### `hddman` +Get HDD manager information. + +#### Internal API +
+`SYNO.Storage.CGI.HddMan` +
+ +#### Returns +
+`dict[str, object] or str` +HDD manager information. + +
@@ -619,6 +1803,19 @@ This API is not documented yet. ### `ftp_security_info` +Get FTP security information. + +#### Internal API +
+`SYNO.Core.FileServ.FTP.Security` +
+ +#### Returns +
+`dict[str, object] or str` +FTP security information. + +
@@ -626,6 +1823,19 @@ This API is not documented yet. ### `bandwidth_control_info` +Get bandwidth control information. + +#### Internal API +
+`SYNO.Core.BandwidthControl.Protocol` +
+ +#### Returns +
+`dict[str, object] or str` +Bandwidth control information. + +
@@ -633,6 +1843,19 @@ This API is not documented yet. ### `directory_domain_info` +Get directory domain information. + +#### Internal API +
+`SYNO.Core.Directory.Domain` +
+ +#### Returns +
+`dict[str, object] or str` +Directory domain information. + +
@@ -640,6 +1863,19 @@ This API is not documented yet. ### `ws_transfer_info` +Get WS transfer information. + +#### Internal API +
+`SYNO.Core.FileServ.ServiceDiscovery.WSTransfer` +
+ +#### Returns +
+`dict[str, object] or str` +WS transfer information. + +
@@ -647,6 +1883,19 @@ This API is not documented yet. ### `ref_link_copy_info` +Get reflink copy information. + +#### Internal API +
+`SYNO.Core.FileServ.ReflinkCopy` +
+ +#### Returns +
+`dict[str, object] or str` +Reflink copy information. + +
@@ -654,6 +1903,19 @@ This API is not documented yet. ### `bonjour_service_info` +Get Bonjour service information. + +#### Internal API +
+`SYNO.Core.ExternalDevice.Printer.BonjourSharing` +
+ +#### Returns +
+`dict[str, object] or str` +Bonjour service information. + +
@@ -661,6 +1923,19 @@ This API is not documented yet. ### `personal_photo_enable` +Get personal photo enable status. + +#### Internal API +
+`SYNO.Core.User.Home` +
+ +#### Returns +
+`dict[str, object] or str` +Personal photo enable status. + +
@@ -668,6 +1943,19 @@ This API is not documented yet. ### `ftp_chroot_user` +Get FTP chroot user information. + +#### Internal API +
+`SYNO.Core.FileServ.FTP.ChrootUser` +
+ +#### Returns +
+`dict[str, object] or str` +FTP chroot user information. + +
@@ -675,6 +1963,19 @@ This API is not documented yet. ### `server_pair` +Get server pair information. + +#### Internal API +
+`SYNO.S2S.Server.Pair` +
+ +#### Returns +
+`dict[str, object] or str` +Server pair information. + +
@@ -682,6 +1983,32 @@ This API is not documented yet. ### `groups_info` +Get groups information. + +#### Internal API +
+`SYNO.Core.Group` +
+ +#### Parameters +
+**_offset_** `int` +Offset for pagination. Defaults to 0. + +**_limit_** `int` +Maximum number of groups to retrieve. Defaults to -1. + +**_name_only_** `bool` +If True, returns only group names. Defaults to False. + + +
+#### Returns +
+`dict[str, object] or str` +Groups information. + +
@@ -689,6 +2016,19 @@ This API is not documented yet. ### `ldap_info` +Get LDAP information. + +#### Internal API +
+`SYNO.Core.Directory.LDAP` +
+ +#### Returns +
+`dict[str, object] or str` +LDAP information. + +
@@ -696,6 +2036,19 @@ This API is not documented yet. ### `sso_iwa_info` +Get SSO IWA information. + +#### Internal API +
+`SYNO.Core.Directory.SSO.IWA` +
+ +#### Returns +
+`dict[str, object] or str` +SSO IWA information. + +
@@ -703,6 +2056,19 @@ This API is not documented yet. ### `sso_info` +Get SSO information. + +#### Internal API +
+`SYNO.Core.Directory.SSO` +
+ +#### Returns +
+`dict[str, object] or str` +SSO information. + +
@@ -710,6 +2076,19 @@ This API is not documented yet. ### `network_interface_info` +Get network interface information. + +#### Internal API +
+`SYNO.Core.Network.Interface` +
+ +#### Returns +
+`dict[str, object] or str` +Network interface information. + +
@@ -717,6 +2096,19 @@ This API is not documented yet. ### `proxy_info` +Get proxy information. + +#### Internal API +
+`SYNO.Core.Network.Proxy` +
+ +#### Returns +
+`dict[str, object] or str` +Proxy information. + +
@@ -724,6 +2116,29 @@ This API is not documented yet. ### `gateway_list` +Get gateway list. + +#### Internal API +
+`SYNO.Core.Network.Router.Gateway.List` +
+ +#### Parameters +
+**_ip_type_** `str` +IP type (e.g., 'ipv4', 'ipv6'). Defaults to 'ipv4'. + +**_type_** `str` +Gateway type (e.g., 'wan'). Defaults to 'wan'. + + +
+#### Returns +
+`dict[str, object] or str` +Gateway list. + +
@@ -731,6 +2146,19 @@ This API is not documented yet. ### `firewall_info` +Get firewall information. + +#### Internal API +
+`SYNO.Core.Security.Firewall.Profile` +
+ +#### Returns +
+`dict[str, object] or str` +Firewall information. + +
@@ -738,6 +2166,19 @@ This API is not documented yet. ### `auto_upgrade_status` +Get auto upgrade status. + +#### Internal API +
+`SYNO.Core.Upgrade.AutoUpgrade` +
+ +#### Returns +
+`dict[str, object] or str` +Auto upgrade status. + +
@@ -745,6 +2186,19 @@ This API is not documented yet. ### `upgrade_server_check` +Check upgrade server. + +#### Internal API +
+`SYNO.Core.Upgrade.Server` +
+ +#### Returns +
+`dict[str, object] or str` +Upgrade server check result. + +
@@ -752,6 +2206,19 @@ This API is not documented yet. ### `alarm_rules_logs` +Get alarm rules logs. + +#### Internal API +
+`SYNO.ResourceMonitor.Log` +
+ +#### Returns +
+`dict[str, object] or str` +Alarm rules logs. + +
@@ -759,6 +2226,19 @@ This API is not documented yet. ### `alarm_rules_list` +Get alarm rules list. + +#### Internal API +
+`SYNO.ResourceMonitor.EventRule` +
+ +#### Returns +
+`dict[str, object] or str` +Alarm rules list. + +
@@ -766,6 +2246,19 @@ This API is not documented yet. ### `resource_monitor_settings_list` +Get resource monitor settings. + +#### Internal API +
+`SYNO.ResourceMonitor.Setting` +
+ +#### Returns +
+`dict[str, object] or str` +Resource monitor settings. + +
@@ -773,6 +2266,35 @@ This API is not documented yet. ### `file_handling_access` +Get file handling access information. + +#### Internal API +
+`SYNO.Core.FileHandle` +
+ +#### Parameters +
+**_sort_direction_** `str` +Sort direction ('ASC' or 'DESC'). Defaults to 'ASC'. + +**_sort_by_** `str` +Field to sort by. Defaults to 'service'. + +**_limit_** `int` +Maximum number of results. Defaults to 50. + +**_offset_** `int` +Offset for pagination. Defaults to 0. + + +
+#### Returns +
+`dict[str, object] or str` +File handling access information. + +
@@ -780,6 +2302,26 @@ This API is not documented yet. ### `list_service_group` +Get service group list. + +#### Internal API +
+`SYNO.Core.System.ProcessGroup` +
+ +#### Parameters +
+**_interval_** `int` +Interval for statistics. Defaults to 0. + + +
+#### Returns +
+`dict[str, object] or str` +Service group list. + +
@@ -787,6 +2329,19 @@ This API is not documented yet. ### `list_process_group` +Get process group list. + +#### Internal API +
+`SYNO.Core.System.Process` +
+ +#### Returns +
+`dict[str, object] or str` +Process group list. + +
@@ -794,6 +2349,19 @@ This API is not documented yet. ### `installed_package_list` +Get installed package list. + +#### Internal API +
+`SYNO.Core.Package` +
+ +#### Returns +
+`dict[str, object] or str` +Installed package list. + +
@@ -801,6 +2369,19 @@ This API is not documented yet. ### `active_notifications` +Get active notifications. + +#### Internal API +
+`SYNO.Core.DSMNotify` +
+ +#### Returns +
+`dict[str, object] or str` +Active notifications. + +
@@ -808,6 +2389,19 @@ This API is not documented yet. ### `get_system_health` +Get system health information. + +#### Internal API +
+`SYNO.Core.System.SystemHealth` +
+ +#### Returns +
+`dict[str, object] or str` +System health information. + +
@@ -815,6 +2409,19 @@ This API is not documented yet. ### `upgrade_status` +Get upgrade status. + +#### Internal API +
+`SYNO.Core.Upgrade` +
+ +#### Returns +
+`dict[str, object] or str` +Upgrade status. + +
diff --git a/documentation/docs/apis/classes/core_user.md b/documentation/docs/apis/classes/core_user.md index 1922e6e3..ac981626 100644 --- a/documentation/docs/apis/classes/core_user.md +++ b/documentation/docs/apis/classes/core_user.md @@ -11,20 +11,38 @@ title: ✅ User ## Overview Core User API implementation. -Supported actions: - - **Getters** : - - Get all users - - Password policies - - Password expiry - - - **Setters** : - - Set user password policy - - - **Actions** : - - Create new user - - Modify user - - Delete user - - User join/leave group +Methods +------- +get_users(offset=0, limit=-1, sort_by="name", sort_direction="ASC", additional=[]) + Retrieve groups information. +get_user(name, additional=[]) + Retrieve user information. +create_user(...) + Create a new user. +modify_user(...) + Modify a user. +delete_user(name) + Delete a user. +affect_groups(name, join_groups=[], leave_groups=[]) + Affect or disaffect groups to a user. +affect_groups_status(task_id) + Get the status of a join task. +get_password_policy() + Get the password policy. +set_password_policy(...) + Set the password policy. +get_password_expiry() + Get the password expiry. +set_password_expiry(...) + Set the password expiry. +password_confirm(password) + Confirm password/session. +get_username_policy() + Get the username policy. + +Examples +-------- +See individual method docstrings for usage examples. ## Methods ### `get_users` Retrieve groups information. @@ -40,7 +58,7 @@ Retrieve groups information. The offset of the groups to retrieve. Defaults to `0`. **_limit_** `int` -The maximum number of groups to retrieve. Defaults to `-1` . +The maximum number of groups to retrieve. Defaults to `-1`. **_sort_by_** `str` Sort by a specific field. Defaults to `"name"`. @@ -49,7 +67,7 @@ Sort by a specific field. Defaults to `"name"`. The sort direction. Defaults to `"ASC"` else `"DESC"`. **_additional_** `list[str]` -Additional fields to retrieve. Defaults to `[]`. +Additional fields to retrieve. Defaults to `[]`. All fields known are: `["description","email","expired","cannot_chg_passwd","passwd_never_expire","password_last_change", "groups", "2fa_status"]`. @@ -110,7 +128,7 @@ A dictionary containing the groups information. ### `get_user` -Retrieve a user information. +Retrieve user information. #### Internal API
@@ -123,7 +141,7 @@ Retrieve a user information. The name of the user. **_additional_** `list[str]` -Additional fields to retrieve. Defaults to `[]`. +Additional fields to retrieve. Defaults to `[]`. All fields known are: `["description","email","expired","cannot_chg_passwd","passwd_never_expire","password_last_change","is_password_pending"]`. @@ -216,7 +234,7 @@ A dictionary containing the user information.
Click to expand ```json -{ +{ "data": { "name":"toto", @@ -503,34 +521,34 @@ Set the password policy. #### Parameters
-**_enable_reset_passwd_by_email_** `bool, optional ` +**_enable_reset_passwd_by_email_** `bool` Defaults to `False`. -**_password_must_change_** `bool, optional ` +**_password_must_change_** `bool` Defaults to `False`. -**_exclude_username_** `bool, optional ` +**_exclude_username_** `bool` Defaults to `True`. -**_included_numeric_char_** `bool, optional ` +**_included_numeric_char_** `bool` Defaults to `True`. -**_included_special_char_** `bool, optional ` +**_included_special_char_** `bool` Defaults to `False`. -**_min_length_** `int, optional ` +**_min_length_** `int` Defaults to `8`. -**_min_length_enable_** `bool, optional ` +**_min_length_enable_** `bool` Defaults to `True`. -**_mixed_case_** `bool, optional ` +**_mixed_case_** `bool` Defaults to `True`. -**_exclude_common_password_** `bool, optional ` +**_exclude_common_password_** `bool` Defaults to `False`. -**_exclude_history_** `bool, optional ` +**_exclude_history_** `bool` Defaults to `False`. @@ -664,7 +682,7 @@ A dictionary indicating the success of the operation. ### `password_confirm` -Issues a passowrd/session comparison to ensure the given password matches the auth of the current session. +Confirm password/session to ensure the given password matches the auth of the current session. :::note This is needed by some APIs as a confirmation method, for example, when creating/modifying a scheduled task with root permissions, seldom needed by end users. @@ -708,7 +726,7 @@ A dictionary containing a `SynoConfirmPWToken`, or an error message. ### `get_username_policy` -Get the username policy (List of username that are not usable). +Get the username policy (list of usernames that are not usable). #### Internal API
diff --git a/documentation/docs/apis/classes/dhcp_server.md b/documentation/docs/apis/classes/dhcp_server.md index e1d56493..500b3f27 100644 --- a/documentation/docs/apis/classes/dhcp_server.md +++ b/documentation/docs/apis/classes/dhcp_server.md @@ -14,9 +14,32 @@ This API is not documented yet. ::: ## Overview +Core DHCP Server API implementation for Synology NAS. +This class provides methods to retrieve and manage DHCP server, PXE, TFTP, and network +interface information. ## Methods ### `general_info` +Get general DHCP server information for a given interface. + +#### Internal API +
+`SYNO.Network.DHCPServer` +
+ +#### Parameters +
+**_ifname_** `str` +Interface name. Defaults to 'ovs_eth0'. + + +
+#### Returns +
+`dict[str, object] or str` +General DHCP server information. + +
@@ -24,6 +47,19 @@ This API is not documented yet. ### `vendor` +Get DHCP vendor information. + +#### Internal API +
+`SYNO.Network.DHCPServer.Vendor` +
+ +#### Returns +
+`dict[str, object] or str` +DHCP vendor information. + +
@@ -31,6 +67,19 @@ This API is not documented yet. ### `pxe` +Get PXE server information. + +#### Internal API +
+`SYNO.Network.DHCPServer.PXE` +
+ +#### Returns +
+`dict[str, object] or str` +PXE server information. + +
@@ -38,6 +87,19 @@ This API is not documented yet. ### `tftp` +Get TFTP server information. + +#### Internal API +
+`SYNO.Core.TFTP` +
+ +#### Returns +
+`dict[str, object] or str` +TFTP server information. + +
@@ -45,6 +107,19 @@ This API is not documented yet. ### `network_bond` +Get network bond interface information. + +#### Internal API +
+`SYNO.Core.Network.Bond` +
+ +#### Returns +
+`dict[str, object] or str` +Network bond interface information. + +
@@ -52,6 +127,19 @@ This API is not documented yet. ### `network_ethernet` +Get network ethernet interface information. + +#### Internal API +
+`SYNO.Core.Network.Ethernet` +
+ +#### Returns +
+`dict[str, object] or str` +Network ethernet interface information. + +
@@ -59,6 +147,26 @@ This API is not documented yet. ### `dhcp_clientlist` +Get DHCP client list for a given interface. + +#### Internal API +
+`SYNO.Network.DHCPServer.ClientList` +
+ +#### Parameters +
+**_ifname_** `str` +Interface name. Defaults to 'bond0'. + + +
+#### Returns +
+`dict[str, object] or str` +DHCP client list. + +
@@ -66,6 +174,26 @@ This API is not documented yet. ### `dhcp_reservations` +Get DHCP reservations for a given interface. + +#### Internal API +
+`SYNO.Network.DHCPServer.Reservation` +
+ +#### Parameters +
+**_ifname_** `str` +Interface name. Defaults to 'bond0'. + + +
+#### Returns +
+`dict[str, object] or str` +DHCP reservations. + +
diff --git a/documentation/docs/apis/classes/directory_server.md b/documentation/docs/apis/classes/directory_server.md index 0e99724f..db8d690c 100644 --- a/documentation/docs/apis/classes/directory_server.md +++ b/documentation/docs/apis/classes/directory_server.md @@ -11,14 +11,15 @@ title: ✅ DirectoryServer ## Overview The directory server API. -Not all items within this class use the Active Directory API. Some use the Synology Entry API which proxies -the request. Some are related to managing users in ways that are useful in the Directory Server context. For +Not all items within this class use the Active Directory API. Some use the Synology Entry API which proxies +the request. Some are related to managing users in ways that are useful in the Directory Server context. For example, sending a user password reset email, or updating the user information. This api works slightly differently than other similar APIs. There are multi-leveled calls where Synology makes requests on behalf of the original request and relays information back. Additionally, the query-string api item is not used often in this class as API is defined within the actual request. The APIs in this class are tested working against the following scenarios: + - **Getters** : - Get Active Directory information - List objects within a Base DN on the Active Directory Server @@ -38,7 +39,7 @@ The APIs in this class are tested working against the following scenarios: - Perform an entry request to complete a Deletion ## Methods ### `get_directory_info` -Gets directory info. +Get directory info. #### Internal API
@@ -90,7 +91,7 @@ Information about your domain. ### `list_directory_objects` -lists directory objects. +List directory objects. #### Internal API
@@ -100,29 +101,26 @@ lists directory objects. #### Parameters
**_basedn_** `str` -The Base DN for the search. eg. `CN=Users,CN=MY,CN=DOMAIN,CN=COM" or CN=MY,CN=DOMAIN,CN=COM` +The Base DN for the search. E.g. `CN=Users,CN=MY,CN=DOMAIN,CN=COM` or `CN=MY,CN=DOMAIN,CN=COM`. **_offset_** `int` When searching large data, you may wish to start at a certain number, e.g. for 10 at a time one -would set the limit to 10 and the offset by multiples of 10 for each request. -Defaults to `0` +would set the limit to 10 and the offset by multiples of 10 for each request. Defaults to `0`. **_limit_** `int` -The numeric the number of maximum objects to return. -Defaults to `40` +The number of maximum objects to return. Defaults to `40`. -**_objectCategory_** `optional, list[str]` -The categories of items to search. e.g. `["organizationalUnit","container","builtinDomain"]` for a list of +**_objectCategory_** `list[str]` +The categories of items to search. E.g. `["organizationalUnit","container","builtinDomain"]` for a list of base server containers, and `["person","group","organizationalUnit","computer"]` for a list of contained objects. -Defaults to `["person","group","organizationalUnit","computer","container","builtinDomain"]` +Defaults to `["person","group","organizationalUnit","computer","container","builtinDomain"]`.
#### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. The first level is the success to the AD server. The second Data level is the status of the actual request. Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
@@ -167,19 +165,8 @@ Since this is a compound request, the data contains an object with it's own requ ### `create_new_user` -Create a new user. -:::note - - The user can be created in AD, but not able to log on until the next synchronization occurs. - -::: - -:::note - - Please note that synchronization with Synology is a separate step. - -::: - +Create a new user. + #### Internal API
`SYNO.ActiveDirectory.User` @@ -188,41 +175,38 @@ Create a new user. #### Parameters
**_logon_name_** `str` -The desired username. E.g `jdoe`. +The desired username. E.g. `jdoe`. **_email_** `str` The desired email. **_password_** `str` -The plain-text password for the new user. E.g `Password123`. +The plain-text password for the new user. E.g. `Password123`. **_located_dn_** `str` -The DN for the user. E.g `CN=Users,CN=MY,CN=DOMAIN,CN=COM`. +The DN for the user. E.g. `CN=Users,CN=MY,CN=DOMAIN,CN=COM`. **_description_** `str` A description for the user. **_account_is_disabled_** `str` -Set to 'true' if the account should be disabled Defaults to `False`. +Set to 'true' if the account should be disabled. Defaults to `False`. **_cannot_change_password_** `str` -Set to 'true' if the user cannot change the password Defaults to `False`. +Set to 'true' if the user cannot change the password. Defaults to `False`. **_change_password_next_logon_** `str` -Set to 'true' if the user must change password on next logon Defaults to `False`. - -**_cannot_change_password_** `str` -Set to 'true' if the user cannot change the password Defaults to `False`. +Set to 'true' if the user must change password on next logon. Defaults to `False`. **_password_never_expire_** `str` -Pwd Never Expire +Set to 'true' if the password never expires.
#### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. The data dictionary contains an 'error', or it contains a 'dn' and a 'name'. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary.
#### Example return @@ -231,9 +215,9 @@ The result of this method is a dictionary object with a 'data' dictionary and a ```json { 'data': { - 'dn': 'CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM', + 'dn': 'CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM', 'name': 'NETBIOSNAME\ababab' - }, + }, 'success': true } ``` @@ -247,13 +231,7 @@ The result of this method is a dictionary object with a 'data' dictionary and a ### `reset_password` Send a password reset email. This will trigger the password reset email from -Control Panel>Notification>Rules>System>Reset password for your account to be sent to the user. -:::info - - In order to use this, Control Panel>User & Group>Advanced>"Allow non-administrator users to reset forgotten passwords via email" must be enabled. - -::: - +Control Panel>Notification>Rules>System>Reset password for your account to be sent to the user. #### Internal API
`SYNO.Auth.ForgotPwd` @@ -262,7 +240,7 @@ Control Panel>Notification>Rules>System>Reset password for your account to be se #### Parameters
**_username_** `str` -The username to reset. E.g. `My Group` +The username to reset. E.g. `My Group`.
@@ -279,7 +257,7 @@ The return object can be checked for the "success" to be a true or false. { "data": { "msg": 3 - }, + }, "success": true } ``` @@ -291,13 +269,8 @@ The return object can be checked for the "success" to be a true or false. ### `change_user_password` -Change the user's password. -:::info - - This is a compound dual-level request where the synology API proxies your request to the Directory Server. - -::: - +Change the user's password. + #### Internal API
`SYNO.Entry.Request` @@ -306,10 +279,10 @@ Change the user's password. #### Parameters
**_user_dn_** `str` -The user DN to be modified. eg. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM` +The user DN to be modified. E.g. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM`. **_password_** `str` -The new password to be set. e.g. `Password123` +The new password to be set. E.g. `Password123`.
@@ -317,8 +290,6 @@ The new password to be set. e.g. `Password123`
`dict[str, object]` The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. -Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
#### Example return @@ -364,52 +335,48 @@ Create a new AD group. #### Parameters
**_name_** `str` -The name of the group. E.g. `My Group` +The name of the group. E.g. `My Group`. **_located_dn_** `str` -The DN to place the group in. eg. `CN=Groups,DC=MY,DC=DOMAIN,DC=COM` +The DN to place the group in. E.g. `CN=Groups,DC=MY,DC=DOMAIN,DC=COM`. **_email_** `str` -The email address used to reference this group. -Defaults to `""` +The email address used to reference this group. Defaults to `""`. **_description_** `str` -A description of the AD Group. -Defaults to `""` +A description of the AD Group. Defaults to `""`. **_type_** `str` -Example Options: `security`, `distribution` +Example Options: `security`, `distribution`. Defaults to `"security"`. (definitions from https://docs.microsoft.com/en-us/microsoft-365/admin/create-groups/compare-groups?view=o365-worldwide ) - `distribution` (Distribution groups) are used for sending email - notifications to a group of people. + notifications to a group of people. - `security` - Security groups are used for granting access to resources - such as SharePoint sites. -Defaults to `"security"` + such as SharePoint sites. **_scope_** `str` -Example Options : `local`, `global`, `universal` -(Definitions from -https://www.netwrix.com/active_directory_group_management.html ) - - `local` (Domain Local Groups) should be used to manage permissions to - resources because this group can be applied everywhere in the domain. - A domain local group can include members of any type in the domain and - members from trusted domains. For example, suppose you need access - management for a collection of folders on one or more servers that - contain information for managers. The group you create for that purpose - should be a domain local group (ex. “DL_Managers_Modify”). - - `global` (Global Groups) are used primarily to define collections of - domain objects (users, other global groups and computers) based on - business roles, which means that they mostly serve as role groups. - Role-based groups of users (such as “HR” or “Marketing”) and role-based - groups of computers (such as a “Marketing Workstations”) areusually - global groups. - - `universal` (Universal Groups) in Active Directory are useful in - multi-domain forests. They enable you to define roles or manage - resources that span more than one domain. Each universal group is - stored in the domain of where it was created, but its group membership - is stored in the Global Catalog and replicated forest-wide. Don’t use - universal groups if you have only one domain. -Defaults to `"global"` +Example Options: `local`, `global`, `universal`. Defaults to `"global"`. + (Definitions from + https://www.netwrix.com/active_directory_group_management.html ) + - `local` (Domain Local Groups) should be used to manage permissions to + resources because this group can be applied everywhere in the domain. + A domain local group can include members of any type in the domain and + members from trusted domains. For example, suppose you need access + management for a collection of folders on one or more servers that + contain information for managers. The group you create for that purpose + should be a domain local group (ex. “DL_Managers_Modify”). + - `global` (Global Groups) are used primarily to define collections of + domain objects (users, other global groups and computers) based on + business roles, which means that they mostly serve as role groups. + Role-based groups of users (such as “HR” or “Marketing”) and role-based + groups of computers (such as a “Marketing Workstations”) areusually + global groups. + - `universal` (Universal Groups) in Active Directory are useful in + multi-domain forests. They enable you to define roles or manage + resources that span more than one domain. Each universal group is + stored in the domain of where it was created, but its group membership + is stored in the Global Catalog and replicated forest-wide. Don’t use + universal groups if you have only one domain.
@@ -425,9 +392,9 @@ A success object, and data object containing the new dn and the netbios name of ```json { 'data': { - 'dn': 'CN=My Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM', + 'dn': 'CN=My Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM', 'name': 'NETBIOSNAME\My Group' - }, + }, 'success': true } ``` @@ -439,7 +406,7 @@ A success object, and data object containing the new dn and the netbios name of ### `add_user_to_group` -Adds a user as a member of a group. +Add a user as a member of a group. #### Internal API
@@ -449,18 +416,18 @@ Adds a user as a member of a group. #### Parameters
**_userDn_** `str` -The fully qualified dn to add. eg. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM` +The fully qualified dn to add. E.g. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM`. **_groupDn_** `str` -the fully qualified dn of the group to which the user is to be added. e.g. `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM` +The fully qualified dn of the group to which the user is to be added. E.g. `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM`.
#### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. +The first level is the success to the AD server. The second Data level is the status of the actual request. Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
@@ -496,13 +463,8 @@ Since this is a compound request, the data contains an object with it's own requ ### `does_dn_exist` -Checks if a container exists. This can be used to verifiy the username or group name is unique. -:::info - - This will not check the container, only if a similarly named container already exists. - -::: - +Check if a container exists. +This can be used to verify the username or group name is unique. #### Internal API
`SYNO.ActiveDirectory.Group` @@ -511,16 +473,16 @@ Checks if a container exists. This can be used to verifiy the username or group #### Parameters
**_groupName_** `str` -The user, or group's name. e.g. `jdoe` or `My Cool Group` -Fully Qualified Domain Name such as `CN=My Cool Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM` are not successful. -Improper case such as `my cool group` instead of `My Cool Group` are successful +The user, or group's name. E.g. `jdoe` or `My Cool Group`. +Fully Qualified Domain Name such as `CN=My Cool Group,CN=Groups,DC=MY,DC=DOMAIN,DC=COM` are not successful. +Improper case such as `my cool group` instead of `My Cool Group` are successful.
#### Returns
`dict[str, object]` -`True` if the group exists. `False` if the group does not exist +`True` if the group exists. `False` if the group does not exist.
@@ -530,7 +492,7 @@ Improper case such as `my cool group` instead of `My Cool Group` are successful ### `modify_user_info` -Performs modification to user information within the Active Directory. +Modify user information within the Active Directory. #### Internal API
@@ -540,25 +502,25 @@ Performs modification to user information within the Active Directory. #### Parameters
**_user_dn_** `str` -The user DN to be modified. eg. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM` +The user DN to be modified. E.g. `CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM`. **_firstName_** `str` -The First name of the user. e.g. `John` +The First name of the user. E.g. `John`. **_lastName_** `str` -The Last Name of the user. e.g. `Doe` +The Last Name of the user. E.g. `Doe`. **_displayName_** `str` -The Display name of the user. e.g. `John Doe` +The Display name of the user. E.g. `John Doe`. **_description_** `str` -The Descrition of the user. e.g. `The guy who just came in` +The Description of the user. E.g. `The guy who just came in`. **_initials_** `str` -The Initials of the user. e.g. `JD` +The Initials of the user. E.g. `JD`. **_physicalDeliveryOfficeName_** `str` -The office location in the user's place of business +The office location in the user's place of business. **_telephoneNumber_** `str` The user's telephone number. @@ -571,8 +533,8 @@ The user's website or location on the web where information can be obtained. #### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. +The first level is the success to the AD server. The second Data level is the status of the actual request. Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
@@ -612,7 +574,7 @@ Since this is a compound request, the data contains an object with it's own requ ### `setEntryRequest` -Performs modification to an object within the Active Directory. +Modify an object within the Active Directory. #### Internal API
@@ -622,24 +584,24 @@ Performs modification to an object within the Active Directory. #### Parameters
**_modificationAPI_** `str` -API to be used +API to be used. **_method_** `str` -Method to be called +Method to be called. **_nameOfObject_** `str` -The user DN to be modified. eg. `"CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM"` +The user DN to be modified. E.g. `"CN=jdoe,CN=Users,DC=MY,DC=DOMAIN,DC=COM"`. **_jsonObject_** `str` -The json Object to be added, eg, a user object where the +The json Object to be added, e.g., a user object.
#### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. +The first level is the success to the AD server. The second Data level is the status of the actual request. Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
@@ -679,8 +641,8 @@ Since this is a compound request, the data contains an object with it's own requ ### `update_domain_records` -Updates the Synology users and groups database with information from Directory Server. -This is a long-running and asynchronous task. You are given back a task_id, and you can use that task_id to check the status with the get_task_status(task_id) method. +Update the Synology users and groups database with information from Directory Server. +This is a long-running and asynchronous task. You are given back a task_id, and you can use that task_id to check the status with the get_task_status(task_id) method. #### Internal API
`SYNO.Core.Directory.Domain` @@ -690,18 +652,19 @@ This is a long-running and asynchronous task. You are given back a task_id, and
`dict[str, object]` The 'data' object contains the 'task_id' used to track with the getTaskStatus() method. -The 'success' object will be true if the operation was successful. or false if failed.
#### Example return
Click to expand -```python - updateResponse=directory.updateDomain() - status = directory.getTaskStatus(updateResponse['data']['task_id']) - while status['data']['status'] == 'updating': - status=directory.getTaskStatus(updateResponse['data']['task_id']) - ``` +```json +{ + "data": { + "task_id": "@administrators/DomainUpdate6146195136397F2" + }, + "success": true +} +```
@@ -710,8 +673,8 @@ The 'success' object will be true if the operation was successful. or false if f ### `get_task_status` -Gets the current status of a task running on the Directory Domain object. -This is used to ensure the task is completed. For example, the primary utilization of this is when updating Synology's internal Domain user and group list. +Get the current status of a task running on the Directory Domain object. +This is used to ensure the task is completed. For example, the primary utilization of this is when updating Synology's internal Domain user and group list. Until this method reports finish, the job is not completed, and it is not safe to operate under the assumption that users have been synchronized. #### Internal API
@@ -729,8 +692,7 @@ The task ID to be tracked for status.
`dict[str, object]` The 'data' object contains the 'status' used to determine the current status. 'status' will be 'updating' or 'finish' if the job was started. -T -The 'success' object will be true if the operation was successful. or false if failed. +The 'success' object will be true if the operation was successful, or false if failed.
#### Example return @@ -740,7 +702,7 @@ The 'success' object will be true if the operation was successful. or false if f { 'data': { 'status': 'updating' - }, + }, 'success': true } ``` @@ -752,7 +714,7 @@ The 'success' object will be true if the operation was successful. or false if f ### `deleteItems` -Deletes an array of DNs from AD. +Delete an array of DNs from AD. #### Internal API
@@ -762,16 +724,15 @@ Deletes an array of DNs from AD. #### Parameters
**_dnList_** `list[str]` -The fully qualified DN to be removed from the directory server. -eg. `["CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM","CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM"]` +The fully qualified DN to be removed from the directory server. E.g. `["CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM","CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM"]`.
#### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. +The first level is the success to the AD server. The second Data level is the status of the actual request. Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
@@ -812,7 +773,7 @@ Since this is a compound request, the data contains an object with it's own requ ### `delete_item` -Deletes a DN from AD. +Delete a DN from AD. #### Internal API
@@ -822,16 +783,15 @@ Deletes a DN from AD. #### Parameters
**_dn_** `str` -The fully qualified DN to be removed from the directory server. -eg. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM` or `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM` +The fully qualified DN to be removed from the directory server. E.g. `CN=jdoe,CN=Users,CN=MY,CN=DOMAIN,CN=COM` or `CN=My Group,CN=Groups,CN=MY,CN=DOMAIN,CN=COM`.
#### Returns
`dict[str, object]` -The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. -The first level is the success to the AD server. The second Data level is the status of the actual request. +The result of this method is a dictionary object with a 'data' dictionary and a 'success' dictionary. +The first level is the success to the AD server. The second Data level is the status of the actual request. Since this is a compound request, the data contains an object with it's own request and results contained within. The object will explain any issues with the request.
@@ -872,8 +832,8 @@ Since this is a compound request, the data contains an object with it's own requ ### `entryRequest` -Some requests require an entry. -Delete for example requires an entry. If an entry is required, the task will not complete without an Entry Request. +Perform an entry request for a task. +Some requests require an entry. Delete, for example, requires an entry. If an entry is required, the task will not complete without an Entry Request. #### Internal API
`SYNO.Entry.Request` @@ -882,11 +842,17 @@ Delete for example requires an entry. If an entry is required, the task will no #### Parameters
**_task_id_** `str` -The ID of the task to be checked. This is provided when making a request. +The ID of the task to be checked. This is provided when making a request. An example Task ID may look like this -`@administrators/Synoads_SYNO.ActiveDirectory.Directory_delete6145EA17C4F03DA9` + `@administrators/Synoads_SYNO.ActiveDirectory.Directory_delete6145EA17C4F03DA9`. +
+#### Returns +
+`Any` +The result of the entry request. +
diff --git a/documentation/docs/apis/classes/docker_api.md b/documentation/docs/apis/classes/docker_api.md index 504704df..1d0ac1f9 100644 --- a/documentation/docs/apis/classes/docker_api.md +++ b/documentation/docs/apis/classes/docker_api.md @@ -11,27 +11,26 @@ title: ✅ Docker ## Overview Docker API implementation. -This class provides methods to interact with Docker containers, images, registries, and projects on a Synology NAS. - -Supported actions: - - **Getters** : - - Get list of containers - - Get resources of all containers - - Get system resources - - List of docker images - - Get list of docker registries - - Get list of container logs - - Get containers resource usage statistics - - Search for docker image in all available registries - - Get list of projects - - Get list of docker networks - - - **Setters** : - - - - - **Actions** : - - Export container profile - - Export container profile and content + This class provides methods to interact with Docker containers, images, registries, and projects on a Synology NAS. + + Supported actions: + - **Getters** : + - Get list of containers + - Get resources of all containers + - Get system resources + - List of docker images + - Get list of docker registries + - Get list of container logs + - Get containers resource usage statistics + - Search for docker image in all available registries + - Get list of projects + - Get list of docker networks + + - **Setters** : + + - **Actions** : + - Export container profile + - Export container profile and content ## Methods ### `containers` Get list of containers. @@ -51,73 +50,73 @@ A dictionary containing the containers information.
Click to expand ```json -{ - "data": { - "1111aaaa-22bb-33cc-44dd-555555eeeeee": { - "containerIds": [ - "21bbe0c6a5d3b246f347367826a78db47f0f334a44bd6621e084f68f0ad63044" - ], - "created_at": "2025-03-14T14:07:04.874304Z", - "enable_service_portal": true, - "id": "187b2816-fd6c-4f87-b178-6d94806c7404", - "is_package": false, - "name": "pihole", - "path": "/volume1/docker/test", - "service_portal_name": "test", - "service_portal_port": 53, - "service_portal_protocol": "http", - "services": [ - { - "display_name": "test (project)", - "id": "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", - "proxy_target": "http://127.0.0.1:53", - "service": "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", - "type": "reverse_proxy" - } - ], - "share_path": "/docker/test", - "state": "", - "status": "STOPPED", - "updated_at": "2025-03-14T15:17:31.840634Z", - "version": 2 + { + "data": { + "1111aaaa-22bb-33cc-44dd-555555eeeeee": { + "containerIds": [ + "21bbe0c6a5d3b246f347367826a78db47f0f334a44bd6621e084f68f0ad63044" + ], + "created_at": "2025-03-14T14:07:04.874304Z", + "enable_service_portal": true, + "id": "187b2816-fd6c-4f87-b178-6d94806c7404", + "is_package": false, + "name": "pihole", + "path": "/volume1/docker/test", + "service_portal_name": "test", + "service_portal_port": 53, + "service_portal_protocol": "http", + "services": [ + { + "display_name": "test (project)", + "id": "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", + "proxy_target": "http://127.0.0.1:53", + "service": "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", + "type": "reverse_proxy" + } + ], + "share_path": "/docker/test", + "state": "", + "status": "STOPPED", + "updated_at": "2025-03-14T15:17:31.840634Z", + "version": 2 + }, + "2222bbbb-33cc-44dd-55ee-666666ffffff": { + "containerIds": [ + "d9301fc3aa925514760e7714a489cc2d14a26ed6e8169479ac6c356de6b5a7d9", + "89d63c6c3c4e299c82c2dcc4ba353c4c1e6c1c938b572153fe9f615646edc4f6", + "4a37c7a4a5cab34658071972c2c2bc3ff89dc6dc1407fd98751c7f227574a088", + "6df4151b6e24ea3b68b62851d65c8a830e342085f6f9cf0cfdf1e6f98357d9b1", + "1a1088cdf8d56e2443c22fa5c6f5658384ba894fe050d82b9214fb84342b0d93", + "36984528684d20c775ac67b3a286e48a5aa8ba73a36f58cfd062a8649d457328" + ], + "created_at": "2024-07-21T11:01:31.019924Z", + "enable_service_portal": true, + "id": "d787e5ac-1b6a-4dd4-a2d9-35bcd5ad9577", + "is_package": false, + "name": "test2", + "path": "/volume1/docker/test2", + "service_portal_name": "test2-server", + "service_portal_port": 2283, + "service_portal_protocol": "http", + "services": [ + { + "display_name": "test2 (project)", + "id": "Docker-Project-d787e5ac-1b6a-4dd4-a2d9-35bcd5ad9577", + "proxy_target": "http://127.0.0.1:2283", + "service": "Docker-Project-d787e5ac-1b6a-4dd4-a2d9-35bcd5ad9577", + "type": "reverse_proxy" + } + ], + "share_path": "/docker/test2", + "state": "", + "status": "ERROR", + "updated_at": "2025-06-12T14:48:08.127657Z", + "version": 2 + } }, - "2222bbbb-33cc-44dd-55ee-666666ffffff": { - "containerIds": [ - "d9301fc3aa925514760e7714a489cc2d14a26ed6e8169479ac6c356de6b5a7d9", - "89d63c6c3c4e299c82c2dcc4ba353c4c1e6c1c938b572153fe9f615646edc4f6", - "4a37c7a4a5cab34658071972c2c2bc3ff89dc6dc1407fd98751c7f227574a088", - "6df4151b6e24ea3b68b62851d65c8a830e342085f6f9cf0cfdf1e6f98357d9b1", - "1a1088cdf8d56e2443c22fa5c6f5658384ba894fe050d82b9214fb84342b0d93", - "36984528684d20c775ac67b3a286e48a5aa8ba73a36f58cfd062a8649d457328" - ], - "created_at": "2024-07-21T11:01:31.019924Z", - "enable_service_portal": true, - "id": "d787e5ac-1b6a-4dd4-a2d9-35bcd5ad9577", - "is_package": false, - "name": "test2", - "path": "/volume1/docker/test2", - "service_portal_name": "test2-server", - "service_portal_port": 2283, - "service_portal_protocol": "http", - "services": [ - { - "display_name": "test2 (project)", - "id": "Docker-Project-d787e5ac-1b6a-4dd4-a2d9-35bcd5ad9577", - "proxy_target": "http://127.0.0.1:2283", - "service": "Docker-Project-d787e5ac-1b6a-4dd4-a2d9-35bcd5ad9577", - "type": "reverse_proxy" - } - ], - "share_path": "/docker/test2", - "state": "", - "status": "ERROR", - "updated_at": "2025-06-12T14:48:08.127657Z", - "version": 2 - } - }, - "success": true -} -``` + "success": true + } + ```
@@ -143,33 +142,33 @@ A dictionary containing the resources information of the containers.
Click to expand ```json - { - "data": { - "resources": [ - { - "cpu": 0, - "memory": 21106688, - "memoryPercent": 0.517403244972229, - "name": "container1" - }, - { - "cpu": 0, - "memory": 0, - "memoryPercent": 0, - "name": "container2" - }, - { - "cpu": 0, - "memory": 0, - "memoryPercent": 0, - "name": "stopped_container" - } - ] - }, - "httpd_restart": false, - "success": true - } -``` + { + "data": { + "resources": [ + { + "cpu": 0, + "memory": 21106688, + "memoryPercent": 0.517403244972229, + "name": "container1" + }, + { + "cpu": 0, + "memory": 0, + "memoryPercent": 0, + "name": "container2" + }, + { + "cpu": 0, + "memory": 0, + "memoryPercent": 0, + "name": "stopped_container" + } + ] + }, + "httpd_restart": false, + "success": true + } + ```
@@ -178,7 +177,7 @@ A dictionary containing the resources information of the containers. ### `system_resources` -Get system resources +Get system resources. #### Internal API
@@ -195,119 +194,119 @@ A dictionary containing the system resources information.
Click to expand ```json -{ - "data" : { - "cpu" : { - "15min_load" : 14, - "1min_load" : 29, - "5min_load" : 16, - "device" : "System", - "other_load" : 2, - "system_load" : 0, - "user_load" : 1 - }, - "disk" : { - "disk" : [ - { - "device" : "sata2", - "display_name" : "Drive 2", - "read_access" : 0, - "read_byte" : 0, - "type" : "internal", - "utilization" : 0, - "write_access" : 0, - "write_byte" : 0 - }, - { - "device" : "sata1", - "display_name" : "Drive 1", - "read_access" : 0, - "read_byte" : 0, - "type" : "internal", - "utilization" : 0, - "write_access" : 0, - "write_byte" : 0 - } - ], - "total" : { - "device" : "total", - "read_access" : 0, - "read_byte" : 0, - "utilization" : 0, - "write_access" : 0, - "write_byte" : 0 - } - }, - "lun" : [], - "memory" : { - "avail_real" : 444840, - "avail_swap" : 4163752, - "buffer" : 21716, - "cached" : 2658180, - "device" : "Memory", - "memory_size" : 4194304, - "real_usage" : 21, - "si_disk" : 0, - "so_disk" : 0, - "swap_usage" : 7, - "total_real" : 3983740, - "total_swap" : 4489140 - }, - "network" : [ - { - "device" : "total", - "rx" : 6822, - "tx" : 6336 - }, - { - "device" : "eth0", - "rx" : 0, - "tx" : 0 - }, - { - "device" : "eth1", - "rx" : 0, - "tx" : 0 - }, - { - "device" : "eth2", - "rx" : 6822, - "tx" : 6336 - } - ], - "nfs" : [], - "smb" : { - "smb_cmd" : [], - "smb_cpu" : [], - "smb_rwpkt" : [] - }, - "space" : { - "total" : { - "device" : "total", - "read_access" : 0, - "read_byte" : 0, - "utilization" : 0, - "write_access" : 0, - "write_byte" : 0 - }, - "volume" : [ - { - "device" : "dm-1", - "display_name" : "volume1", - "read_access" : 0, - "read_byte" : 0, - "utilization" : 0, - "write_access" : 0, - "write_byte" : 0 - } - ] - }, - "time" : 1749998465 - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "cpu" : { + "15min_load" : 14, + "1min_load" : 29, + "5min_load" : 16, + "device" : "System", + "other_load" : 2, + "system_load" : 0, + "user_load" : 1 + }, + "disk" : { + "disk" : [ + { + "device" : "sata2", + "display_name" : "Drive 2", + "read_access" : 0, + "read_byte" : 0, + "type" : "internal", + "utilization" : 0, + "write_access" : 0, + "write_byte" : 0 + }, + { + "device" : "sata1", + "display_name" : "Drive 1", + "read_access" : 0, + "read_byte" : 0, + "type" : "internal", + "utilization" : 0, + "write_access" : 0, + "write_byte" : 0 + } + ], + "total" : { + "device" : "total", + "read_access" : 0, + "read_byte" : 0, + "utilization" : 0, + "write_access" : 0, + "write_byte" : 0 + } + }, + "lun" : [], + "memory" : { + "avail_real" : 444840, + "avail_swap" : 4163752, + "buffer" : 21716, + "cached" : 2658180, + "device" : "Memory", + "memory_size" : 4194304, + "real_usage" : 21, + "si_disk" : 0, + "so_disk" : 0, + "swap_usage" : 7, + "total_real" : 3983740, + "total_swap" : 4489140 + }, + "network" : [ + { + "device" : "total", + "rx" : 6822, + "tx" : 6336 + }, + { + "device" : "eth0", + "rx" : 0, + "tx" : 0 + }, + { + "device" : "eth1", + "rx" : 0, + "tx" : 0 + }, + { + "device" : "eth2", + "rx" : 6822, + "tx" : 6336 + } + ], + "nfs" : [], + "smb" : { + "smb_cmd" : [], + "smb_cpu" : [], + "smb_rwpkt" : [] + }, + "space" : { + "total" : { + "device" : "total", + "read_access" : 0, + "read_byte" : 0, + "utilization" : 0, + "write_access" : 0, + "write_byte" : 0 + }, + "volume" : [ + { + "device" : "dm-1", + "display_name" : "volume1", + "read_access" : 0, + "read_byte" : 0, + "utilization" : 0, + "write_access" : 0, + "write_byte" : 0 + } + ] + }, + "time" : 1749998465 + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -346,30 +345,30 @@ A dictionary containing the list of downloaded images.
Click to expand ```json -{ - "data" : { - "images" : [ - { - "created" : 1745034718, - "description" : "", - "digest" : "", - "id" : "sha256:14300de7e087290520999f00d6a12b61385d1fe780ea83f38eabb7e8be66225f", - "remote_digest" : "", - "repository" : "caddy", - "size" : 50509416, - "tags" : [ "alpine" ], - "upgradable" : false, - "virtual_size" : 50509416 - } - ], - "limit" : 1, - "offset" : 0, - "total" : 1 - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "images" : [ + { + "created" : 1745034718, + "description" : "", + "digest" : "", + "id" : "sha256:14300de7e087290520999f00d6a12b61385d1fe780ea83f38eabb7e8be66225f", + "remote_digest" : "", + "repository" : "caddy", + "size" : 50509416, + "tags" : [ "alpine" ], + "upgradable" : false, + "virtual_size" : 50509416 + } + ], + "limit" : 1, + "offset" : 0, + "total" : 1 + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -379,58 +378,42 @@ A dictionary containing the list of downloaded images. ### `images_registry_resources` Get list of docker registries. -Example return --------------- -```json -{ - "data" : { - "offset" : 0, - "registries" : [ - { - "enable_registry_mirror" : false, - "enable_trust_SSC" : true, - "mirror_urls" : [], - "name" : "Docker Hub", - "syno" : true, - "url" : "https://registry.hub.docker.com" - } - ], - "total" : 1, - "using" : "Docker Hub" - }, - "httpd_restart" : false, - "success" : true -} -``` + #### Internal API
`SYNO.Docker.Registry`
+#### Returns +
+`dict[str, object]` +A dictionary containing the list of docker registries. + +
#### Example return
Click to expand ```json -{ - "data" : { - "offset" : 0, - "registries" : [ - { - "enable_registry_mirror" : false, - "enable_trust_SSC" : true, - "mirror_urls" : [], - "name" : "Docker Hub", - "syno" : true, - "url" : "https://registry.hub.docker.com" - } - ], - "total" : 1, - "using" : "Docker Hub" - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "offset" : 0, + "registries" : [ + { + "enable_registry_mirror" : false, + "enable_trust_SSC" : true, + "mirror_urls" : [], + "name" : "Docker Hub", + "syno" : true, + "url" : "https://registry.hub.docker.com" + } + ], + "total" : 1, + "using" : "Docker Hub" + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -440,76 +423,51 @@ Example return ### `network` Get list of docker networks. -Example return --------------- -```json -{ - "data" : { - "network" : [ - { - "containers" : [ "vault" ], - "driver" : "bridge", - "enable_ipv6" : false, - "gateway" : "172.22.0.1", - "id" : "b741915823aacdffc8ab806ab348e198c2c486b4dd5df2627b0d586259926b1a", - "iprange" : "", - "name" : "vault_default", - "subnet" : "172.22.0.0/16" - }, - { - "containers" : [], - "driver" : "host", - "enable_ipv6" : false, - "gateway" : "", - "id" : "2fc7ebae3901359e7bc9d7b50fad1f6aa2f8c1076474cadc9f83b3256f921ff3", - "iprange" : "", - "name" : "host", - "subnet" : "" - } - ] - }, - "httpd_restart" : false, - "success" : true -} -``` + #### Internal API
`SYNO.Docker.Network`
+#### Returns +
+`dict[str, object]` +A dictionary containing the list of docker networks. + +
#### Example return
Click to expand ```json -{ - "data" : { - "network" : [ - { - "containers" : [ "vault" ], - "driver" : "bridge", - "enable_ipv6" : false, - "gateway" : "172.22.0.1", - "id" : "b741915823aacdffc8ab806ab348e198c2c486b4dd5df2627b0d586259926b1a", - "iprange" : "", - "name" : "vault_default", - "subnet" : "172.22.0.0/16" - }, - { - "containers" : [], - "driver" : "host", - "enable_ipv6" : false, - "gateway" : "", - "id" : "2fc7ebae3901359e7bc9d7b50fad1f6aa2f8c1076474cadc9f83b3256f921ff3", - "iprange" : "", - "name" : "host", - "subnet" : "" - } - ] - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "network" : [ + { + "containers" : [ "vault" ], + "driver" : "bridge", + "enable_ipv6" : false, + "gateway" : "172.22.0.1", + "id" : "b741915823aacdffc8ab806ab348e198c2c486b4dd5df2627b0d586259926b1a", + "iprange" : "", + "name" : "vault_default", + "subnet" : "172.22.0.0/16" + }, + { + "containers" : [], + "driver" : "host", + "enable_ipv6" : false, + "gateway" : "", + "id" : "2fc7ebae3901359e7bc9d7b50fad1f6aa2f8c1076474cadc9f83b3256f921ff3", + "iprange" : "", + "name" : "host", + "subnet" : "" + } + ] + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -528,7 +486,7 @@ Search for docker image in all available registries. #### Parameters
**_query_** `str` -name of the docker image to search for. Defaults to None. +Name of the docker image to search for. Defaults to None.
@@ -542,37 +500,37 @@ A dictionary containing the search results for the docker image.
Click to expand ```json -{ - "data" : { - "data" : [ - { - "description" : "Caddy 2 is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go.", - "downloads" : 650989718, - "is_automated" : false, - "is_official" : true, - "name" : "caddy", - "registry" : "https://registry.hub.docker.com", - "star_count" : 881 - }, - { - "description" : "Caddy is a lightweight, general-purpose web server.", - "downloads" : 111974910, - "is_automated" : true, - "is_official" : false, - "name" : "abiosoft/caddy", - "registry" : "https://registry.hub.docker.com", - "star_count" : 289 - } - ], - "limit" : 50, - "offset" : 0, - "page_size" : 50, - "total" : 6647 - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "data" : [ + { + "description" : "Caddy 2 is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go.", + "downloads" : 650989718, + "is_automated" : false, + "is_official" : true, + "name" : "caddy", + "registry" : "https://registry.hub.docker.com", + "star_count" : 881 + }, + { + "description" : "Caddy is a lightweight, general-purpose web server.", + "downloads" : 111974910, + "is_automated" : true, + "is_official" : false, + "name" : "abiosoft/caddy", + "registry" : "https://registry.hub.docker.com", + "star_count" : 289 + } + ], + "limit" : 50, + "offset" : 0, + "page_size" : 50, + "total" : 6647 + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -582,120 +540,73 @@ A dictionary containing the search results for the docker image. ### `list_projects` Get list of projects. -Example return --------------- -```json -{ - "data" : { - "187b2816-fd6c-4f87-b178-6d94806c7404" : { - "containerIds" : [ "21bbe0c6a5d3b246f347367826a78db47f0f334a44bd6621e084f68f0ad63044" ], - "created_at" : "2025-03-14T14:07:04.874304Z", - "enable_service_portal" : true, - "id" : "187b2816-fd6c-4f87-b178-6d94806c7404", - "is_package" : false, - "name" : "project1", - "path" : "/volume1/docker/project1", - "service_portal_name" : "project1", - "service_portal_port" : 53, - "service_portal_protocol" : "http", - "services" : [ - { - "display_name" : "project1 (project)", - "id" : "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", - "proxy_target" : "http://127.0.0.1:53", - "service" : "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", - "type" : "reverse_proxy" - } - ], - "share_path" : "/docker/project1", - "state" : "", - "status" : "STOPPED", - "updated_at" : "2025-03-14T15:17:31.840634Z", - "version" : 2 - }, - "3c091e8b-f68f-4161-97a3-fc3db3f4bdc9" : { - "containerIds" : [ "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4" ], - "created_at" : "2025-05-27T08:33:03.213407Z", - "enable_service_portal" : false, - "id" : "3c091e8b-f68f-4161-97a3-fc3db3f4bdc9", - "is_package" : false, - "name" : "project2", - "path" : "/volume1/docker/project2", - "service_portal_name" : "", - "service_portal_port" : 0, - "service_portal_protocol" : "", - "services" : [], - "share_path" : "/docker/project2", - "state" : "", - "status" : "RUNNING", - "updated_at" : "2025-06-15T10:38:52.247951Z", - "version" : 2 - } - }, - "httpd_restart" : false, - "success" : true -} -``` + #### Internal API
`SYNO.Docker.Project`
+#### Returns +
+`dict[str, object]` +A dictionary containing the list of projects. + +
#### Example return
Click to expand ```json -{ - "data" : { - "187b2816-fd6c-4f87-b178-6d94806c7404" : { - "containerIds" : [ "21bbe0c6a5d3b246f347367826a78db47f0f334a44bd6621e084f68f0ad63044" ], - "created_at" : "2025-03-14T14:07:04.874304Z", - "enable_service_portal" : true, - "id" : "187b2816-fd6c-4f87-b178-6d94806c7404", - "is_package" : false, - "name" : "project1", - "path" : "/volume1/docker/project1", - "service_portal_name" : "project1", - "service_portal_port" : 53, - "service_portal_protocol" : "http", - "services" : [ - { - "display_name" : "project1 (project)", - "id" : "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", - "proxy_target" : "http://127.0.0.1:53", - "service" : "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", - "type" : "reverse_proxy" - } - ], - "share_path" : "/docker/project1", - "state" : "", - "status" : "STOPPED", - "updated_at" : "2025-03-14T15:17:31.840634Z", - "version" : 2 - }, - "3c091e8b-f68f-4161-97a3-fc3db3f4bdc9" : { - "containerIds" : [ "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4" ], - "created_at" : "2025-05-27T08:33:03.213407Z", - "enable_service_portal" : false, - "id" : "3c091e8b-f68f-4161-97a3-fc3db3f4bdc9", - "is_package" : false, - "name" : "project2", - "path" : "/volume1/docker/project2", - "service_portal_name" : "", - "service_portal_port" : 0, - "service_portal_protocol" : "", - "services" : [], - "share_path" : "/docker/project2", - "state" : "", - "status" : "RUNNING", - "updated_at" : "2025-06-15T10:38:52.247951Z", - "version" : 2 - } - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "187b2816-fd6c-4f87-b178-6d94806c7404" : { + "containerIds" : [ "21bbe0c6a5d3b246f347367826a78db47f0f334a44bd6621e084f68f0ad63044" ], + "created_at" : "2025-03-14T14:07:04.874304Z", + "enable_service_portal" : true, + "id" : "187b2816-fd6c-4f87-b178-6d94806c7404", + "is_package" : false, + "name" : "project1", + "path" : "/volume1/docker/project1", + "service_portal_name" : "project1", + "service_portal_port" : 53, + "service_portal_protocol" : "http", + "services" : [ + { + "display_name" : "project1 (project)", + "id" : "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", + "proxy_target" : "http://127.0.0.1:53", + "service" : "Docker-Project-187b2816-fd6c-4f87-b178-6d94806c7404", + "type" : "reverse_proxy" + } + ], + "share_path" : "/docker/project1", + "state" : "", + "status" : "STOPPED", + "updated_at" : "2025-03-14T15:17:31.840634Z", + "version" : 2 + }, + "3c091e8b-f68f-4161-97a3-fc3db3f4bdc9" : { + "containerIds" : [ "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4" ], + "created_at" : "2025-05-27T08:33:03.213407Z", + "enable_service_portal" : false, + "id" : "3c091e8b-f68f-4161-97a3-fc3db3f4bdc9", + "is_package" : false, + "name" : "project2", + "path" : "/volume1/docker/project2", + "service_portal_name" : "", + "service_portal_port" : 0, + "service_portal_protocol" : "", + "services" : [], + "share_path" : "/docker/project2", + "state" : "", + "status" : "RUNNING", + "updated_at" : "2025-06-15T10:38:52.247951Z", + "version" : 2 + } + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -728,309 +639,309 @@ A dictionary containing the project information.
Click to expand ```json -{ - "data" : { - "containerIds" : [ "1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf" ], - "containers" : [ - { - "AppArmorProfile" : "docker-default", - "Args" : [ "server", "-config=/vault/file/" ], - "Config" : { - "AttachStderr" : true, - "AttachStdin" : false, - "AttachStdout" : true, - "Cmd" : null, - "Domainname" : "", - "Entrypoint" : [ "vault", "server", "-config=/vault/file/" ], - "Env" : [ - "VAULT_RAFT_PATH=/vault/file", - "VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200", - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - "NAME=vault", - "VERSION=" - ], - "ExposedPorts" : { - "8200/tcp" : {} - }, - "Healthcheck" : { - "Interval" : 30000000000, - "Retries" : 5, - "Test" : [ "CMD", "vault", "status" ], - "Timeout" : 10000000000 - }, - "Hostname" : "vault", - "Image" : "hashicorp/vault:latest", - "Labels" : { - "com.docker.compose.config-hash" : "6a08fb0e6d57f8ad25b3d78cac40d369be831be5cf98406520e514d68aa03251", - "com.docker.compose.container-number" : "1", - "com.docker.compose.depends_on" : "", - "com.docker.compose.image" : "sha256:2006f053b116f3a57dad1d8fff9d19c13f3e801e594dcbd58e219d4ccb654337", - "com.docker.compose.oneoff" : "False", - "com.docker.compose.project" : "vault", - "com.docker.compose.project.config_files" : "/volume1/docker/vault/compose.yaml", - "com.docker.compose.project.working_dir" : "/volume1/docker/vault", - "com.docker.compose.replace" : "1153d033ece9eb4242926f805a211daed65922652fdf73ffcf8147e20e4c0ce2", - "com.docker.compose.service" : "vault", - "com.docker.compose.version" : "2.20.1", - "description" : "Vault is a tool for securely accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, and more. Vault provides a unified interface to any secret, while providing tight access control and recording a detailed audit log.", - "maintainer" : "Vault Team ", - "name" : "Vault", - "release" : "322786e236e268532e4b189845971ba67b5cbb23", - "revision" : "322786e236e268532e4b189845971ba67b5cbb23", - "summary" : "Vault is a tool for securely accessing secrets.", - "vendor" : "HashiCorp", - "version" : "1.19.4" - }, - "OnBuild" : null, - "OpenStdin" : false, - "StdinOnce" : false, - "Tty" : false, - "User" : "", - "Volumes" : { - "/vault/file" : {}, - "/vault/logs" : {} - }, - "WorkingDir" : "/" - }, - "Created" : "2025-05-25T17:57:06.296933361Z", - "Driver" : "btrfs", - "ExecIDs" : null, - "GraphDriver" : { - "Data" : null, - "Name" : "btrfs" - }, - "HostConfig" : { - "AutoRemove" : false, - "Binds" : [ - "/volume1/docker/vault/data:/vault/file:rw", - "/volume1/docker/vault/logs:/vault/logs:rw", - "/volume1/docker/vault/config:/vault/config:rw", - "/volume1/docker/vault/plugins:/vault/plugins:rw", - "/etc/localtime:/etc/localtime:ro" - ], - "BlkioDeviceReadBps" : null, - "BlkioDeviceReadIOps" : null, - "BlkioDeviceWriteBps" : null, - "BlkioDeviceWriteIOps" : null, - "BlkioWeight" : 0, - "BlkioWeightDevice" : null, - "CapAdd" : [ "IPC_LOCK" ], - "CapDrop" : null, - "Cgroup" : "", - "CgroupParent" : "", - "CgroupnsMode" : "host", - "ConsoleSize" : [ 0, 0 ], - "ContainerIDFile" : "", - "CpuCount" : 0, - "CpuPercent" : 0, - "CpuPeriod" : 0, - "CpuQuota" : 0, - "CpuRealtimePeriod" : 0, - "CpuRealtimeRuntime" : 0, - "CpuShares" : 768, - "CpusetCpus" : "", - "CpusetMems" : "", - "DeviceCgroupRules" : null, - "DeviceRequests" : null, - "Devices" : null, - "Dns" : [], - "DnsOptions" : [], - "DnsSearch" : [], - "ExtraHosts" : [], - "GroupAdd" : null, - "IOMaximumBandwidth" : 0, - "IOMaximumIOps" : 0, - "IpcMode" : "private", - "Isolation" : "", - "Links" : null, - "LogConfig" : { - "Config" : {}, - "Type" : "db" - }, - "MaskedPaths" : [ - "/proc/asound", - "/proc/acpi", - "/proc/kcore", - "/proc/keys", - "/proc/latency_stats", - "/proc/timer_list", - "/proc/timer_stats", - "/proc/sched_debug", - "/proc/scsi", - "/sys/firmware" - ], - "Memory" : 536870912, - "MemoryReservation" : 0, - "MemorySwap" : 1073741824, - "MemorySwappiness" : null, - "NanoCpus" : 0, - "NetworkMode" : "vault_default", - "OomKillDisable" : false, - "OomScoreAdj" : 0, - "PidMode" : "", - "PidsLimit" : null, - "PortBindings" : { - "8200/tcp" : [ - { - "HostIp" : "", - "HostPort" : "8205" - } - ] - }, - "Privileged" : false, - "PublishAllPorts" : false, - "ReadonlyPaths" : [ - "/proc/bus", - "/proc/fs", - "/proc/irq", - "/proc/sys", - "/proc/sysrq-trigger" - ], - "ReadonlyRootfs" : false, - "RestartPolicy" : { - "MaximumRetryCount" : 5, - "Name" : "on-failure" - }, - "Runtime" : "runc", - "SecurityOpt" : [ "no-new-privileges:true" ], - "ShmSize" : 67108864, - "UTSMode" : "", - "Ulimits" : null, - "UsernsMode" : "", - "VolumeDriver" : "", - "VolumesFrom" : null - }, - "HostnamePath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/hostname", - "HostsPath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/hosts", - "Id" : "1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf", - "Image" : "sha256:2006f053b116f3a57dad1d8fff9d19c13f3e801e594dcbd58e219d4ccb654337", - "LogPath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/log.db", - "MountLabel" : "", - "Mounts" : [ - { - "Destination" : "/vault/plugins", - "Mode" : "rw", - "Propagation" : "rprivate", - "RW" : true, - "Source" : "/volume1/docker/vault/plugins", - "Type" : "bind" - }, - { - "Destination" : "/etc/localtime", - "Mode" : "ro", - "Propagation" : "rprivate", - "RW" : false, - "Source" : "/etc/localtime", - "Type" : "bind" - }, - { - "Destination" : "/vault/config", - "Mode" : "rw", - "Propagation" : "rprivate", - "RW" : true, - "Source" : "/volume1/docker/vault/config", - "Type" : "bind" - }, - { - "Destination" : "/vault/file", - "Mode" : "rw", - "Propagation" : "rprivate", - "RW" : true, - "Source" : "/volume1/docker/vault/data", - "Type" : "bind" - }, - { - "Destination" : "/vault/logs", - "Mode" : "rw", - "Propagation" : "rprivate", - "RW" : true, - "Source" : "/volume1/docker/vault/logs", - "Type" : "bind" - } - ], - "Name" : "/vault", - "NetworkSettings" : { - "Bridge" : "", - "EndpointID" : "", - "Gateway" : "", - "GlobalIPv6Address" : "", - "GlobalIPv6PrefixLen" : 0, - "HairpinMode" : false, - "IPAddress" : "", - "IPPrefixLen" : 0, - "IPv6Gateway" : "", - "LinkLocalIPv6Address" : "", - "LinkLocalIPv6PrefixLen" : 0, - "MacAddress" : "", - "Networks" : { - "vault_default" : { - "Aliases" : [ "vault", "vault", "1f2aa674d794" ], - "DriverOpts" : null, - "EndpointID" : "", - "Gateway" : "", - "GlobalIPv6Address" : "", - "GlobalIPv6PrefixLen" : 0, - "IPAMConfig" : null, - "IPAddress" : "", - "IPPrefixLen" : 0, - "IPv6Gateway" : "", - "Links" : null, - "MacAddress" : "", - "NetworkID" : "b741915823aacdffc8ab806ab348e198c2c486b4dd5df2627b0d586259926b1a" - } - }, - "Ports" : {}, - "SandboxID" : "d523ddff9d90b2ecc74f20c33db7b4898fa2869f10899ccc6567febd64d7142c", - "SandboxKey" : "/var/run/docker/netns/d523ddff9d90", - "SecondaryIPAddresses" : null, - "SecondaryIPv6Addresses" : null - }, - "Path" : "vault", - "Platform" : "linux", - "ProcessLabel" : "", - "ResolvConfPath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/resolv.conf", - "RestartCount" : 5, - "State" : { - "Dead" : false, - "Error" : "", - "ExitCode" : 1, - "FinishedAt" : "2025-05-25T17:57:30.266770048Z", - "Health" : { - "FailingStreak" : 0, - "Log" : [], - "Status" : "unhealthy" - }, - "OOMKilled" : false, - "Paused" : false, - "Pid" : 0, - "Restarting" : false, - "Running" : false, - "StartedAt" : "2025-05-25T17:57:30.184237615Z", - "Status" : "exited" - } - } - ], - "content" : "docker-compose.yml contet", - "created_at" : "2025-05-25T17:31:00.875402Z", - "enable_service_portal" : false, - "id" : "b4d44e6c-5ab4-45f7-b380-481ef9839df1", - "is_package" : false, - "name" : "vault", - "path" : "/volume1/docker/vault", - "service_portal_name" : "", - "service_portal_port" : 0, - "service_portal_protocol" : "", - "services" : null, - "share_path" : "/docker/vault", - "state" : "", - "status" : "STOPPED", - "updated_at" : "2025-05-25T17:57:06.257863Z", - "version" : 2 - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "containerIds" : [ "1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf" ], + "containers" : [ + { + "AppArmorProfile" : "docker-default", + "Args" : [ "server", "-config=/vault/file/" ], + "Config" : { + "AttachStderr" : true, + "AttachStdin" : false, + "AttachStdout" : true, + "Cmd" : null, + "Domainname" : "", + "Entrypoint" : [ "vault", "server", "-config=/vault/file/" ], + "Env" : [ + "VAULT_RAFT_PATH=/vault/file", + "VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "NAME=vault", + "VERSION=" + ], + "ExposedPorts" : { + "8200/tcp" : {} + }, + "Healthcheck" : { + "Interval" : 30000000000, + "Retries" : 5, + "Test" : [ "CMD", "vault", "status" ], + "Timeout" : 10000000000 + }, + "Hostname" : "vault", + "Image" : "hashicorp/vault:latest", + "Labels" : { + "com.docker.compose.config-hash" : "6a08fb0e6d57f8ad25b3d78cac40d369be831be5cf98406520e514d68aa03251", + "com.docker.compose.container-number" : "1", + "com.docker.compose.depends_on" : "", + "com.docker.compose.image" : "sha256:2006f053b116f3a57dad1d8fff9d19c13f3e801e594dcbd58e219d4ccb654337", + "com.docker.compose.oneoff" : "False", + "com.docker.compose.project" : "vault", + "com.docker.compose.project.config_files" : "/volume1/docker/vault/compose.yaml", + "com.docker.compose.project.working_dir" : "/volume1/docker/vault", + "com.docker.compose.replace" : "1153d033ece9eb4242926f805a211daed65922652fdf73ffcf8147e20e4c0ce2", + "com.docker.compose.service" : "vault", + "com.docker.compose.version" : "2.20.1", + "description" : "Vault is a tool for securely accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, certificates, and more. Vault provides a unified interface to any secret, while providing tight access control and recording a detailed audit log.", + "maintainer" : "Vault Team ", + "name" : "Vault", + "release" : "322786e236e268532e4b189845971ba67b5cbb23", + "revision" : "322786e236e268532e4b189845971ba67b5cbb23", + "summary" : "Vault is a tool for securely accessing secrets.", + "vendor" : "HashiCorp", + "version" : "1.19.4" + }, + "OnBuild" : null, + "OpenStdin" : false, + "StdinOnce" : false, + "Tty" : false, + "User" : "", + "Volumes" : { + "/vault/file" : {}, + "/vault/logs" : {} + }, + "WorkingDir" : "/" + }, + "Created" : "2025-05-25T17:57:06.296933361Z", + "Driver" : "btrfs", + "ExecIDs" : null, + "GraphDriver" : { + "Data" : null, + "Name" : "btrfs" + }, + "HostConfig" : { + "AutoRemove" : false, + "Binds" : [ + "/volume1/docker/vault/data:/vault/file:rw", + "/volume1/docker/vault/logs:/vault/logs:rw", + "/volume1/docker/vault/config:/vault/config:rw", + "/volume1/docker/vault/plugins:/vault/plugins:rw", + "/etc/localtime:/etc/localtime:ro" + ], + "BlkioDeviceReadBps" : null, + "BlkioDeviceReadIOps" : null, + "BlkioDeviceWriteBps" : null, + "BlkioDeviceWriteIOps" : null, + "BlkioWeight" : 0, + "BlkioWeightDevice" : null, + "CapAdd" : [ "IPC_LOCK" ], + "CapDrop" : null, + "Cgroup" : "", + "CgroupParent" : "", + "CgroupnsMode" : "host", + "ConsoleSize" : [ 0, 0 ], + "ContainerIDFile" : "", + "CpuCount" : 0, + "CpuPercent" : 0, + "CpuPeriod" : 0, + "CpuQuota" : 0, + "CpuRealtimePeriod" : 0, + "CpuRealtimeRuntime" : 0, + "CpuShares" : 768, + "CpusetCpus" : "", + "CpusetMems" : "", + "DeviceCgroupRules" : null, + "DeviceRequests" : null, + "Devices" : null, + "Dns" : [], + "DnsOptions" : [], + "DnsSearch" : [], + "ExtraHosts" : [], + "GroupAdd" : null, + "IOMaximumBandwidth" : 0, + "IOMaximumIOps" : 0, + "IpcMode" : "private", + "Isolation" : "", + "Links" : null, + "LogConfig" : { + "Config" : {}, + "Type" : "db" + }, + "MaskedPaths" : [ + "/proc/asound", + "/proc/acpi", + "/proc/kcore", + "/proc/keys", + "/proc/latency_stats", + "/proc/timer_list", + "/proc/timer_stats", + "/proc/sched_debug", + "/proc/scsi", + "/sys/firmware" + ], + "Memory" : 536870912, + "MemoryReservation" : 0, + "MemorySwap" : 1073741824, + "MemorySwappiness" : null, + "NanoCpus" : 0, + "NetworkMode" : "vault_default", + "OomKillDisable" : false, + "OomScoreAdj" : 0, + "PidMode" : "", + "PidsLimit" : null, + "PortBindings" : { + "8200/tcp" : [ + { + "HostIp" : "", + "HostPort" : "8205" + } + ] + }, + "Privileged" : false, + "PublishAllPorts" : false, + "ReadonlyPaths" : [ + "/proc/bus", + "/proc/fs", + "/proc/irq", + "/proc/sys", + "/proc/sysrq-trigger" + ], + "ReadonlyRootfs" : false, + "RestartPolicy" : { + "MaximumRetryCount" : 5, + "Name" : "on-failure" + }, + "Runtime" : "runc", + "SecurityOpt" : [ "no-new-privileges:true" ], + "ShmSize" : 67108864, + "UTSMode" : "", + "Ulimits" : null, + "UsernsMode" : "", + "VolumeDriver" : "", + "VolumesFrom" : null + }, + "HostnamePath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/hostname", + "HostsPath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/hosts", + "Id" : "1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf", + "Image" : "sha256:2006f053b116f3a57dad1d8fff9d19c13f3e801e594dcbd58e219d4ccb654337", + "LogPath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/log.db", + "MountLabel" : "", + "Mounts" : [ + { + "Destination" : "/vault/plugins", + "Mode" : "rw", + "Propagation" : "rprivate", + "RW" : true, + "Source" : "/volume1/docker/vault/plugins", + "Type" : "bind" + }, + { + "Destination" : "/etc/localtime", + "Mode" : "ro", + "Propagation" : "rprivate", + "RW" : false, + "Source" : "/etc/localtime", + "Type" : "bind" + }, + { + "Destination" : "/vault/config", + "Mode" : "rw", + "Propagation" : "rprivate", + "RW" : true, + "Source" : "/volume1/docker/vault/config", + "Type" : "bind" + }, + { + "Destination" : "/vault/file", + "Mode" : "rw", + "Propagation" : "rprivate", + "RW" : true, + "Source" : "/volume1/docker/vault/data", + "Type" : "bind" + }, + { + "Destination" : "/vault/logs", + "Mode" : "rw", + "Propagation" : "rprivate", + "RW" : true, + "Source" : "/volume1/docker/vault/logs", + "Type" : "bind" + } + ], + "Name" : "/vault", + "NetworkSettings" : { + "Bridge" : "", + "EndpointID" : "", + "Gateway" : "", + "GlobalIPv6Address" : "", + "GlobalIPv6PrefixLen" : 0, + "HairpinMode" : false, + "IPAddress" : "", + "IPPrefixLen" : 0, + "IPv6Gateway" : "", + "LinkLocalIPv6Address" : "", + "LinkLocalIPv6PrefixLen" : 0, + "MacAddress" : "", + "Networks" : { + "vault_default" : { + "Aliases" : [ "vault", "vault", "1f2aa674d794" ], + "DriverOpts" : null, + "EndpointID" : "", + "Gateway" : "", + "GlobalIPv6Address" : "", + "GlobalIPv6PrefixLen" : 0, + "IPAMConfig" : null, + "IPAddress" : "", + "IPPrefixLen" : 0, + "IPv6Gateway" : "", + "Links" : null, + "MacAddress" : "", + "NetworkID" : "b741915823aacdffc8ab806ab348e198c2c486b4dd5df2627b0d586259926b1a" + } + }, + "Ports" : {}, + "SandboxID" : "d523ddff9d90b2ecc74f20c33db7b4898fa2869f10899ccc6567febd64d7142c", + "SandboxKey" : "/var/run/docker/netns/d523ddff9d90", + "SecondaryIPAddresses" : null, + "SecondaryIPv6Addresses" : null + }, + "Path" : "vault", + "Platform" : "linux", + "ProcessLabel" : "", + "ResolvConfPath" : "/volume1/@docker/containers/1f2aa674d7942c25789c144c1e4ea04388e5a914e1ed3d7a1b8978f8f2f81ebf/resolv.conf", + "RestartCount" : 5, + "State" : { + "Dead" : false, + "Error" : "", + "ExitCode" : 1, + "FinishedAt" : "2025-05-25T17:57:30.266770048Z", + "Health" : { + "FailingStreak" : 0, + "Log" : [], + "Status" : "unhealthy" + }, + "OOMKilled" : false, + "Paused" : false, + "Pid" : 0, + "Restarting" : false, + "Running" : false, + "StartedAt" : "2025-05-25T17:57:30.184237615Z", + "Status" : "exited" + } + } + ], + "content" : "docker-compose.yml contet", + "created_at" : "2025-05-25T17:31:00.875402Z", + "enable_service_portal" : false, + "id" : "b4d44e6c-5ab4-45f7-b380-481ef9839df1", + "is_package" : false, + "name" : "vault", + "path" : "/volume1/docker/vault", + "service_portal_name" : "", + "service_portal_port" : 0, + "service_portal_protocol" : "", + "services" : null, + "share_path" : "/docker/vault", + "state" : "", + "status" : "STOPPED", + "updated_at" : "2025-05-25T17:57:06.257863Z", + "version" : 2 + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -1049,7 +960,7 @@ Start a container by its name. #### Parameters
**_container_** `str` -The name of the container +The name of the container.
@@ -1063,18 +974,18 @@ A dictionary containing the result of the export operation.
Click to expand ```json -{ - "data" : { - "cpu" : 0, - "memory" : 21241856, - "memoryPercent" : 0.52071672677993774, - "name" : "glance", - "start_dependent_container" : false - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "cpu" : 0, + "memory" : 21241856, + "memoryPercent" : 0.52071672677993774, + "name" : "glance", + "start_dependent_container" : false + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -1093,7 +1004,7 @@ Stop a container by its name. #### Parameters
**_container_** `str` -The name of the container +The name of the container.
@@ -1107,17 +1018,17 @@ A dictionary containing the result of the stop operation.
Click to expand ```json -{ - "data" : { - "cpu" : 0, - "memory" : 0, - "memoryPercent" : 0, - "name" : "glance" - }, - "httpd_restart" : false, - "success" : true -} -``` + { + "data" : { + "cpu" : 0, + "memory" : 0, + "memoryPercent" : 0, + "name" : "glance" + }, + "httpd_restart" : false, + "success" : true + } + ```
@@ -1126,7 +1037,7 @@ A dictionary containing the result of the stop operation. ### `export_container_settings` -Export container profile +Export container profile. file \.syno.json will be created in the specified path. #### Internal API
@@ -1136,12 +1047,12 @@ file \.syno.json will be created in the specified path. #### Parameters
**_container_** `str` -The name of the container +The name of the container. **_path_** `str` The path on filesystem of Synology NAS where the container settings will be exported. If not specified, the file will be offered as a download through the browser. -For example: `/docker/nging` +For example: `/docker/nging`.
@@ -1155,12 +1066,12 @@ A dictionary containing the result of the export operation.
Click to expand ```json - { - "data" : {}, - "httpd_restart" : false, - "success" : true - } -``` + { + "data" : {}, + "httpd_restart" : false, + "success" : true + } + ```
@@ -1179,11 +1090,11 @@ archive \.syno.txz will be created in the specified path. #### Parameters
**_container_** `str` -The name of the container +The name of the container. **_path_** `str` The path on filesystem of Synology NAS where the container settings will be exported. -For example: `/docker/nging` +For example: `/docker/nging`.
@@ -1197,12 +1108,12 @@ A dictionary containing the result of the export operation.
Click to expand ```json - { - "data" : {}, - "httpd_restart" : false, - "success" : true - } -``` + { + "data" : {}, + "httpd_restart" : false, + "success" : true + } + ```
@@ -1221,7 +1132,7 @@ Get list of container logs. #### Parameters
**_name_** `str` -The name of the container +The name of the container. **_from_date_** `str` The start date for the logs. Defaults to None. @@ -1256,23 +1167,23 @@ A dictionary containing the logs from the specified container.
Click to expand ```json - { - "data": { - "limit": 1, - "logs": [ - { - "created": "2025-06-15T10:38:55.869358659Z", - "docid": "1", - "stream": "stderr", - "text": "2025/06/15 10:38:55 Starting server on :8080" - } - ], - "offset": 0, - "total": 1 - }, - "success": true - } -``` + { + "data": { + "limit": 1, + "logs": [ + { + "created": "2025-06-15T10:38:55.869358659Z", + "docid": "1", + "stream": "stderr", + "text": "2025/06/15 10:38:55 Starting server on :8080" + } + ], + "offset": 0, + "total": 1 + }, + "success": true + } + ```
@@ -1298,111 +1209,111 @@ A dictionary containing the resource usage statistics of the containers.
Click to expand ```json - { - "data" : { - "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4" : { - "blkio_stats" : { - "io_merged_recursive" : [], - "io_queue_recursive" : [], - "io_service_bytes_recursive" : [], - "io_service_time_recursive" : [], - "io_serviced_recursive" : [], - "io_time_recursive" : [], - "io_wait_time_recursive" : [], - "sectors_recursive" : [] - }, - "cpu_stats" : { - "cpu_usage" : { - "percpu_usage" : [ 286394951, 245078386, 304613157, 186566695 ], - "total_usage" : 1022653189, - "usage_in_kernelmode" : 380000000, - "usage_in_usermode" : 580000000 - }, - "online_cpus" : 4, - "system_cpu_usage" : 990015100000000, - "throttling_data" : { - "periods" : 0, - "throttled_periods" : 0, - "throttled_time" : 0 - } - }, - "id" : "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4", - "memory_stats" : { - "limit" : 4079349760, - "max_usage" : 22630400, - "stats" : { - "active_anon" : 5500928, - "active_file" : 1294336, - "cache" : 15626240, - "dirty" : 0, - "hierarchical_memory_limit" : 9223372036854771712, - "hierarchical_memsw_limit" : 9223372036854771712, - "inactive_anon" : 0, - "inactive_file" : 14331904, - "mapped_file" : 11005952, - "pgfault" : 43383, - "pgmajfault" : 6, - "pgpgin" : 33405, - "pgpgout" : 28247, - "rss" : 5500928, - "rss_huge" : 0, - "total_active_anon" : 5500928, - "total_active_file" : 1294336, - "total_cache" : 15626240, - "total_dirty" : 0, - "total_inactive_anon" : 0, - "total_inactive_file" : 14331904, - "total_mapped_file" : 11005952, - "total_pgfault" : 43383, - "total_pgmajfault" : 6, - "total_pgpgin" : 33405, - "total_pgpgout" : 28247, - "total_rss" : 5500928, - "total_rss_huge" : 0, - "total_unevictable" : 0, - "total_writeback" : 0, - "unevictable" : 0, - "writeback" : 0 - }, - "usage" : 21127168 - }, - "name" : "/glance", - "networks" : { - "eth0" : { - "rx_bytes" : 876, - "rx_dropped" : 0, - "rx_errors" : 0, - "rx_packets" : 10, - "tx_bytes" : 0, - "tx_dropped" : 0, - "tx_errors" : 0, - "tx_packets" : 0 - } - }, - "num_procs" : 0, - "pids_stats" : {}, - "precpu_stats" : { - "cpu_usage" : { - "total_usage" : 0, - "usage_in_kernelmode" : 0, - "usage_in_usermode" : 0 - }, - "throttling_data" : { - "periods" : 0, - "throttled_periods" : 0, - "throttled_time" : 0 - } - }, - "preread" : "0001-01-01T00:00:00Z", - "read" : "2025-06-15T14:11:00.431111646Z", - "storage_stats" : {} - } - }, - "httpd_restart" : false, - "success" : true - } + { + "data" : { + "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4" : { + "blkio_stats" : { + "io_merged_recursive" : [], + "io_queue_recursive" : [], + "io_service_bytes_recursive" : [], + "io_service_time_recursive" : [], + "io_serviced_recursive" : [], + "io_time_recursive" : [], + "io_wait_time_recursive" : [], + "sectors_recursive" : [] + }, + "cpu_stats" : { + "cpu_usage" : { + "percpu_usage" : [ 286394951, 245078386, 304613157, 186566695 ], + "total_usage" : 1022653189, + "usage_in_kernelmode" : 380000000, + "usage_in_usermode" : 580000000 + }, + "online_cpus" : 4, + "system_cpu_usage" : 990015100000000, + "throttling_data" : { + "periods" : 0, + "throttled_periods" : 0, + "throttled_time" : 0 + } + }, + "id" : "ee220111cff2d2e7b9d764a4b781f9e23faa3cd7f3048d315aa6c95d48f0a1e4", + "memory_stats" : { + "limit" : 4079349760, + "max_usage" : 22630400, + "stats" : { + "active_anon" : 5500928, + "active_file" : 1294336, + "cache" : 15626240, + "dirty" : 0, + "hierarchical_memory_limit" : 9223372036854771712, + "hierarchical_memsw_limit" : 9223372036854771712, + "inactive_anon" : 0, + "inactive_file" : 14331904, + "mapped_file" : 11005952, + "pgfault" : 43383, + "pgmajfault" : 6, + "pgpgin" : 33405, + "pgpgout" : 28247, + "rss" : 5500928, + "rss_huge" : 0, + "total_active_anon" : 5500928, + "total_active_file" : 1294336, + "total_cache" : 15626240, + "total_dirty" : 0, + "total_inactive_anon" : 0, + "total_inactive_file" : 14331904, + "total_mapped_file" : 11005952, + "total_pgfault" : 43383, + "total_pgmajfault" : 6, + "total_pgpgin" : 33405, + "total_pgpgout" : 28247, + "total_rss" : 5500928, + "total_rss_huge" : 0, + "total_unevictable" : 0, + "total_writeback" : 0, + "unevictable" : 0, + "writeback" : 0 + }, + "usage" : 21127168 + }, + "name" : "/glance", + "networks" : { + "eth0" : { + "rx_bytes" : 876, + "rx_dropped" : 0, + "rx_errors" : 0, + "rx_packets" : 10, + "tx_bytes" : 0, + "tx_dropped" : 0, + "tx_errors" : 0, + "tx_packets" : 0 + } + }, + "num_procs" : 0, + "pids_stats" : {}, + "precpu_stats" : { + "cpu_usage" : { + "total_usage" : 0, + "usage_in_kernelmode" : 0, + "usage_in_usermode" : 0 + }, + "throttling_data" : { + "periods" : 0, + "throttled_periods" : 0, + "throttled_time" : 0 + } + }, + "preread" : "0001-01-01T00:00:00Z", + "read" : "2025-06-15T14:11:00.431111646Z", + "storage_stats" : {} + } + }, + "httpd_restart" : false, + "success" : true + } -``` + ```
diff --git a/documentation/docs/apis/classes/downloadstation.md b/documentation/docs/apis/classes/downloadstation.md index 48fbb3c2..9a45a9d7 100644 --- a/documentation/docs/apis/classes/downloadstation.md +++ b/documentation/docs/apis/classes/downloadstation.md @@ -14,9 +14,100 @@ This API is not documented yet. ::: ## Overview - +Core Download Station API implementation for Synology NAS. + +This class provides methods to manage downloads, tasks, RSS feeds, and BT searches. + +Parameters +---------- +ip_address : str + IP address or hostname of the Synology NAS. +port : str + Port number to connect to. +username : str + Username for authentication. +password : str + Password for authentication. +secure : bool, optional + Use HTTPS if True, HTTP if False (default is False). +cert_verify : bool, optional + Verify SSL certificates (default is False). +dsm_version : int, optional + DSM version (default is 7). +debug : bool, optional + Enable debug output (default is True). +otp_code : Optional[str], optional + One-time password for 2FA (default is None). +device_id : Optional[str], optional + Device ID (default is None). +device_name : Optional[str], optional + Device name (default is None). +interactive_output : bool, optional + Enable interactive output (default is True). +download_st_version : int, optional + Download Station API version (default is None). + +Methods +------- +get_info() + Get Download Station info. +get_config() + Get Download Station config. +set_server_config(...) + Set Download Station server config. +schedule_info() + Get schedule info. +schedule_set_config(...) + Set schedule config. +tasks_list(...) + List download tasks. +tasks_info(...) + Get info for specific tasks. +tasks_source(...) + Download task source. +create_task(...) + Create a new download task. +delete_task(...) + Delete a download task. +pause_task(...) + Pause a download task. +resume_task(...) + Resume a download task. +edit_task(...) + Edit a download task. +get_statistic_info() + Get Download Station statistics. +get_rss_info_list(...) + Get RSS site info list. +refresh_rss_site(...) + Refresh RSS site. +rss_feed_list(...) + Get RSS feed list. +start_bt_search(...) + Start a BT search. +get_bt_search_results(...) + Get BT search results. +get_bt_search_category() + Get BT search categories. +clean_bt_search(...) + Clean BT search tasks. +get_bt_module() + Get BT search modules. ## Methods ### `get_info` +Get Download Station info. + +#### Internal API +
+`SYNO.DownloadStation.Info` +
+ +#### Returns +
+`dict[str, object] or str` +Download Station info. + +
@@ -24,6 +115,19 @@ This API is not documented yet. ### `get_config` +Get Download Station config. + +#### Internal API +
+`SYNO.DownloadStation.Info` +
+ +#### Returns +
+`dict[str, object] or str` +Download Station config. + +
@@ -31,6 +135,56 @@ This API is not documented yet. ### `set_server_config` +Set Download Station server configuration. + +#### Internal API +
+`SYNO.DownloadStation.Info` +
+ +#### Parameters +
+**_bt_max_download_** `Optional[int]` +Maximum BT download speed. + +**_bt_max_upload_** `Optional[int]` +Maximum BT upload speed. + +**_emule_max_download_** `Optional[int]` +Maximum eMule download speed. + +**_emule_max_upload_** `Optional[int]` +Maximum eMule upload speed. + +**_nzb_max_download_** `Optional[int]` +Maximum NZB download speed. + +**_http_max_download_** `Optional[int]` +Maximum HTTP download speed. + +**_ftp_max_download_** `Optional[int]` +Maximum FTP download speed. + +**_emule_enabled_** `Optional[bool]` +Enable eMule. + +**_unzip_service_enabled_** `Optional[bool]` +Enable unzip service. + +**_default_destination_** `Optional[str]` +Default download destination. + +**_emule_default_destination_** `Optional[str]` +Default eMule download destination. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -38,6 +192,19 @@ This API is not documented yet. ### `schedule_info` +Get Download Station schedule configuration. + +#### Internal API +
+`SYNO.DownloadStation.Schedule` +
+ +#### Returns +
+`dict[str, object] or str` +Schedule configuration. + +
@@ -45,6 +212,29 @@ This API is not documented yet. ### `schedule_set_config` +Set Download Station schedule configuration. + +#### Internal API +
+`SYNO.DownloadStation.Schedule` +
+ +#### Parameters +
+**_enabled_** `bool` +Enable schedule (default is False). + +**_emule_enabled_** `bool` +Enable eMule schedule (default is False). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -52,6 +242,32 @@ This API is not documented yet. ### `tasks_list` +List download tasks. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_additional_param_** `Optional[str or list[str]]` +Additional fields to retrieve. + +**_offset_** `int` +Offset for pagination (default is 0). + +**_limit_** `int` +Maximum number of tasks to retrieve (default is -1). + + +
+#### Returns +
+`dict[str, object] or str` +List of download tasks. + +
@@ -59,6 +275,29 @@ This API is not documented yet. ### `tasks_info` +Get information for specific download tasks. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_task_id_** `str or list[str]` +Task ID(s). + +**_additional_param_** `Optional[str or list[str]]` +Additional fields to retrieve. + + +
+#### Returns +
+`dict[str, object] or str` +Task information. + +
@@ -66,6 +305,53 @@ This API is not documented yet. ### `tasks_source` +Download task source. + +#### Internal API +
+`SYNO.DownloadStation2.Task.Source` +
+ +#### Parameters +
+**_task_id_** `str or list[str]` +Task ID(s). + + +
+#### Returns +
+`bytes` +Task source content. + +
+ + + +--- + + +### `get_task_list` +Get info from a task list containing the files to be downloaded. This is to be used after creating a task, and before starting the download. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_list_id_** `str` +List ID returned by create_task. + + +
+#### Returns +
+`dict[str, any]` +A dictionary containing a task list information. + +
@@ -73,6 +359,29 @@ This API is not documented yet. ### `create_task` +Create a new download task. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_url_** `str` +Download URL. + +**_destination_** `str` +Download destination. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -80,6 +389,29 @@ This API is not documented yet. ### `delete_task` +Delete a download task. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_task_id_** `str or list[str]` +Task ID(s). + +**_force_** `bool` +Force delete (default is False). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -87,6 +419,26 @@ This API is not documented yet. ### `pause_task` +Pause a download task. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_task_id_** `str or list[str]` +Task ID(s). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -94,6 +446,26 @@ This API is not documented yet. ### `resume_task` +Resume a download task. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_task_id_** `str or list[str]` +Task ID(s). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -101,6 +473,66 @@ This API is not documented yet. ### `edit_task` +Edit a download task. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_task_id_** `str or list[str]` +Task ID(s). + +**_destination_** `str` +New download destination (default is 'sharedfolder'). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
+ + + +--- + + +### `download_task_list` +Download files from a task list. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_list_id_** `str` +Task list ID. + +**_file_indexes_** `list[int]` +List of file indexes to download. +For example, if `get_task_list()` returns `files: [{index: 0, name: "file1.txt"}, {index: 1, name: "file2.txt"}]`, then `file_indexes = [1]` will download only file2.txt. + +**_destination_** `str` +Download destination, e.g. 'sharedfolder/subfolder' + +**_create_subfolder_** `bool` +Create subfolder. Defaults to `True` + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the task_id for the started download task. + +
@@ -108,6 +540,19 @@ This API is not documented yet. ### `get_statistic_info` +Get Download Station statistics. + +#### Internal API +
+`SYNO.DownloadStation.Statistic` +
+ +#### Returns +
+`dict[str, object] or str` +Statistics information. + +
@@ -115,6 +560,29 @@ This API is not documented yet. ### `get_rss_info_list` +Get RSS site info list. + +#### Internal API +
+`SYNO.DownloadStation.RSS.Site` +
+ +#### Parameters +
+**_offset_** `Optional[int]` +Offset for pagination. + +**_limit_** `Optional[int]` +Maximum number of RSS sites to retrieve. + + +
+#### Returns +
+`dict[str, object] or str` +RSS site info list. + +
@@ -122,6 +590,26 @@ This API is not documented yet. ### `refresh_rss_site` +Refresh an RSS site. + +#### Internal API +
+`SYNO.DownloadStation.RSS.Site` +
+ +#### Parameters +
+**_rss_id_** `Optional[str]` +RSS site ID. + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -129,6 +617,32 @@ This API is not documented yet. ### `rss_feed_list` +Get RSS feed list. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_rss_id_** `Optional[str]` +RSS site ID. + +**_offset_** `Optional[int]` +Offset for pagination. + +**_limit_** `Optional[int]` +Maximum number of RSS feeds to retrieve. + + +
+#### Returns +
+`dict[str, object] or str` +RSS feed list. + +
@@ -136,6 +650,29 @@ This API is not documented yet. ### `start_bt_search` +Start a BT search. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_keyword_** `Optional[str]` +Search keyword. + +**_module_** `str` +BT search module (default is 'all'). + + +
+#### Returns +
+`dict[str, object] or str` +BT search task information or message. + +
@@ -143,6 +680,44 @@ This API is not documented yet. ### `get_bt_search_results` +Get BT search results. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_taskid_** `Optional[str]` +BT search task ID. + +**_offset_** `Optional[int]` +Offset for pagination. + +**_limit_** `Optional[int]` +Maximum number of results to retrieve. + +**_sort_by_** `Optional[str]` +Field to sort by. + +**_sort_direction_** `Optional[str]` +Sort direction. + +**_filter_category_** `Optional[str]` +Filter by category. + +**_filter_title_** `Optional[str]` +Filter by title. + + +
+#### Returns +
+`dict[str, object] or str` +BT search results. + +
@@ -150,6 +725,19 @@ This API is not documented yet. ### `get_bt_search_category` +Get BT search categories. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Returns +
+`dict[str, object] or str` +BT search categories. + +
@@ -157,6 +745,26 @@ This API is not documented yet. ### `clean_bt_search` +Clean BT search tasks. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Parameters +
+**_taskid_** `Optional[str or list[str]]` +BT search task ID(s). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
@@ -164,6 +772,19 @@ This API is not documented yet. ### `get_bt_module` +Get BT search modules. + +#### Internal API +
+`SYNO.DownloadStation` +
+ +#### Returns +
+`dict[str, object] or str` +BT search modules. + +
diff --git a/documentation/docs/apis/classes/drive_admin_console.md b/documentation/docs/apis/classes/drive_admin_console.md index d385302d..64c94617 100644 --- a/documentation/docs/apis/classes/drive_admin_console.md +++ b/documentation/docs/apis/classes/drive_admin_console.md @@ -14,9 +14,25 @@ This API is not documented yet. ::: ## Overview +Synology Drive Admin Console API implementation. +This class provides methods to retrieve and manage Synology Drive Admin Console status, +configuration, connections, logs, shares, and settings. ## Methods ### `status_info` +Get Synology Drive status information. + +#### Internal API +
+`SYNO.SynologyDrive` +
+ +#### Returns +
+`dict[str, object] or str` +Status information. + +
@@ -24,6 +40,19 @@ This API is not documented yet. ### `config_info` +Get Synology Drive configuration information. + +#### Internal API +
+`SYNO.SynologyDrive.Config` +
+ +#### Returns +
+`dict[str, object] or str` +Configuration information. + +
@@ -31,6 +60,19 @@ This API is not documented yet. ### `connections` +Get summary of Synology Drive connections. + +#### Internal API +
+`SYNO.SynologyDrive.Connection` +
+ +#### Returns +
+`dict[str, object] or str` +Connections summary. + +
@@ -38,6 +80,19 @@ This API is not documented yet. ### `drive_check_user` +Check user status in Synology Drive. + +#### Internal API +
+`SYNO.SynologyDrive` +
+ +#### Returns +
+`dict[str, object] or str` +User check result. + +
@@ -45,6 +100,19 @@ This API is not documented yet. ### `active_connections` +Get list of active Synology Drive connections. + +#### Internal API +
+`SYNO.SynologyDrive.Connection` +
+ +#### Returns +
+`dict[str, object] or str` +List of active connections. + +
@@ -52,6 +120,19 @@ This API is not documented yet. ### `active_sync_connections` +Get list of active Synology Drive ShareSync connections. + +#### Internal API +
+`SYNO.SynologyDriveShareSync.Connection` +
+ +#### Returns +
+`dict[str, object] or str` +List of active ShareSync connections. + +
@@ -59,6 +140,19 @@ This API is not documented yet. ### `share_active_list` +Get list of active shares in Synology Drive. + +#### Internal API +
+`SYNO.SynologyDrive.Share` +
+ +#### Returns +
+`dict[str, object] or str` +List of active shares. + +
@@ -66,6 +160,47 @@ This API is not documented yet. ### `log` +Get Synology Drive logs. + +#### Internal API +
+`SYNO.SynologyDrive.Log` +
+ +#### Parameters +
+**_share_type_** `str` +Type of share to filter logs (default is 'all'). + +**_get_all_** `bool` +Whether to get all logs (default is False). + +**_limit_** `int` +Maximum number of logs to return (default is 1000). + +**_keyword_** `str` +Keyword to filter logs (default is ''). + +**_date_from_** `int` +Start date in epoch format (default is 0). + +**_date_to_** `int` +End date in epoch format (default is 0). + +**_username_** `str` +Username to filter logs (default is ''). + +**_target_** `str` +Target type to filter logs (default is 'user'). + + +
+#### Returns +
+`dict[str, object] or str` +Log information. + +
@@ -73,6 +208,19 @@ This API is not documented yet. ### `c2fs_share` +Get list of C2FS shares. + +#### Internal API +
+`SYNO.C2FS.Share` +
+ +#### Returns +
+`dict[str, object] or str` +List of C2FS shares. + +
@@ -80,6 +228,19 @@ This API is not documented yet. ### `settings` +Get Synology Drive settings. + +#### Internal API +
+`SYNO.SynologyDrive.Settings` +
+ +#### Returns +
+`dict[str, object] or str` +Settings information. + +
@@ -87,6 +248,19 @@ This API is not documented yet. ### `db_usage` +Get Synology Drive database usage. + +#### Internal API +
+`SYNO.SynologyDrive.DBUsage` +
+ +#### Returns +
+`dict[str, object] or str` +Database usage information. + +
@@ -94,6 +268,19 @@ This API is not documented yet. ### `delete_status` +Get status of deleted nodes in Synology Drive. + +#### Internal API +
+`SYNO.SynologyDrive.Node.Delete` +
+ +#### Returns +
+`dict[str, object] or str` +Delete status information. + +
@@ -101,6 +288,19 @@ This API is not documented yet. ### `file_property_transfer_status` +Get file property transfer status for User Home migration. + +#### Internal API +
+`SYNO.SynologyDrive.Migration.UserHome` +
+ +#### Returns +
+`dict[str, object] or str` +File property transfer status. + +
@@ -108,6 +308,32 @@ This API is not documented yet. ### `user_sync_profile` +Get user sync profile(s). + +#### Internal API +
+`SYNO.SynologyDrive.Profiles` +
+ +#### Parameters +
+**_user_** `str` +Username to filter profiles (default is ''). + +**_start_** `int` +Start index for pagination (default is 0). + +**_limit_** `str or int` +Maximum number of profiles to return (default is 'null'). + + +
+#### Returns +
+`dict[str, object] or str` +User sync profile information. + +
@@ -115,6 +341,26 @@ This API is not documented yet. ### `index_pause` +Pause native client index for a specified duration. + +#### Internal API +
+`SYNO.SynologyDrive.Index` +
+ +#### Parameters +
+**_time_pause_** `int` +Pause duration in seconds (default is 60). + + +
+#### Returns +
+`dict[str, object] or str` +API response. + +
diff --git a/documentation/docs/apis/classes/event_scheduler.md b/documentation/docs/apis/classes/event_scheduler.md index ea44fdf7..af7bc4d9 100644 --- a/documentation/docs/apis/classes/event_scheduler.md +++ b/documentation/docs/apis/classes/event_scheduler.md @@ -13,14 +13,15 @@ Event Scheduler API implementation. This API provides functionality solely related to Event Tasks. For scheduled tasks, check `TaskScheduler`. -### Supported methods - -- **Getters** : +Methods +------- +**Getters** : - Get task results - Get result output -- **Setters** : - - Set task settings -- **Actions** : +**Setters** : + - Set task settings + - Set power schedule +**Actions** : - Enable task - Disable task - Run task @@ -82,33 +83,41 @@ A dictionary containing the task results. ### `get_result_output` Retrieve the output for a given result. -Parameters - ---------- - task_name : str - Name of the Event task to enable/disable. - result_id : int - ID of the result to retrieve. From `get_task_results()`. - Returns - ------- - dict[str, object] - A dictionary containing the result output. - Example return - -------------- - ```json - { - "data": { - "script_in": "hello", - "script_out": "/volume3/datastore/scripts_output/asd/1726190267/script.log: line 1: hello: command not found -" - }, - "success": true - } - ``` + #### Internal API
`SYNO.Core.EventScheduler`
+#### Parameters +
+**_task_name_** `str` +Name of the Event task to enable/disable. + +**_result_id_** `int` +ID of the result to retrieve. From get_task_results(). + + +
+#### Returns +
+`dict[str, object]` +A dictionary containing the result output. + +
+#### Example return +
+Click to expand +```json +{ + "data": { + "script_in": "hello", + "script_out": "/volume3/datastore/scripts_output/asd/1726190267/script.log: line 1: hello: command not found\n" + }, + "success": true +} +``` +
@@ -128,8 +137,8 @@ Enable or disable Event task. **_task_name_** `str` Name of the Event task to enable/disable. -**_enable (bool)_** `` -Wheter to enable (`True`) or disable (`False`) the task. +**_enable_** `bool` +Whether to enable (`True`) or disable (`False`) the task.
@@ -164,7 +173,7 @@ Run a specific Event task. #### Parameters
-**_task_name_** `str ` +**_task_name_** `str` Name of the Event task to run. @@ -200,7 +209,7 @@ Delete a specific Event task. #### Parameters
-**_task_name_** `str ` +**_task_name_** `str` Name of the Event task to run. @@ -211,6 +220,15 @@ Name of the Event task to run. A dictionary containing the result of the task deletion.
+#### Example return +
+Click to expand +```json +{ + "success": true +} +``` +
@@ -227,27 +245,27 @@ Create or modify an event-based task. #### Parameters
-**_action_** `str ` -Action to perform on the task. +**_action_** `str` +Action to perform on the task. Possible values: -- `create` -> Creates a new task. +- `create` -> Create a new task. - `set` -> Modify an existing task. -**_task_name_** `str ` +**_task_name_** `str` The name of the task. **_owner_** `dict[str, str]` -Dictionary containing the owner's ID and name (e.g., `{"1026": "user1"}`). -You can get the user UID by running `synouser --get your_user` in your NAS CLI. +Dictionary containing the owner's ID and name (e.g., `{"1026": "user1"}`). +You can get the user UID by running `synouser --get your_user` in your NAS CLI. For root privileges, pass `{"0":"root"}`. -**_trigger_event_** `str ` -The event that triggers the task. +**_trigger_event_** `str` +The event that triggers the task. Possible values: - `shutdown` - `bootup` -**_script_** `str ` +**_script_** `str` The script to be executed when the task is triggered. **_depend_on_task_** `list[str]` @@ -267,7 +285,7 @@ If `True`, notifications are only sent when an error occurs. Defaults to `False` #### Returns
`dict[str, object]` -A dictionary containing the result of the task creation or modification, or a strnig in case of an error. +A dictionary containing the result of the task creation or modification, or a string in case of an error.
#### Example return @@ -285,3 +303,111 @@ A dictionary containing the result of the task creation or modification, or a st --- +### `set_power_schedule` +Set the power schedule, poweron tasks and poweroff tasks. + +#### Internal API +
+`SYNO.Core.Hardware.PowerSchedule` +
+ +#### Parameters +
+**_poweron_tasks_** `List[dict]` +List of tasks for power on. Defaults to `[]`. +Example of a task: +```python +{ + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) +} +``` + +**_poweroff_tasks_** `List[dict]` +List of tasks for power off. Defaults to `[]`. +Example of a task: +```python +{ + "enabled": True, # Enable or not the task + "hour": 13, # Hour 0-23 + "min": 59, # Minutes 0-59 + "weekdays": "0,1,2,3,4,5,6" # All days of the week (Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday) +} +``` + + +
+#### Returns +
+`dict` +List of tasks in power schedule. + +
+#### Example return +
+Click to expand +```json +{ + "data": { + "poweroff_tasks": [], + "poweron_tasks": [ + { + "enabled": true, + "hour": 0, + "min": 0, + "weekdays": "1,2,3,4,5" + } + ] + }, + "success": true +} +``` +
+ + + +--- + + +### `load_power_schedule` +Load the power schedule, poweron tasks and poweroff tasks. + +#### Internal API +
+`SYNO.Core.Hardware.PowerSchedule` +
+ +#### Returns +
+`dict` +List of tasks in power schedule. + +
+#### Example return +
+Click to expand +```json +{ + "data": { + "poweroff_tasks": [], + "poweron_tasks": [ + { + "enabled": true, + "hour": 0, + "min": 0, + "weekdays": "1,2,3,4,5" + } + ] + }, + "success": true +} +``` +
+ + + +--- + + diff --git a/documentation/docs/apis/classes/filestation.md b/documentation/docs/apis/classes/filestation.md index 96575c8e..fbe2432c 100644 --- a/documentation/docs/apis/classes/filestation.md +++ b/documentation/docs/apis/classes/filestation.md @@ -14,9 +14,52 @@ This API is not documented yet. ::: ## Overview - +FileStation API implementation. + +Provides methods to interact with Synology NAS FileStation API for file and folder operations, +search, upload, download, and background task management. + +Parameters +---------- +ip_address : str + IP address of the Synology NAS. +port : str + Port number for the connection. +username : str + Username for authentication. +password : str + Password for authentication. +secure : bool, optional + Use HTTPS if True, HTTP otherwise. Default is False. +cert_verify : bool, optional + Verify SSL certificates if True. Default is False. +dsm_version : int, optional + DSM version of the Synology NAS. Default is 7. +debug : bool, optional + Enable debug output if True. Default is True. +otp_code : str, optional + One-time password for 2-step verification. Default is None. +device_id : str, optional + Device ID for authentication. Default is None. +device_name : str, optional + Name of the device. Default is None. +interactive_output : bool, optional + If True, enables interactive output. Default is False. ## Methods ### `get_info` +Get FileStation information. + +#### Internal API +
+`SYNO.FileStation.Info` +
+ +#### Returns +
+`dict[str, object] or str` +FileStation information or error message. + +
@@ -24,6 +67,41 @@ This API is not documented yet. ### `get_list_share` +List shared folders. + +#### Internal API +
+`SYNO.FileStation.List` +
+ +#### Parameters +
+**_additional_** `str or list of str` +Additional attributes to include. + +**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_onlywritable_** `bool` +If True, only writable shares are listed. + + +
+#### Returns +
+`dict[str, object] or str` +List of shared folders or error message. + +
@@ -31,6 +109,50 @@ This API is not documented yet. ### `get_file_list` +List files in a folder. + +#### Internal API +
+`SYNO.FileStation.List` +
+ +#### Parameters +
+**_folder_path_** `str` +Path to the folder. + +**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_pattern_** `str` +Pattern to filter files. + +**_filetype_** `str` +File type filter. + +**_goto_path_** `str` +Path to go to. + +**_additional_** `str or list of str` +Additional attributes to include. + + +
+#### Returns +
+`dict[str, object]` +List of files or error message. + +
@@ -38,6 +160,29 @@ This API is not documented yet. ### `get_file_info` +Get information about a file or files. + +#### Internal API +
+`SYNO.FileStation.List` +
+ +#### Parameters +
+**_path_** `str or list of str` +Path(s) to the file(s). + +**_additional_** `str or list of str` +Additional attributes to include. + + +
+#### Returns +
+`dict[str, object] or str` +File information or error message. + +
@@ -45,6 +190,68 @@ This API is not documented yet. ### `search_start` +Start a search task. + +#### Internal API +
+`SYNO.FileStation.Search` +
+ +#### Parameters +
+**_folder_path_** `str` +Path to the folder where the search will start. + +**_recursive_** `bool` +If True, the search will be recursive. + +**_pattern_** `str` +Pattern to search for. + +**_extension_** `str` +File extension to filter by. + +**_filetype_** `str` +File type filter. + +**_size_from_** `int` +Minimum file size. + +**_size_to_** `int` +Maximum file size. + +**_mtime_from_** `str or int` +Minimum modification time (Unix timestamp or formatted string). + +**_mtime_to_** `str or int` +Maximum modification time (Unix timestamp or formatted string). + +**_crtime_from_** `str or int` +Minimum creation time (Unix timestamp or formatted string). + +**_crtime_to_** `str or int` +Maximum creation time (Unix timestamp or formatted string). + +**_atime_from_** `str or int` +Minimum access time (Unix timestamp or formatted string). + +**_atime_to_** `str or int` +Maximum access time (Unix timestamp or formatted string). + +**_owner_** `str` +Owner filter. + +**_group_** `str` +Group filter. + + +
+#### Returns +
+`dict[str, object] or str` +Search task ID or error message. + +
@@ -52,6 +259,44 @@ This API is not documented yet. ### `get_search_list` +Get the results of a search task. + +#### Internal API +
+`SYNO.FileStation.Search` +
+ +#### Parameters +
+**_task_id_** `str` +Task ID of the search task. + +**_filetype_** `str` +File type filter. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_offset_** `int` +Offset for pagination. + +**_additional_** `str or list of str` +Additional attributes to include. + + +
+#### Returns +
+`dict[str, object] or str` +Search results or error message. + +
@@ -59,6 +304,26 @@ This API is not documented yet. ### `stop_search_task` +Stop a search task. + +#### Internal API +
+`SYNO.FileStation.Search` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the search task to stop. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -66,6 +331,19 @@ This API is not documented yet. ### `stop_all_search_task` +Stop all running search tasks. + +#### Internal API +
+`SYNO.FileStation.Search` +
+ +#### Returns +
+`str` +Confirmation message. + +
@@ -73,6 +351,41 @@ This API is not documented yet. ### `get_mount_point_list` +List mount points. + +#### Internal API +
+`SYNO.FileStation.VirtualFolder` +
+ +#### Parameters +
+**_mount_type_** `str` +Type of mount point to filter by. + +**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_additional_** `str or list of str` +Additional attributes to include. + + +
+#### Returns +
+`dict[str, object] or str` +List of mount points or error message. + +
@@ -80,6 +393,38 @@ This API is not documented yet. ### `get_favorite_list` +List favorite files and folders. + +#### Internal API +
+`SYNO.FileStation.Favorite` +
+ +#### Parameters +
+**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_status_filter_** `str` +Status filter. + +**_additional_** `str or list of str` +Additional attributes to include. + + +
+#### Returns +
+`dict[str, object] or str` +List of favorites or error message. + +
@@ -87,6 +432,32 @@ This API is not documented yet. ### `add_a_favorite` +Add a file or folder to favorites. + +#### Internal API +
+`SYNO.FileStation.Favorite` +
+ +#### Parameters +
+**_path_** `str` +Path to the file or folder. + +**_name_** `str` +Name for the favorite. + +**_index_** `int` +Index for the favorite. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -94,6 +465,26 @@ This API is not documented yet. ### `delete_a_favorite` +Delete a favorite. + +#### Internal API +
+`SYNO.FileStation.Favorite` +
+ +#### Parameters +
+**_path_** `str` +Path to the favorite to delete. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -101,6 +492,19 @@ This API is not documented yet. ### `clear_broken_favorite` +Clear broken favorites. + +#### Internal API +
+`SYNO.FileStation.Favorite` +
+ +#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -108,6 +512,29 @@ This API is not documented yet. ### `edit_favorite_name` +Edit the name of a favorite. + +#### Internal API +
+`SYNO.FileStation.Favorite` +
+ +#### Parameters +
+**_path_** `str` +Path to the favorite. + +**_new_name_** `str` +New name for the favorite. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -115,6 +542,29 @@ This API is not documented yet. ### `replace_all_favorite` +Replace all favorites with new paths and names. + +#### Internal API +
+`SYNO.FileStation.Favorite` +
+ +#### Parameters +
+**_path_** `str or list of str` +New path or list of new paths for the favorites. + +**_name_** `str or list of str` +New name or list of new names for the favorites. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -122,6 +572,26 @@ This API is not documented yet. ### `start_dir_size_calc` +Start a directory size calculation task. + +#### Internal API +
+`SYNO.FileStation.DirSize` +
+ +#### Parameters +
+**_path_** `str` +Path to the directory. + + +
+#### Returns +
+`dict[str, object] or str` +Task ID or error message. + +
@@ -129,6 +599,26 @@ This API is not documented yet. ### `stop_dir_size_calc` +Stop a directory size calculation task. + +#### Internal API +
+`SYNO.FileStation.DirSize` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the size calculation task to stop. + + +
+#### Returns +
+`str` +Confirmation message. + +
@@ -136,6 +626,26 @@ This API is not documented yet. ### `get_dir_status` +Get the status of a directory size calculation task. + +#### Internal API +
+`SYNO.FileStation.DirSize` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the size calculation task. + + +
+#### Returns +
+`dict[str, object] or str` +Task status or error message. + +
@@ -143,6 +653,26 @@ This API is not documented yet. ### `start_md5_calc` +Start an MD5 calculation task. + +#### Internal API +
+`SYNO.FileStation.MD5` +
+ +#### Parameters +
+**_file_path_** `str` +Path to the file. + + +
+#### Returns +
+`str or dict[str, object]` +Task ID or error message. + +
@@ -150,6 +680,26 @@ This API is not documented yet. ### `get_md5_status` +Get the status of an MD5 calculation task. + +#### Internal API +
+`SYNO.FileStation.MD5` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the MD5 calculation task. + + +
+#### Returns +
+`str or dict[str, object]` +Task status or error message. + +
@@ -157,6 +707,26 @@ This API is not documented yet. ### `stop_md5_calc` +Stop an MD5 calculation task. + +#### Internal API +
+`SYNO.FileStation.DirSize` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the MD5 calculation task to stop. + + +
+#### Returns +
+`str` +Confirmation message. + +
@@ -164,6 +734,35 @@ This API is not documented yet. ### `check_permissions` +Check permissions for a file or folder. + +#### Internal API +
+`SYNO.FileStation.CheckPermission` +
+ +#### Parameters +
+**_path_** `str` +Path to the file or folder. + +**_filename_** `str` +Name of the file. + +**_overwrite_** `bool` +If True, overwriting is allowed. + +**_create_only_** `bool` +If True, only creation is allowed. + + +
+#### Returns +
+`dict[str, object] or str` +Permission check result or error message. + +
@@ -171,6 +770,41 @@ This API is not documented yet. ### `upload_file` +Upload a file to the server. + +#### Internal API +
+`SYNO.FileStation.Upload` +
+ +#### Parameters +
+**_dest_path_** `str` +Destination path on the server. + +**_file_path_** `str` +Path to the file to upload. + +**_create_parents_** `bool` +If True, parent folders will be created. + +**_overwrite_** `bool` +If True, existing files will be overwritten. + +**_verify_** `bool` +If True, SSL certificates will be verified. + +**_progress_bar_** `bool` +If True, shows a progress bar during upload. + + +
+#### Returns +
+`str or tuple[int, dict[str, object]]` +Upload result or error message. + +
@@ -178,6 +812,26 @@ This API is not documented yet. ### `get_shared_link_info` +Get information about a shared link. + +#### Internal API +
+`SYNO.FileStation.Sharing` +
+ +#### Parameters +
+**_link_id_** `str` +ID of the shared link. + + +
+#### Returns +
+`dict[str, object] or str` +Shared link information or error message. + +
@@ -185,6 +839,38 @@ This API is not documented yet. ### `get_shared_link_list` +List shared links. + +#### Internal API +
+`SYNO.FileStation.Sharing` +
+ +#### Parameters +
+**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_force_clean_** `bool` +If True, forces a clean of the shared link list. + + +
+#### Returns +
+`dict[str, object] or str` +List of shared links or error message. + +
@@ -192,6 +878,38 @@ This API is not documented yet. ### `create_sharing_link` +Create a shared link. + +#### Internal API +
+`SYNO.FileStation.Sharing` +
+ +#### Parameters +
+**_path_** `str` +Path to the file or folder to share. + +**_password_** `str` +Password for the shared link. + +**_date_expired_** `str or int` +Expiration date for the shared link (Unix timestamp or formatted string). + +**_date_available_** `str or int` +Availability date for the shared link (Unix timestamp or formatted string). + +**_expire_times_** `int` +Number of times the link can be accessed before expiring. + + +
+#### Returns +
+`dict[str, object] or str` +Shared link details or error message. + +
@@ -199,6 +917,26 @@ This API is not documented yet. ### `delete_shared_link` +Delete a shared link. + +#### Internal API +
+`SYNO.FileStation.Sharing` +
+ +#### Parameters +
+**_link_id_** `str` +ID of the shared link to delete. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -206,6 +944,19 @@ This API is not documented yet. ### `clear_invalid_shared_link` +Clear invalid shared links. + +#### Internal API +
+`SYNO.FileStation.Sharing` +
+ +#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -213,13 +964,74 @@ This API is not documented yet. ### `edit_shared_link` +Edit a shared link. + +#### Internal API +
+`SYNO.FileStation.Sharing` +
+ +#### Parameters +
+**_link_id_** `str` +ID of the shared link to edit. + +**_password_** `str` +New password for the shared link. + +**_date_expired_** `str or int` +New expiration date for the shared link (Unix timestamp or formatted string). + +**_date_available_** `str or int` +New availability date for the shared link (Unix timestamp or formatted string). + +**_expire_times_** `int` +New number of times the link can be accessed before expiring. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
--- -### `create_folder` +### `create_folder` +Create a new folder. + +#### Internal API +
+`SYNO.FileStation.CreateFolder` +
+ +#### Parameters +
+**_folder_path_** `str or list of str` +Path or list of paths where the folder should be created. + +**_name_** `str or list of str` +Name or list of names for the new folder. + +**_force_parent_** `bool` +If True, parent folders will be created if they don't exist. + +**_additional_** `str or list of str` +Additional attributes to include. + + +
+#### Returns +
+`str or dict[str, object]` +Creation result or error message. + +
@@ -227,6 +1039,35 @@ This API is not documented yet. ### `rename_folder` +Rename a folder. + +#### Internal API +
+`SYNO.FileStation.Rename` +
+ +#### Parameters +
+**_path_** `str or list of str` +Current path or list of paths of the folder(s) to rename. + +**_name_** `str or list of str` +New name or list of new names for the folder(s). + +**_additional_** `str or list of str` +Additional attributes to include. + +**_search_taskid_** `str` +Task ID of a search task. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -234,6 +1075,41 @@ This API is not documented yet. ### `start_copy_move` +Start a copy or move task. + +#### Internal API +
+`SYNO.FileStation.CopyMove` +
+ +#### Parameters +
+**_path_** `str or list of str` +Source path or list of source paths to copy or move. + +**_dest_folder_path_** `str or list of str` +Destination folder path or list of destination folder paths. + +**_overwrite_** `bool` +If True, existing files will be overwritten. + +**_remove_src_** `bool` +If True, source files will be removed after copying. + +**_accurate_progress_** `bool` +If True, shows accurate progress. + +**_search_taskid_** `str` +Task ID of a search task. + + +
+#### Returns +
+`str or dict[str, object]` +Task ID or error message. + +
@@ -241,6 +1117,26 @@ This API is not documented yet. ### `get_copy_move_status` +Get the status of a copy or move task. + +#### Internal API +
+`SYNO.FileStation.CopyMove` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the copy or move task. + + +
+#### Returns +
+`dict[str, object] or str` +Task status or error message. + +
@@ -248,6 +1144,26 @@ This API is not documented yet. ### `stop_copy_move_task` +Stop a copy or move task. + +#### Internal API +
+`SYNO.FileStation.CopyMove` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the copy or move task to stop. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -255,6 +1171,35 @@ This API is not documented yet. ### `start_delete_task` +Start a delete task. + +#### Internal API +
+`SYNO.FileStation.Delete` +
+ +#### Parameters +
+**_path_** `str or list of str` +Path or list of paths to the file or folder to delete. + +**_accurate_progress_** `bool` +If True, shows accurate progress. + +**_recursive_** `bool` +If True, deletes folders recursively. + +**_search_taskid_** `str` +Task ID of a search task. + + +
+#### Returns +
+`dict[str, object] or str` +Task ID or error message. + +
@@ -262,6 +1207,26 @@ This API is not documented yet. ### `get_delete_status` +Get the status of a delete task. + +#### Internal API +
+`SYNO.FileStation.Delete` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the delete task. + + +
+#### Returns +
+`dict[str, object] or str` +Task status or error message. + +
@@ -269,6 +1234,26 @@ This API is not documented yet. ### `stop_delete_task` +Stop a delete task. + +#### Internal API +
+`SYNO.FileStation.Delete` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the delete task to stop. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -276,6 +1261,32 @@ This API is not documented yet. ### `delete_blocking_function` +Delete a file or folder (blocking function). +This function will stop your script until done! Do not interrupt. +#### Internal API +
+`SYNO.FileStation.Delete` +
+ +#### Parameters +
+**_path_** `str or list of str` +Path or list of paths to the file or folder to delete. + +**_recursive_** `bool` +If True, deletes folders recursively. + +**_search_taskid_** `str` +Task ID of a search task. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -283,6 +1294,47 @@ This API is not documented yet. ### `start_extract_task` +Start an extract task. + +#### Internal API +
+`SYNO.FileStation.Extract` +
+ +#### Parameters +
+**_file_path_** `str` +Path to the archive file. + +**_dest_folder_path_** `str` +Destination folder path where the files will be extracted. + +**_overwrite_** `bool` +If True, existing files will be overwritten. + +**_keep_dir_** `bool` +If True, the original directory structure will be kept. + +**_create_subfolder_** `bool` +If True, a subfolder will be created for the extracted files. + +**_codepage_** `str` +Codepage for the extraction. + +**_password_** `str` +Password for the archive, if required. + +**_item_id_** `str` +Item ID for the extraction task. + + +
+#### Returns +
+`dict[str, object] or str` +Task ID or error message. + +
@@ -290,6 +1342,26 @@ This API is not documented yet. ### `get_extract_status` +Get the status of an extract task. + +#### Internal API +
+`SYNO.FileStation.Extract` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the extract task. + + +
+#### Returns +
+`dict[str, object] or str` +Task status or error message. + +
@@ -297,6 +1369,26 @@ This API is not documented yet. ### `stop_extract_task` +Stop an extract task. + +#### Internal API +
+`SYNO.FileStation.Extract` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the extract task to stop. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -304,6 +1396,47 @@ This API is not documented yet. ### `get_file_list_of_archive` +Get the list of files in an archive. + +#### Internal API +
+`SYNO.FileStation.Extract` +
+ +#### Parameters +
+**_file_path_** `str` +Path to the archive file. + +**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_codepage_** `str` +Codepage for the file list. + +**_password_** `str` +Password for the archive, if required. + +**_item_id_** `str` +Item ID for the archive. + + +
+#### Returns +
+`dict[str, object] or str` +List of files in the archive or error message. + +
@@ -311,6 +1444,41 @@ This API is not documented yet. ### `start_file_compression` +Start a file compression task. + +#### Internal API +
+`SYNO.FileStation.Compress` +
+ +#### Parameters +
+**_path_** `str or list of str` +Path or list of paths to the file or folder to compress. + +**_dest_file_path_** `str` +Destination file path for the compressed file. + +**_level_** `int` +Compression level. + +**_mode_** `str` +Compression mode. + +**_compress_format_** `str` +Compression format. + +**_password_** `str` +Password for the compressed file, if required. + + +
+#### Returns +
+`dict[str, object] or str` +Task ID or error message. + +
@@ -318,6 +1486,26 @@ This API is not documented yet. ### `get_compress_status` +Get the status of a file compression task. + +#### Internal API +
+`SYNO.FileStation.Compress` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the compression task. + + +
+#### Returns +
+`dict[str, object] or str` +Task status or error message. + +
@@ -325,6 +1513,26 @@ This API is not documented yet. ### `stop_compress_task` +Stop a file compression task. + +#### Internal API +
+`SYNO.FileStation.Compress` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID of the compression task to stop. + + +
+#### Returns +
+`dict[str, object] or str` +Response from the API or error message. + +
@@ -332,6 +1540,38 @@ This API is not documented yet. ### `get_list_of_all_background_task` +Get a list of all background tasks. + +#### Internal API +
+`SYNO.FileStation.BackgroundTask` +
+ +#### Parameters +
+**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Limit for pagination. + +**_sort_by_** `str` +Field to sort by. + +**_sort_direction_** `str` +Sort direction ('asc' or 'desc'). + +**_api_filter_** `str` +API filter. + + +
+#### Returns +
+`dict[str, object] or str` +List of background tasks or error message. + +
@@ -339,6 +1579,38 @@ This API is not documented yet. ### `get_file` +Download a file from the server. + +#### Internal API +
+`SYNO.FileStation.Download` +
+ +#### Parameters +
+**_path_** `str` +Path to the file on the server. + +**_mode_** `str` +Mode for downloading the file ('open' to open in browser, 'download' to download to disk). + +**_dest_path_** `str` +Destination path on the local machine (for 'download' mode). + +**_chunk_size_** `int` +Chunk size for downloading. + +**_verify_** `bool` +If True, SSL certificates will be verified. + + +
+#### Returns +
+`Optional[str]` +None if successful, error message otherwise. + +
@@ -346,16 +1618,26 @@ This API is not documented yet. ### `generate_file_tree` -Generate the file tree based on the folder path you give, you need to create the root node before call this function - +Recursively generate the file tree based on the folder path you give constrained with. +You need to create the root node before calling this function. +#### Internal API +
+`hotfix` +
#### Parameters
**_folder_path_** `str` -Folder path to generate file tree +Folder path to generate file tree. **_tree_** `Tree` -Instance of the Tree of lib "Treelib" +Instance of the Tree from the `treelib` library. + +**_max_depth_** `int` +Non-negative number of maximum depth of tree generation if node tree is directory, default to '1' to generate full tree. If 'max_depth=0' it will be equivalent to no recursion. + +**_start_depth_** `int` +Non negative number to start to control tree generation default to '0'.
diff --git a/documentation/docs/apis/classes/log_center.md b/documentation/docs/apis/classes/log_center.md index f63ca313..0c92930b 100644 --- a/documentation/docs/apis/classes/log_center.md +++ b/documentation/docs/apis/classes/log_center.md @@ -14,9 +14,25 @@ This API is not documented yet. ::: ## Overview +Interface for Synology Log Center API. +Provides methods to interact with log center features such as retrieving logs, +client status, remote archives, and storage settings. ## Methods ### `logcenter` +Retrieve the list of log center receive rules. + +#### Internal API +
+`SYNO.LogCenter.RecvRule` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the receive rules or an error message. + +
@@ -24,6 +40,19 @@ This API is not documented yet. ### `client_status_cnt` +Retrieve the count status from the syslog client. + +#### Internal API +
+`SYNO.Core.SyslogClient.Status` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the count status or an error message. + +
@@ -31,6 +60,19 @@ This API is not documented yet. ### `client_status_eps` +Retrieve the EPS (events per second) status from the syslog client. + +#### Internal API +
+`SYNO.Core.SyslogClient.Status` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the EPS status or an error message. + +
@@ -38,6 +80,19 @@ This API is not documented yet. ### `remote_log_archives` +Retrieve the list of remote log archive subfolders. + +#### Internal API +
+`SYNO.LogCenter.Log` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing remote archive subfolders or an error message. + +
@@ -45,6 +100,19 @@ This API is not documented yet. ### `display_logs` +Retrieve the list of logs from the syslog client. + +#### Internal API +
+`SYNO.Core.SyslogClient.Log` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the logs or an error message. + +
@@ -52,6 +120,19 @@ This API is not documented yet. ### `setting_storage_list` +Retrieve the log center storage settings. + +#### Internal API +
+`SYNO.LogCenter.Setting.Storage` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing storage settings or an error message. + +
@@ -59,6 +140,19 @@ This API is not documented yet. ### `registry_send_list` +Retrieve the list of log center client registry send settings. + +#### Internal API +
+`SYNO.LogCenter.Client` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing registry send settings or an error message. + +
@@ -66,6 +160,19 @@ This API is not documented yet. ### `history` +Retrieve the log center history. + +#### Internal API +
+`SYNO.LogCenter.History` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the log center history or an error message. + +
diff --git a/documentation/docs/apis/classes/notestation.md b/documentation/docs/apis/classes/notestation.md index 43064e8d..6231bf7b 100644 --- a/documentation/docs/apis/classes/notestation.md +++ b/documentation/docs/apis/classes/notestation.md @@ -14,9 +14,25 @@ This API is not documented yet. ::: ## Overview +Interface for Synology NoteStation API. +Provides methods to interact with NoteStation features such as retrieving settings, +notebooks, tags, shortcuts, todos, smart notes, and individual notes. ## Methods ### `settings_info` +Retrieve NoteStation settings information. + +#### Internal API +
+`SYNO.NoteStation.Setting` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing settings information or an error message. + +
@@ -24,6 +40,19 @@ This API is not documented yet. ### `info` +Retrieve NoteStation general information. + +#### Internal API +
+`SYNO.NoteStation.Info` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing general information or an error message. + +
@@ -31,6 +60,19 @@ This API is not documented yet. ### `notebooks_info` +Retrieve the list of notebooks. + +#### Internal API +
+`SYNO.NoteStation.Notebook` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the list of notebooks or an error message. + +
@@ -38,6 +80,19 @@ This API is not documented yet. ### `tags_info` +Retrieve the list of tags. + +#### Internal API +
+`SYNO.NoteStation.Tag` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the list of tags or an error message. + +
@@ -45,6 +100,19 @@ This API is not documented yet. ### `shortcuts` +Retrieve the list of shortcuts. + +#### Internal API +
+`SYNO.NoteStation.Shortcut` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the list of shortcuts or an error message. + +
@@ -52,6 +120,19 @@ This API is not documented yet. ### `todo` +Retrieve the list of todo items. + +#### Internal API +
+`SYNO.NoteStation.Todo` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the list of todo items or an error message. + +
@@ -59,6 +140,19 @@ This API is not documented yet. ### `smart` +Retrieve the list of smart notes. + +#### Internal API +
+`SYNO.NoteStation.Smart` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the list of smart notes or an error message. + +
@@ -66,6 +160,19 @@ This API is not documented yet. ### `note_list` +Retrieve the list of notes. + +#### Internal API +
+`SYNO.NoteStation.Note` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the list of notes or an error message. + +
@@ -73,6 +180,26 @@ This API is not documented yet. ### `specific_note_id` +Retrieve a specific note by its ID. + +#### Internal API +
+`SYNO.NoteStation.Note` +
+ +#### Parameters +
+**_note_id_** `str or int` +The ID of the note to retrieve. + + +
+#### Returns +
+`dict[str, object] or str` +The API response containing the note data or an error message. + +
diff --git a/documentation/docs/apis/classes/oauth.md b/documentation/docs/apis/classes/oauth.md index dc3fc567..76b62aa5 100644 --- a/documentation/docs/apis/classes/oauth.md +++ b/documentation/docs/apis/classes/oauth.md @@ -14,9 +14,34 @@ This API is not documented yet. ::: ## Overview +Interface for Synology OAuth API. +Provides methods to interact with OAuth clients, tokens, and logs. ## Methods ### `clients` +Retrieve the list of OAuth clients. + +#### Internal API +
+`SYNO.OAUTH.Client` +
+ +#### Parameters +
+**_offset_** `int` +The starting index of the client list. Default is 0. + +**_limit_** `int` +The maximum number of clients to retrieve. Default is 20. + + +
+#### Returns +
+`dict[str, object] or str` +The API response containing the list of clients or an error message. + +
@@ -24,6 +49,29 @@ This API is not documented yet. ### `tokens` +Retrieve the list of OAuth tokens. + +#### Internal API +
+`SYNO.OAUTH.Token` +
+ +#### Parameters +
+**_offset_** `int` +The starting index of the token list. Default is 0. + +**_limit_** `int` +The maximum number of tokens to retrieve. Default is 20. + + +
+#### Returns +
+`dict[str, object] or str` +The API response containing the list of tokens or an error message. + +
@@ -31,6 +79,29 @@ This API is not documented yet. ### `logs` +Retrieve the list of OAuth logs. + +#### Internal API +
+`SYNO.OAUTH.Log` +
+ +#### Parameters +
+**_offset_** `int` +The starting index of the log list. Default is 0. + +**_limit_** `int` +The maximum number of logs to retrieve. Default is 20. + + +
+#### Returns +
+`dict[str, object] or str` +The API response containing the list of logs or an error message. + +
diff --git a/documentation/docs/apis/classes/photos.md b/documentation/docs/apis/classes/photos.md index 9e39cf9b..219c1c0e 100644 --- a/documentation/docs/apis/classes/photos.md +++ b/documentation/docs/apis/classes/photos.md @@ -14,9 +14,50 @@ This API is partially documented or under construction. ::: ## Overview - +Interface for Synology Photos API. + +Provides methods to interact with Photos features such as retrieving user info, +folders, albums, sharing, and items. + +Parameters +---------- +ip_address : str + The IP address or hostname of the Synology NAS. +port : str + The port number to connect to. +username : str + The username for authentication. +password : str + The password for authentication. +secure : bool, optional + Whether to use HTTPS. Default is False. +cert_verify : bool, optional + Whether to verify SSL certificates. Default is False. +dsm_version : int, optional + DSM version. Default is 7. +debug : bool, optional + Enable debug output. Default is True. +otp_code : str, optional + One-time password for 2FA, if required. +device_id : str, optional + Device ID for the session. +device_name : str, optional + Device name for the session. ## Methods ### `get_userinfo` +Retrieve user information for the current session. + +#### Internal API +
+`SYNO.Foto.UserInfo` +
+ +#### Returns +
+`Any` +The user information data. + +
@@ -24,6 +65,26 @@ This API is partially documented or under construction. ### `get_folder` +Retrieve information about a specific folder. + +#### Internal API +
+`SYNO.Foto.Browse.Folder` +
+ +#### Parameters +
+**_folder_id_** `int` +The ID of the folder. Default is 0. + + +
+#### Returns +
+`dict[str, object] or str` +The folder information or an error message. + +
@@ -31,6 +92,35 @@ This API is partially documented or under construction. ### `list_folders` +List folders in Personal Space. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_folder_id_** `int` +The parent folder ID. Default is 0. + +**_limit_** `int` +Maximum number of folders to return. Default is 1000. + +**_offset_** `int` +Number of folders to skip. Default is 0. + +**_additional_** `str or list of str` +Additional fields to include. + + +
+#### Returns +
+`dict[str, object] or str` +The list of folders or an error message. + +
@@ -38,6 +128,35 @@ This API is partially documented or under construction. ### `list_teams_folders` +List folders in Team Space. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_folder_id_** `int` +The parent folder ID. Default is 0. + +**_limit_** `int` +Maximum number of folders to return. Default is 2000. + +**_offset_** `int` +Number of folders to skip. Default is 0. + +**_additional_** `str or list of str` +Additional fields to include. + + +
+#### Returns +
+`dict[str, object] or str` +The list of team folders or an error message. + +
@@ -45,6 +164,26 @@ This API is partially documented or under construction. ### `count_folders` +Count folders in Personal Space. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_folder_id_** `int` +The parent folder ID. Default is 0. + + +
+#### Returns +
+`dict[str, object] or str` +The count of folders or an error message. + +
@@ -52,6 +191,26 @@ This API is partially documented or under construction. ### `count_team_folders` +Count folders in Team Space. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_folder_id_** `int` +The parent folder ID. Default is 0. + + +
+#### Returns +
+`dict[str, object] or str` +The count of team folders or an error message. + +
@@ -59,6 +218,26 @@ This API is partially documented or under construction. ### `lookup_folder` +Lookup a folder by path in Personal Space. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_path_** `str` +The folder path. + + +
+#### Returns +
+`dict[str, object] or str` +The folder information or None if not found. + +
@@ -66,6 +245,26 @@ This API is partially documented or under construction. ### `lookup_team_folder` +Lookup a folder by path in Team Space. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_path_** `str` +The folder path. + + +
+#### Returns +
+`dict[str, object] or str` +The folder information or None if not found. + +
@@ -73,6 +272,29 @@ This API is partially documented or under construction. ### `get_album` +Retrieve information about a specific album. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_album_id_** `str` +The album ID. + +**_additional_** `str or list of str` +Additional fields to include. + + +
+#### Returns +
+`dict[str, object] or str` +The album information or an error message. + +
@@ -80,6 +302,29 @@ This API is partially documented or under construction. ### `list_albums` +List albums. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_offset_** `int` +Number of albums to skip. Default is 0. + +**_limit_** `int` +Maximum number of albums to return. Default is 100. + + +
+#### Returns +
+`dict[str, object] or str` +The list of albums or an error message. + +
@@ -87,6 +332,32 @@ This API is partially documented or under construction. ### `suggest_condition` +Suggest album conditions based on a keyword. + +#### Internal API +
+`SYNO.Foto.Browse.ConditionAlbum` +
+ +#### Parameters +
+**_keyword_** `str` +The keyword to suggest conditions for. + +**_condition_** `list of str` +List of conditions to use. Default is ['general_tag']. + +**_user_id_** `str` +User ID to use. If None, uses the current user. + + +
+#### Returns +
+`dict[str, object] or str` +The suggested conditions or an error message. + +
@@ -94,6 +365,29 @@ This API is partially documented or under construction. ### `create_album` +Create a new album with the specified condition. + +#### Internal API +
+`SYNO.Foto.Browse.ConditionAlbum` +
+ +#### Parameters +
+**_name_** `str` +The name of the album. + +**_condition_** `list of str` +The condition for the album. + + +
+#### Returns +
+`dict[str, object] or str` +The API response for album creation. + +
@@ -101,6 +395,26 @@ This API is partially documented or under construction. ### `delete_album` +Delete an album by ID. + +#### Internal API +
+`SYNO.Foto.Browse.Album` +
+ +#### Parameters +
+**_album_id_** `str` +The album ID. + + +
+#### Returns +
+`dict[str, object] or str` +The API response for album deletion. + +
@@ -108,6 +422,29 @@ This API is partially documented or under construction. ### `set_album_condition` +Set the condition for an album. + +#### Internal API +
+`SYNO.Foto.Browse.ConditionAlbum` +
+ +#### Parameters +
+**_folder_id_** `int` +The folder ID. + +**_condition_** `list of str` +The condition to set. + + +
+#### Returns +
+`dict[str, object] or str` +The API response for setting the condition. + +
@@ -115,6 +452,35 @@ This API is partially documented or under construction. ### `share_album` +Share an album with specified permissions. + +#### Internal API +
+`SYNO.Foto.Sharing.Misc` +
+ +#### Parameters +
+**_album_id_** `str` +The album ID. + +**_permission_** `str or list of str` +Permissions to set. + +**_enabled_** `bool` +Whether sharing is enabled. Default is True. + +**_expiration_** `int or str` +Expiration time for the share. Default is 0. + + +
+#### Returns +
+`Any` +The API response for sharing the album. + +
@@ -122,6 +488,35 @@ This API is partially documented or under construction. ### `share_team_folder` +Share a team folder with specified permissions. + +#### Internal API +
+`SYNO.Foto.Sharing.Misc` +
+ +#### Parameters +
+**_folder_id_** `int` +The folder ID. + +**_permission_** `str` +Permissions to set. + +**_enabled_** `bool` +Whether sharing is enabled. Default is True. + +**_expiration_** `int or str` +Expiration time for the share. Default is 0. + + +
+#### Returns +
+`Any` +The API response for sharing the team folder. + +
@@ -129,6 +524,26 @@ This API is partially documented or under construction. ### `list_shareable_users_and_groups` +List users and groups that can be shared with. + +#### Internal API +
+`SYNO.Foto.Sharing.Misc` +
+ +#### Parameters +
+**_team_space_sharable_list_** `bool` +Whether to include team space sharable list. Default is False. + + +
+#### Returns +
+`dict[str, object] or str` +The list of users and groups or an error message. + +
@@ -136,7 +551,7 @@ This API is partially documented or under construction. ### `list_item_in_folders` -List all items in all folders in Personal Space +List all items in all folders in Personal Space. #### Internal API
@@ -148,36 +563,36 @@ List all items in all folders in Personal Space **_offset_** `int` Specify how many shared folders are skipped before beginning to return listed shared folders. -**_limit_** `int ` +**_limit_** `int` Number of shared folders requested. Set to `0` to list all shared folders. **_folder_id_** `int` -ID of folder +ID of folder. **_sort_by_** `str` -Possible values: -- `filename` -- `filesize` -- `takentime` -- `item_type` +Possible values: 'filename', 'filesize', 'takentime', 'item_type'. -**_sort_direction_** `str, optional ` -Possible values: `asc` or `desc`. Defaults to: `desc` +**_sort_direction_** `str` +Possible values: 'asc' or 'desc'. Defaults to: 'desc'. -**_passphrase_** `str` -Passphrase for a shared album +**_type_** `str` +Possible values: 'photo', 'video', 'live'. -**_additional_** `list[str]` -Possible values: -`["thumbnail","resolution", "orientation", "video_convert", "video_meta", "provider_user_id", "exif", "tag", "description", "gps", "geocoding_id", "address", "person"]` +**_passphrase_** `str` +Passphrase for a shared album. -**_type_** `str ` +**_additional_** `list` +Additional fields to include. Possible values: -- `photo`: Photo -- `video`: Video -- `live`: iPhone live photos' + `["thumbnail","resolution", "orientation", "video_convert", "video_meta", "provider_user_id", "exif", "tag", "description", "gps", "geocoding_id", "address", "person"]`. +
+#### Returns +
+`dict[str, object] or str` +The list of items or an error message. +
@@ -186,6 +601,19 @@ Possible values: ### `list_search_filters` +List available search filters. + +#### Internal API +
+`SYNO.Foto.Search.Filter` +
+ +#### Returns +
+`dict[str, object] or str` +The list of search filters or an error message. + +
@@ -193,6 +621,19 @@ Possible values: ### `get_guest_settings` +Retrieve guest settings for Photos. + +#### Internal API +
+`SYNO.Foto.Setting.Guest` +
+ +#### Returns +
+`dict[str, object] or str` +The guest settings or an error message. + +
diff --git a/documentation/docs/apis/classes/security_advisor.md b/documentation/docs/apis/classes/security_advisor.md index 742fe55c..a3bae6bd 100644 --- a/documentation/docs/apis/classes/security_advisor.md +++ b/documentation/docs/apis/classes/security_advisor.md @@ -14,9 +14,25 @@ This API is not documented yet. ::: ## Overview +Interface for Synology Security Advisor API. +Provides methods to retrieve general info, scan results, checklists, +login activity, and configuration for Security Advisor. ## Methods ### `general_info` +Retrieve general information about Security Advisor location configuration. + +#### Internal API +
+`SYNO.SecurityAdvisor.Conf.Location` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing location configuration or an error message. + +
@@ -24,6 +40,19 @@ This API is not documented yet. ### `security_scan` +Retrieve the current security scan configuration. + +#### Internal API +
+`SYNO.Core.SecurityScan.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing security scan configuration or an error message. + +
@@ -31,6 +60,19 @@ This API is not documented yet. ### `checklist` +Retrieve the checklist for the Security Advisor. + +#### Internal API +
+`SYNO.SecurityAdvisor.Conf.Checklist` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing the checklist or an error message. + +
@@ -38,6 +80,29 @@ This API is not documented yet. ### `login_activity` +Retrieve login activity records. + +#### Internal API +
+`SYNO.SecurityAdvisor.LoginActivity` +
+ +#### Parameters +
+**_offset_** `int` +The starting index of the login activity list. Default is 0. + +**_limit_** `int` +The maximum number of records to retrieve. Default is 20. + + +
+#### Returns +
+`dict[str, object] or str` +The API response containing login activity records or an error message. + +
@@ -45,6 +110,19 @@ This API is not documented yet. ### `advisor_config` +Retrieve Security Advisor configuration. + +#### Internal API +
+`SYNO.SecurityAdvisor.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing advisor configuration or an error message. + +
@@ -52,6 +130,19 @@ This API is not documented yet. ### `scan_config` +Retrieve custom group enumeration for security scan configuration. + +#### Internal API +
+`SYNO.Core.SecurityScan.Conf` +
+ +#### Returns +
+`dict[str, object] or str` +The API response containing custom group enumeration or an error message. + +
diff --git a/documentation/docs/apis/classes/snapshot.md b/documentation/docs/apis/classes/snapshot.md index 9af830c4..fa3b6f97 100644 --- a/documentation/docs/apis/classes/snapshot.md +++ b/documentation/docs/apis/classes/snapshot.md @@ -14,20 +14,20 @@ Class for interacting with Snapshot Replication APIs. This class implements APIs to manage snapshots. There is no documentation for these APIs, so the implementation is based on network inspection. -### Supported methods +Methods +------- +**Getters** : + - Get all share/LUN snapshots + - Get all replications + - Get all LUNs - - **Getters** : - - Get all share/LUN snapshots - - Get all replications - - Get all LUNs +**Setters** : + - Set snapshot attributes - - **Setters** : - - Set snapshot attributes - - - **Actions** : - - Create share/LUN snapshot (WORM support only for share snaps ATM) - - Delete share/LUN snapshot - - Sync replication +**Actions** : + - Create share/LUN snapshot (WORM support only for share snaps ATM) + - Delete share/LUN snapshot + - Sync replication Examples -------- @@ -78,17 +78,14 @@ List snapshots for a share. Name of the share to list snapshots for. **_attribute_filter_** `list[str]` -List of attributes filter to apply. Defaults to `[]` (no filter). - -Each attribute filter is a string in the format of `"attr==value"` or `"attr=value"` and optionally prefixed with `!` to negate the filter. - +List of attributes filter to apply. Defaults to `[]` (no filter). +Each attribute filter is a string in the format of `"attr==value"` or `"attr=value"` and optionally prefixed with `!` to negate the filter. The following are examples of valid attribute filters: - `["!hide==true", "desc==abc"]` -> hide is not true and desc is exactly abc. - `["desc=abc"]` -> desc has abc in it. **_additional_attribute_** `list[str]` -List of snapshot attributes whose values are included in the response. Defaults to `[]` (only time is returned). - +List of snapshot attributes whose values are included in the response. Defaults to `[]` (only time is returned). Note that not all attributes are available via API. The following are confirmed to work: - `"desc"` - `"lock"` @@ -153,9 +150,8 @@ List snapshots for a LUN. UUID of the source LUN to list snapshots for. **_additional_** `list[str]` -Additional fields to retrieve. Specify `[]` to get only basic information. -Defaults to `["locked_app_keys", "is_worm_locked"]` - +Additional fields to retrieve. Specify `[]` to get only basic information. +Defaults to `["locked_app_keys", "is_worm_locked"]` Possible values: - `"locked_app_keys"` -> If snapshot is preserved by the system, the locking package key will be returned. - `"is_worm_locked"` -> Whether the snapshot is locked by WORM. @@ -235,7 +231,7 @@ Dictionary containing the LUN snapshots information. ### `list_luns` -List available LUNs +List available LUNs. #### Internal API
@@ -245,29 +241,25 @@ List available LUNs #### Parameters
**_types_** `list[str]` -Type of LUNS to retrieve. - - Defaults to `[ "BLOCK", "FILE", "THIN", "ADV", "SINK", "CINDER", "CINDER_BLUN", "CINDER_BLUN_THICK", "BLUN", "BLUN_THICK", "BLUN_SINK", "BLUN_THICK_SINK" ]`. - - Possible values: - - `"BLOCK"` - - `"FILE"` - - `"THIN"` - - `"ADV"` - - `"SINK"` - - `"CINDER"` - - `"CINDER_BLUN"` - - `"CINDER_BLUN_THICK"` - - `"BLUN"` - - `"BLUN_THICK"` - - `"BLUN_SINK"` - - `"BLUN_THICK_SINK"` +Type of LUNS to retrieve. +Defaults to `[ "BLOCK", "FILE", "THIN", "ADV", "SINK", "CINDER", "CINDER_BLUN", "CINDER_BLUN_THICK", "BLUN", "BLUN_THICK", "BLUN_SINK", "BLUN_THICK_SINK" ]`. +Possible values: +- `"BLOCK"` +- `"FILE"` +- `"THIN"` +- `"ADV"` +- `"SINK"` +- `"CINDER"` +- `"CINDER_BLUN"` +- `"CINDER_BLUN_THICK"` +- `"BLUN"` +- `"BLUN_THICK"` +- `"BLUN_SINK"` +- `"BLUN_THICK_SINK"` **_additional_info_** `list[str]` -Additional LUN information to include in the response. Specify `[]` to get only basic information. - -Defaults to `[ "is_action_locked", "is_mapped", "extent_size", "allocated_size", "status", "allow_bkpobj", "flashcache_status", "family_config", "snapshot_info" ]`. - +Additional LUN information to include in the response. Specify `[]` to get only basic information. +Defaults to `[ "is_action_locked", "is_mapped", "extent_size", "allocated_size", "status", "allow_bkpobj", "flashcache_status", "family_config", "snapshot_info" ]`. Possible values: - `"is_action_locked"` - `"is_mapped"` @@ -438,10 +430,8 @@ List replication plans. #### Parameters
**_additional_info_** `list[str]` -List of additional information to include in the response. Specify `[]` to get only basic information. - -Defaults to `["sync_policy", "sync_report", "main_site_info", "dr_site_info", "can_do", "op_info", "last_op_info", "topology", "testfailover_info", "retention_lock_report"]`. - +List of additional information to include in the response. Specify `[]` to get only basic information. +Defaults to `["sync_policy", "sync_report", "main_site_info", "dr_site_info", "can_do", "op_info", "last_op_info", "topology", "testfailover_info", "retention_lock_report"]`. Possible values: - `"sync_policy"` -> Information about the sync policy as schedule, retention, lock, etc. - `"sync_report"` -> Information about the previous runs and their results / error count. @@ -459,7 +449,7 @@ Possible values: #### Returns
`dict[str, object]` -API response if successful, error message if not +API response if successful, error message if not.
#### Example return @@ -790,7 +780,7 @@ Whether to lock the snapshot. Defaults to `False`. Whether to make the snapshot immutable. Defaults to `False`. **_immutable_days_** `int` -Number of days to make the snapshot immutable for. Defaults to `7`. +Number of days to make the snapshot immutable for. Defaults to `7`. Must be greater than `0`. Mandatory if immutable is `True`. @@ -819,12 +809,7 @@ API response if successful, error message if not. ### `delete_snapshots` Delete snapshots for a share. -:::warning - - This action removes data from the file system. Use with caution. - -::: - + #### Internal API
`SYNO.Core.Share.Snapshot` @@ -872,10 +857,10 @@ Set attributes for a snapshot. #### Parameters
**_share_name_** `str` -Name of the share to set attributes for +Name of the share to set attributes for. **_snapshot_** `str` -Name of the snapshot to set attributes for +Name of the snapshot to set attributes for. **_description_** `str` Description of the snapshot. Defaults to `None` (no change). @@ -901,7 +886,7 @@ API response if successful, error message if not. #### Example return
Click to expand -```json +```json { "success": true } @@ -937,7 +922,7 @@ Description of the snapshot. Defaults to `Snapshot taken by [Synology API]`. #### Returns
`dict[str, object]` -API response if successful +API response if successful.
#### Example return @@ -956,13 +941,8 @@ API response if successful ### `create_snapshot_lun` -Create a snapshot for a LUN. -:::note - - At the moment, it does not support creating WORM snapshots. - -::: - +Create a snapshot for a LUN. + #### Internal API
`SYNO.Core.ISCSI.LUN` @@ -971,7 +951,7 @@ Create a snapshot for a LUN. #### Parameters
**_lun_id_** `str` -ID of the LUN to create a snapshot for +ID of the LUN to create a snapshot for. **_description_** `str` Description of the snapshot. Defaults to `Snapshot taken by [Synology API]`. @@ -987,7 +967,7 @@ Whether to make the snapshot application aware. Defaults to `True`. #### Returns
`dict[str, object]` -API response if successful +API response if successful.
#### Example return @@ -1011,12 +991,7 @@ API response if successful ### `delete_snapshots_lun` Delete snapshots for a LUN. -:::warning - - This action removes data from the file system. Use with caution. - -::: - + #### Internal API
`SYNO.Core.ISCSI.LUN` @@ -1032,9 +1007,7 @@ List of UUIDs of the snapshots to delete. #### Returns
`dict[str, object]` -API response if successful. - -If deletion fails, an error code is returned alonside the snapshot uuid: +If deletion fails, an error code is returned alongside the snapshot uuid: ```json { "data": [ @@ -1044,7 +1017,8 @@ If deletion fails, an error code is returned alonside the snapshot uuid: ], "success": true } -``` +``` +API response if successful.
#### Example return diff --git a/documentation/docs/apis/classes/surveillancestation.md b/documentation/docs/apis/classes/surveillancestation.md index 53f23945..d9c70f32 100644 --- a/documentation/docs/apis/classes/surveillancestation.md +++ b/documentation/docs/apis/classes/surveillancestation.md @@ -14,9 +14,26 @@ This API is not documented yet. ::: ## Overview +API wrapper for Synology Surveillance Station. +Provides methods to interact with Surveillance Station features such as retrieving +station information and saving camera configurations. ## Methods ### `surveillance_station_info` +Retrieve information about the Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Info` +
+ +#### Returns +
+`dict[str, object] or str` +A dictionary containing Surveillance Station information, or a string +with error details if the request fails. + +
@@ -24,6 +41,104 @@ This API is not documented yet. ### `camera_save` +Save or update camera configuration. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_id_** `str` +Camera ID. + +**_name_** `str` +Camera name. + +**_dsld_** `int` +Device slot ID. + +**_newName_** `str` +New camera name. + +**_ip_** `str` +Camera IP address. + +**_port_** `int` +Camera port. + +**_vendor_** `str` +Camera vendor. + +**_model_** `str` +Camera model. + +**_userName_** `str` +Username for camera authentication. + +**_password_** `str` +Password for camera authentication. + +**_videoCodec_** `int` +Video codec type. + +**_audioCodec_** `int` +Audio codec type. + +**_tvStandard_** `int` +TV standard. + +**_channel_** `str` +Channel identifier. + +**_userDefinePath_** `str` +User-defined path. + +**_fov_** `str` +Field of view. + +**_streamXX_** `Any` +Stream configuration. + +**_recordTime_** `int` +Recording time. + +**_preRecordTime_** `int` +Pre-recording time. + +**_postRecordTime_** `int` +Post-recording time. + +**_enableRecordingKeepDays_** `bool` +Enable recording retention by days. + +**_recordingKeepDays_** `int` +Number of days to keep recordings. + +**_enableRecordingKeepSize_** `bool` +Enable recording retention by size. + +**_recordingKeepSize_** `int` +Maximum size for recordings. + +**_enableLowProfile_** `bool` +Enable low profile recording. + +**_recordSchedule_** `list of int` +Recording schedule. + +**_rtspPathTimeout_** `int` +RTSP path timeout. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
@@ -31,6 +146,53 @@ This API is not documented yet. ### `camera_list` +Retrieve a list of cameras from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of camera IDs to filter. + +**_offset_** `int` +The starting index for the camera list. + +**_limit_** `int` +The maximum number of cameras to return. + +**_blFromCamList_** `bool` +Whether to retrieve from the camera list. + +**_blIncludeDeletedCam_** `bool` +Whether to include deleted cameras. + +**_privCamType_** `str` +Filter by camera privilege type. + +**_basic_** `bool` +Whether to return only basic information. + +**_streamInfo_** `bool` +Whether to include stream information. + +**_blPrivilege_** `bool` +Whether to include privilege information. + +**_camStm_** `int` +Camera stream type. + + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing camera list information, or a string with error details. + +
@@ -38,20 +200,61 @@ This API is not documented yet. ### `get_camera_info` -This function return information about a camera. -cameraIds : This parameter is named cameraIds in the API documentation but it refer to 1 camera ID -privCamType: int = 1 - SYNO.SS.CamPriv.LIVEVIEW = 1; - SYNO.SS.CamPriv.PLAYBACK = 2; - SYNO.SS.CamPriv.LENS = 4; - SYNO.SS.CamPriv.AUDIO = 8; - SYNO.SS.CamPriv.DIGIOUT = 16; -All other parameters must be let to default value +Return information about a camera. + #### Internal API
`SYNO.SurveillanceStation.Camera`
+#### Parameters +
+**_cameraIds_** `int` +Camera ID. Although named cameraIds in the API, it refers to a single camera ID. + +**_privCamType_** `int, default=1` +Camera privilege type. Possible values: + 1: LIVEVIEW + 2: PLAYBACK + 4: LENS + 8: AUDIO + 16: DIGIOUT + +**_blIncludeDeletedCam_** `bool, default=True` +Whether to include deleted cameras. + +**_basic_** `bool, default=True` +Whether to return only basic information. + +**_streamInfo_** `bool, default=True` +Whether to include stream information. + +**_optimize_** `bool, default=True` +Whether to optimize the returned data. + +**_ptz_** `bool, default=True` +Whether to include PTZ (Pan-Tilt-Zoom) information. + +**_eventDetection_** `bool, default=True` +Whether to include event detection information. + +**_deviceOutCap_** `bool, default=True` +Whether to include device output capabilities. + +**_fisheye_** `bool, default=True` +Whether to include fisheye camera information. + +**_camAppInfo_** `bool, default=True` +Whether to include camera application information. + + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing camera information, or a string with error details. + +
@@ -59,6 +262,29 @@ All other parameters must be let to default value ### `camera_list_group` +Retrieve a list of camera groups from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_offset_** `int` +The starting index for the camera group list. + +**_limit_** `int` +The maximum number of camera groups to return. + + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing camera group information, or a string with error details. + +
@@ -66,13 +292,35 @@ All other parameters must be let to default value ### `get_snapshot` -By default, the profileType is 1, which is the default profile. -Binary data is returned, so the response is not a json object. +Retrieve a snapshot image from a camera. + #### Internal API
`SYNO.SurveillanceStation.Camera`
+#### Parameters +
+**_id_** `Any` +Camera identifier. + +**_name_** `str` +Camera name. + +**_dsld_** `int` +Device slot ID. + +**_profileType_** `int, default=1` +Profile type for the snapshot (1 is the default profile). + + +
+#### Returns +
+`str` +Binary data of the snapshot image. The response is not a JSON object. + +
@@ -80,6 +328,29 @@ Binary data is returned, so the response is not a json object. ### `enable_camera` +Enable one or more cameras by their IDs. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of camera IDs to enable. + +**_blIncludeDeletedCam_** `bool` +Whether to include deleted cameras in the operation. Default is False. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the enable operation as a dictionary, or a string with error details. + +
@@ -87,6 +358,29 @@ Binary data is returned, so the response is not a json object. ### `disable_camera` +Disable one or more cameras by their IDs. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of camera IDs to disable. + +**_blIncludeDeletedCam_** `bool` +Whether to include deleted cameras in the operation. Default is False. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the disable operation as a dictionary, or a string with error details. + +
@@ -94,6 +388,26 @@ Binary data is returned, so the response is not a json object. ### `get_capability_by_cam_id` +Retrieve the capability information for a specific camera by its ID. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera for which to retrieve capability information. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the camera's capability information, or a string with error details if the request fails. + +
@@ -101,6 +415,26 @@ Binary data is returned, so the response is not a json object. ### `count_occupied_size` +Retrieve the occupied storage size for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to retrieve the occupied size. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the occupied size information, or a string with error details if the request fails. + +
@@ -108,6 +442,26 @@ Binary data is returned, so the response is not a json object. ### `is_shortcut_valid` +Check if a camera shortcut is valid. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_cameraId_** `int` +The ID of the camera to validate the shortcut for. + + +
+#### Returns +
+`dict[str, object] or str` +A dictionary with the validation result, or a string with error details. + +
@@ -115,6 +469,26 @@ Binary data is returned, so the response is not a json object. ### `get_live_path` +Retrieve the live view path for one or more cameras. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera` +
+ +#### Parameters +
+**_idList_** `int` +Camera ID or comma-separated list of camera IDs for which to retrieve the live view path. + + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing the live view path information, or a string with error details. + +
@@ -122,2045 +496,9567 @@ Binary data is returned, so the response is not a json object. ### `audio_event_enum` +Enumerate audio events for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to enumerate audio events. + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing audio event enumeration, or a string with error details. - ---- +
-### `alarm_event_enum` +--- ---- +### `alarm_event_enum` +Enumerate alarm events for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to enumerate alarm events. + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing alarm event enumeration, or a string with error details. -### `md_parameter_save` +
--- -### `motion_event_enum` - +### `md_parameter_save` +Save motion detection parameters for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to save motion detection parameters. + +**_source_** `int` +The source channel or stream index. + +**_mode_** `int` +The motion detection mode. + +**_sensitivity_** `int` +Sensitivity level for motion detection. + +**_threshold_** `int` +Threshold value for motion detection. + +**_objectSize_** `int` +Minimum object size to trigger detection. + +**_percentage_** `int` +Minimum percentage of the detection area to trigger detection. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation as a dictionary, or a string with error details. ---- +
-### `motion_parameter_save` +--- ---- +### `motion_event_enum` +Enumerate motion events for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to enumerate motion events. + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing motion event enumeration, or a string with error details. -### `di_parameter_save` +
--- -### `alarm_sts_polling` - - - ---- +### `motion_parameter_save` +Save advanced motion detection parameters for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to save motion detection parameters. + +**_source_** `int` +The source channel or stream index. + +**_mode_** `int` +The motion detection mode. + +**_keep_** `bool` +Whether to keep the current settings. + +**_level_** `int` +Sensitivity level for advanced motion detection. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation as a dictionary, or a string with error details. -### `td_parameter_save` +
--- -### `enumerate_camera_group` - - - ---- +### `di_parameter_save` +Save digital input (DI) parameters for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to save DI parameters. + +**_idx_** `int` +The index of the DI channel. + +**_keep_** `bool` +Whether to keep the current DI settings. + +**_normal_** `int` +The normal state value for the DI channel. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation as a dictionary, or a string with error details. -### `save_specific_group` +
--- -### `delete_specific_groups` - - - ---- +### `alarm_sts_polling` +Poll the alarm status for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to poll alarm status. + +**_timeOut_** `int` +Timeout value for the polling operation. + +**_keep_** `Any` +Reserved for future use or additional options (currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing alarm status polling result, or a string with error details. -### `enumerate_group_information` +
--- -### `enumerate_camera_from_archive` - - - ---- +### `td_parameter_save` +Save tamper detection (TD) parameters for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Event` +
+ +#### Parameters +
+**_camId_** `int` +The ID of the camera for which to save tamper detection parameters. + +**_source_** `int` +The source channel or stream index. + +**_keep_** `Any` +Whether to keep the current settings (reserved for future use). + +**_duration_** `int` +Duration for the tamper detection event. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation as a dictionary, or a string with error details. -### `enumerate_archive_from_folder` +
--- -### `check_available_size_of_sdcard` - - - ---- +### `enumerate_camera_group` +Enumerate camera groups in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Group` +
+ +#### Parameters +
+**_privCamType_** `int` +Camera privilege type to filter groups. + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing camera group enumeration, or a string with error details. -### `check_licence_quota` +
--- -### `format_specific_sd_card` - +### `save_specific_group` +Save or update a specific camera group in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Group` +
+ +#### Parameters +
+**_groupList_** `Any` +The list of groups to be saved or updated. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation as a dictionary, or a string with error details. ---- +
-### `quick_create_single_camera` +--- ---- +### `delete_specific_groups` +Delete specific camera groups in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Group` +
+ +#### Parameters +
+**_Id_** `int` +The ID of the camera group to delete. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation as a dictionary, or a string with error details. -### `move_camera_lens` +
--- -### `camera_lens_zoom` - +### `enumerate_group_information` +Enumerate group information for camera import in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Import` +
+ +#### Parameters +
+**_camServerId_** `int` +The ID of the camera server. + +**_shareName_** `str` +The name of the shared folder. + +**_archiveName_** `str` +The name of the archive. + +**_camlist_** `Any` +List of cameras to include. + +**_actFromHost_** `bool` +Whether the action is performed from the host. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the group information enumeration as a dictionary, or a string with error details. ---- +
-### `list_preset_ptz_camera` +--- ---- +### `enumerate_camera_from_archive` +Enumerate cameras from a specified archive in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Import` +
+ +#### Parameters +
+**_shareName_** `str` +The name of the shared folder containing the archive. + +**_archiveName_** `str` +The name of the archive to enumerate cameras from. + +**_serverId_** `int` +The ID of the server associated with the archive. + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing camera enumeration details, or a string with error details if the request fails. -### `move_camera_lens_to_preset_position` +
--- -### `list_patrol_cameras` - +### `enumerate_archive_from_folder` +Enumerate archives from a specified folder in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Import` +
+ +#### Parameters +
+**_shareName_** `str` +The name of the shared folder containing the archives. + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing archive enumeration details, or a string with error details if the request fails. ---- +
-### `force_cam_to_execute_patrol` +--- ---- +### `check_available_size_of_sdcard` +Check the available size of the SD card for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Wizard` +
+ +#### Parameters +
+**_camId_** `Any` +The ID of the camera. + +**_host_** `str` +The host address of the camera. + +**_port_** `str` +The port number for the camera connection. + +**_user_** `str` +The username for authentication. + +**_passw_** `str` +The password for authentication. + +**_vendor_** `str` +The vendor of the camera. + +**_model_** `str` +The model of the camera. + +**_ch_** `str` +The channel identifier. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the available size information, or a string with error details. -### `focus_camera` +
--- -### `control_camera_iris_in_out` +### `check_licence_quota` +Check the license quota for Surveillance Station cameras. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Wizard` +
+ +#### Returns +
+`dict[str, object] or str` +A dictionary containing license quota information, or a string with error details if the request fails. + +
--- -### `auto_focus` - +### `format_specific_sd_card` +Format the SD card of a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Wizard` +
+ +#### Parameters +
+**_camId_** `Any` +The ID of the camera whose SD card is to be formatted. + +**_host_** `str` +The host address of the camera. + +**_port_** `str` +The port number for the camera connection. + +**_user_** `str` +The username for authentication. + +**_passw_** `str` +The password for authentication. + +**_vendor_** `str` +The vendor of the camera. + +**_model_** `str` +The model of the camera. + +**_ch_** `str` +The channel identifier. + +**_timeout_** `int` +Timeout value for the formatting operation. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +A dictionary containing the result of the format operation, or a string with error details. ---- +
-### `move_cam_lens_to_absolute_position` +--- ---- +### `quick_create_single_camera` +Quickly create a single camera in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Wizard` +
+ +#### Parameters +
+**_camServerId_** `Any` +The ID of the camera server. + +**_actFromHost_** `bool` +Whether the action is performed from the host. + +**_camStreamingType_** `str` +The streaming type of the camera. + +**_camName_** `str` +The name of the camera. + +**_camIP_** `str` +The IP address of the camera. + +**_camPort_** `str` +The port number of the camera. + +**_camVendor_** `str` +The vendor of the camera. + +**_camModel_** `str` +The model of the camera. + +**_camMountType_** `int` +The mount type of the camera. + +**_camChannel_** `str` +The channel of the camera. + +**_camVideoType_** `str` +The video type of the camera. + +**_camAudioType_** `str` +The audio type of the camera. + +**_camSourcePath_** `str` +The source path for the camera stream. + +**_camUserName_** `str` +The username for camera authentication. + +**_camPassWord_** `str` +The password for camera authentication. (To be checked). + +
+#### Returns +
+`dict[str, object] or str` +Result of the quick create operation as a dictionary, or a string with error details. -### `move_cam_to_home_position` +
--- -### `auto_pan_camera` - +### `move_camera_lens` +Move the camera lens in a specified direction with an optional speed and move type. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control. + +**_direction_** `str` +The direction to move the lens (e.g., 'up', 'down', 'left', 'right'). + +**_speed_** `int` +The speed at which to move the lens. + +**_moveType_** `str` +The type of movement (reserved for future use, currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the move operation as a dictionary, or a string with error details. ---- +
-### `start_stop_object_tracking` +--- ---- +### `camera_lens_zoom` +Control the zoom function of a camera lens. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control. + +**_control_** `Any` +The zoom control command or value. + +**_moveType_** `str` +The type of movement (reserved for future use, currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the zoom operation as a dictionary, or a string with error details. -### `start_stop_external_recording` +
--- -### `query_event_list_by_filter` - +### `list_preset_ptz_camera` +List preset positions for a PTZ (Pan-Tilt-Zoom) camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the PTZ camera to list presets for. + +**_offset_** `int` +The starting index for the preset list. + +**_limit_** `int` +The maximum number of presets to return. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing the list of PTZ presets, or a string with error details. ---- +
-### `delete_recordings` +--- ---- +### `move_camera_lens_to_preset_position` +Move the camera lens to a specified preset position. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control. + +**_presetId_** `Any` +The ID of the preset position to move to. + +**_position_** `Any` +The position value for the preset. + +**_speed_** `Any` +The speed at which to move the lens. + +**_type_** `Any` +The type of movement or preset. + +**_isPatrol_** `bool` +Whether the movement is part of a patrol operation. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the move operation as a dictionary, or a string with error details. -### `delete_events_by_filter` +
--- -### `delete_all_recordings` - +### `list_patrol_cameras` +List patrols for a PTZ (Pan-Tilt-Zoom) camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the PTZ camera to list patrols for. + +**_offset_** `int` +The starting index for the patrol list. + +**_limit_** `int` +The maximum number of patrols to return. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing the list of PTZ patrols, or a string with error details. ---- +
-### `apply_settings_advance_tab` +--- ---- +### `force_cam_to_execute_patrol` +Force a camera to execute a specified patrol. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to execute the patrol. + +**_patrolId_** `Any` +The ID of the patrol to execute. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the patrol execution as a dictionary, or a string with error details. -### `count_by_number_of_event` +
--- -### `keep_event_play_alive` - +### `focus_camera` +Control the focus function of a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control. + +**_control_** `Any` +The focus control command or value. + +**_moveType_** `Any` +The type of movement (reserved for future use, currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the focus operation as a dictionary, or a string with error details. ---- +
-### `stop_recording_event` +--- ---- +### `control_camera_iris_in_out` +Control the iris (in/out) function of a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control. + +**_control_** `Any` +The iris control command or value. + +**_moveType_** `Any` +The type of movement (reserved for future use, currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the iris control operation as a dictionary, or a string with error details. -### `load_settings_in_advanced_tab` +
--- -### `lock_selected_event` - +### `auto_focus` +Perform an auto-focus operation on a specified camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to auto-focus. + +
+#### Returns +
+`dict[str, object] or str` +Result of the auto-focus operation as a dictionary, or a string with error details. ---- +
-### `unlock_selected_event` +--- ---- +### `move_cam_lens_to_absolute_position` +Move the camera lens to an absolute position. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_posX_** `int` +The X coordinate for the absolute position. + +**_posY_** `int` +The Y coordinate for the absolute position. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the move operation as a dictionary, or a string with error details. -### `unlock_selected_filter_event` +
--- -### `lock_selected_recordings` - +### `move_cam_to_home_position` +Move the camera to its home position. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to move to the home position. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the move operation as a dictionary, or a string with error details. ---- +
-### `download_recordings` +--- ---- +### `auto_pan_camera` +Automatically pan the camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to auto-pan. + +**_moveType_** `str` +The type of movement (reserved for future use, currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the auto-pan operation as a dictionary, or a string with error details. -### `check_if_recording_playable` +
--- -### `play_specific_recording` +### `start_stop_object_tracking` +Start or stop object tracking for a specified camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ` +
+ +#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control object tracking. + +**_moveType_** `str` +The type of movement (reserved for future use, currently not working). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the object tracking operation as a dictionary, or a string with error details. + +
--- -### `download_merged_recording_files` -Download the merged files of UTC time range recordings of target camera. -If there are different resolution or codec within UTC time range, the recordings will merge as much as possible -and downlod file will be a zip file. -This method will start a task which have keep-alive mechanism. -Use GetRangeExportProgress method to get newest progress and keep-alive. -After receiving progress 100, use OnRangeExportDone method to download exported recording within 1 -minutes. -If you want to cancel range export task, just do not send GetRangeExportProgress method or -OnRangeExportDone method. System will cleanup processed files itself. +### `start_stop_external_recording` +Start or stop external recording for a specified camera. + #### Internal API
-`SYNO.SurveillanceStation.Recording` +`SYNO.SurveillanceStation.ExternalRecording`
+#### Parameters +
+**_cameraId_** `Any` +The ID of the camera to control external recording. + +**_action_** `str` +The action to perform (e.g., 'start' or 'stop'). (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the external recording operation as a dictionary, or a string with error details. - ---- - - -### `get_newest_progress_keep_alive` +
--- -### `download_recording_from_target` -Response -MP4 or zip file data. -The response type can be found in fileExt of GetRangeExportProgress method response when progress 100. -Note -GetRangeExportProgress method must be sent within 1 minute after corresponding RangeExport method task -is completed, otherwise the exported recordings will be cleared. -2.3.11.20 API Error Code -Code Description -400 Execution failed. -401 Parameter invalid. -405 CMS server connection failed. -414 Some events not exist. -439 Too many items selected. +### `query_event_list_by_filter` +Query the event list by applying various filters. + #### Internal API
`SYNO.SurveillanceStation.Recording`
+#### Parameters +
+**_offset_** `int` +The starting index for the event list. + +**_limit_** `int` +The maximum number of events to return. + +**_cameraIds_** `str` +Comma-separated list of camera IDs to filter events. + +**_fromTime_** `int` +Start time (timestamp) for filtering events. + +**_toTime_** `int` +End time (timestamp) for filtering events. + +**_dsld_** `int` +Device slot ID to filter events. + +**_mountId_** `int` +Mount ID to filter events. + + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing the filtered event list, or a string with error details. + +
--- -### `handle_load_event_export` +### `delete_recordings` +Delete specific recordings from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_idList_** `int` +The ID or comma-separated list of IDs of the recordings to delete. + +**_dsld_** `int` +Device slot ID associated with the recordings. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation as a dictionary, or a string with error details. +
---- -### `check_name_export_event` - +--- ---- +### `delete_events_by_filter` +Delete events from Surveillance Station by applying various filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_reason_** `str` +The reason for deleting the events. + +**_cameraIds_** `str` +Comma-separated list of camera IDs to filter events. + +**_fromTime_** `Any` +Start time (timestamp) for filtering events. + +**_toTime_** `Any` +End time (timestamp) for filtering events. + +**_locked_** `int` +Whether to include locked events. + +**_evtSrcType_** `int` +Event source type. + +**_evtSrcId_** `int` +Event source ID. + +**_blIncludeSnapshot_** `bool` +Whether to include snapshots in the deletion. + +**_includeAllCam_** `bool` +Whether to include all cameras. + +**_from_end_** `int` +End index for the filter range. + +**_from_start_** `int` +Start index for the filter range. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation as a dictionary, or a string with error details. -### `get_camera_information_list` +
--- -### `check_destination_folder_availability` +### `delete_all_recordings` +Delete all recordings from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the delete operation as a dictionary, or a string with error details. +
---- +--- -### `handle_save_event_export` +### `apply_settings_advance_tab` +Apply advanced settings in the Surveillance Station recording tab. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_rotateUnrecogCam_** `bool` +Whether to rotate unrecognized cameras. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the apply operation as a dictionary, or a string with error details. ---- +
-### `get_event_export_info_from_recording_server` +--- ---- +### `count_by_number_of_event` +Count the number of events by category, with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_offset_** `bool` +Whether to offset the results. + +**_limit_** `int` +The maximum number of results to return. + +**_reason_** `str` +The reason for filtering events. + +**_cameraIds_** `str` +Comma-separated list of camera IDs to filter events. + +**_fromTime_** `int` +Start time (timestamp) for filtering events. + +**_toTime_** `int` +End time (timestamp) for filtering events. + +**_locked_** `int` +Whether to include locked events. + +**_evtSrcType_** `int` +Event source type. + +**_evtSrcId_** `int` +Event source ID. + +**_blIncludeSnapshot_** `bool` +Whether to include snapshots in the count. + +**_includeAllCam_** `bool` +Whether to include all cameras. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Dictionary containing the event count by category, or a string with error details. -### `load_event_mount` +
--- -### `redirect_webapi_to_target_ds` -webAPI Array of `webAPI_info` -Example: -`webAPI={"api": "SYNO.SurveillanceStation.AddOns", "version": 1, "method": -"List"}` +### `keep_event_play_alive` +Keep the event play session alive. + #### Internal API
-`SYNO.SurveillanceStation.CMS` +`SYNO.SurveillanceStation.Recording`
+#### Returns +
+`dict[str, object] or str` +Result of the keepalive operation as a dictionary, or a string with error details. - - ---- - - -### `modify_share_privilege` +
--- -### `apply_option_settings` +### `stop_recording_event` +Stop a recording event for the specified event IDs. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_idList_** `Any` +The ID or list of IDs of the events to stop recording. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the stop operation as a dictionary, or a string with error details. +
---- -### `get_cms_info` +--- +### `load_settings_in_advanced_tab` +Load settings from the advanced tab in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Returns +
+`dict[str, object] or str` +Dictionary containing the advanced settings, or a string with error details. ---- +
-### `get_log_recording_data_from_target_ds` +--- ---- +### `lock_selected_event` +Lock selected events by applying various filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_reason_** `str` +The reason for locking the events. + +**_cameraIds_** `str` +Comma-separated list of camera IDs to filter events. + +**_fromTime_** `int` +Start time (timestamp) for filtering events. + +**_toTime_** `int` +End time (timestamp) for filtering events. + +**_locked_** `int` +Whether to lock the events. + +**_evtSrcType_** `int` +Event source type. + +**_evtSrcId_** `int` +Event source ID. + +**_blIncludeSnapshot_** `bool` +Whether to include snapshots in the lock operation. + +**_includeAllCam_** `bool` +Whether to include all cameras. + +**_from_end_** `int` +End index for the filter range. + +**_from_start_** `int` +Start index for the filter range. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation as a dictionary, or a string with error details. -### `get_samba_service` +
--- -### `check_if_samba_on_and_rec_enabled` - +### `unlock_selected_event` +Unlock selected events by their IDs. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of event IDs to unlock. + +**_dsld_** `int` +Device slot ID associated with the events. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation as a dictionary, or a string with error details. ---- +
-### `get_encoded_single_image_of_camera` +--- ---- +### `unlock_selected_filter_event` +Unlock events by applying various filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_reason_** `str` +The reason for unlocking the events. + +**_cameraIds_** `str` +Comma-separated list of camera IDs to filter events. + +**_fromTime_** `int` +Start time (timestamp) for filtering events. + +**_toTime_** `int` +End time (timestamp) for filtering events. + +**_locked_** `int` +Whether to unlock only locked events. + +**_evtSrcType_** `int` +Event source type. + +**_evtSrcId_** `int` +Event source ID. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation as a dictionary, or a string with error details. -### `get_cms_status` +
--- -### `enable_smb_service` - +### `lock_selected_recordings` +Lock selected recordings by their IDs. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of recording IDs to lock. + +**_dsld_** `int` +Device slot ID associated with the recordings. + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation as a dictionary, or a string with error details. ---- +
-### `notify_slave_ds_to_disconnect` +--- ---- +### `download_recordings` +Download recordings by specifying recording ID and optional parameters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_id_** `int` +The ID of the recording to download. + +**_mountId_** `int` +The mount ID associated with the recording. + +**_offsetTimeMs_** `int` +Offset time in milliseconds for the download. + +**_playTimeMs_** `int` +Playback time in milliseconds for the download. + +
+#### Returns +
+`dict[str, object] or str` +The downloaded recording as a binary response, or a string with error details. -### `lock_recording_server_prevent_setting_change` +
--- -### `enable_ds_into_recording_server` - +### `check_if_recording_playable` +Check if a recording is playable by event ID and optional parameters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_eventId_** `int` +The event ID of the recording to check. + +**_chkDetail_** `bool` +Whether to check detailed information. + +**_mountId_** `int` +The mount ID associated with the recording. + +**_dsld_** `int` +Device slot ID. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the check as a dictionary, or a string with error details. ---- +
-### `unpair_recording_servers` +--- ---- +### `play_specific_recording` +Stream a specific recording from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_recordingId_** `int` +The ID of the recording to play. + +**_alertRecording_** `bool` +Whether the recording is an alert recording. + +**_mountId_** `int` +The mount ID associated with the recording. + +**_dsld_** `int` +Device slot ID. + +**_videoCodec_** `int` +Video codec to use for streaming. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Streaming information or error details. -### `get_free_memory_size` +
--- -### `handle_slave_ds` - - - ---- +### `download_merged_recording_files` +Download merged files of recordings within a UTC time range for a target camera. +If there are different resolutions or codecs within the time range, recordings will be merged as much as possible, +and the download file will be a zip file. +This method starts a task with a keep-alive mechanism. +Use GetRangeExportProgress to get the latest progress and keep-alive. +After receiving progress 100, use OnRangeExportDone to download the exported recording within 1 minute. +To cancel the export task, do not send GetRangeExportProgress or OnRangeExportDone; the system will clean up processed files. +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_camId_** `int` +The camera ID to export recordings from. + +**_fromTime_** `int` +Start UTC timestamp for the export range. + +**_toTime_** `int` +End UTC timestamp for the export range. + +**_fileName_** `str` +Name of the output file. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Task information for the export or error details. -### `get_target_ds_info` +
--- -### `logout_slave_ds` - - - ---- +### `get_newest_progress_keep_alive` +Get the latest progress of a range export task and keep the task alive. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording` +
+ +#### Parameters +
+**_dlid_** `int` +The download task ID. + +
+#### Returns +
+`dict[str, object] or str` +Progress information or error details. -### `pair_slave_ds` +
--- -### `login_slave_ds` -2.3.15.9 API Error Code -Code Description -400 Execution failed. -401 Invalid parameter. -415 message connect failed. +### `download_recording_from_target` +Download the exported recording file from a completed range export task. + #### Internal API
-`SYNO.SurveillanceStation.CMS.GetDsStatus` +`SYNO.SurveillanceStation.Recording`
+#### Parameters +
+**_dlid_** `int` +The download task ID. + +**_fileName_** `str` +Name of the file to download. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Downloaded file data or error details. - ---- - - -### `save_slave_ds` +
--- -### `load_slave_ds_list` - +### `handle_load_event_export` +Load exported event recordings with optional pagination. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Export` +
+ +#### Parameters +
+**_start_** `int` +The starting index for loading events. + +**_limit_** `bool` +The maximum number of events to load. + +
+#### Returns +
+`dict[str, object] or str` +Exported event information or error details. ---- +
-### `count_number_of_logs` +--- ---- +### `check_name_export_event` +Check if an export event name is valid or already exists. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Export` +
+ +#### Parameters +
+**_dsId_** `int` +The data source ID. + +**_name_** `int` +The name to check for the export event. + +**_share_** `str` +The share name associated with the export event. + +
+#### Returns +
+`dict[str, object] or str` +Result of the name check or error details. -### `clear_selected_logs` +
--- -### `get_information_log` - +### `get_camera_information_list` +Retrieve the list of camera information for event export. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Export` +
+ +#### Parameters +
+**_dslld_** `int` +The ID of the data source (recording server) to query cameras from. + +
+#### Returns +
+`dict[str, object] or str` +Camera information list or error details. ---- +
-### `get_advanced_settings_logs` +--- ---- +### `check_destination_folder_availability` +Check if the destination folder has enough available space for export. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Export` +
+ +#### Parameters +
+**_freeSize_** `int` +Required free size in bytes. + +**_startTime_** `int` +Start time of the export range (UTC timestamp). + +**_stopTime_** `int` +End time of the export range (UTC timestamp). + +**_camIdList_** `str` +Comma-separated list of camera IDs to check. + +
+#### Returns +
+`dict[str, object] or str` +Availability information or error details. -### `set_advanced_setting_logs` +
--- -### `load_license_data` - +### `handle_save_event_export` +Save an event export task with the specified parameters. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Export` +
+ +#### Parameters +
+**_name_** `str` +Name of the export task. + +**_srcDsId_** `int` +Source data source ID. + +**_dstDsId_** `int` +Destination data source ID. + +**_dstdir_** `str` +Destination directory for export. + +**_freesize_** `int` +Required free size in bytes. + +**_start_time_** `int` +Start time of the export range (UTC timestamp). + +**_stop_time_** `int` +End time of the export range (UTC timestamp). + +**_isoverwrite_** `int` +Whether to overwrite existing files (1 for true, 0 for false). + +**_camlistid_** `str` +Comma-separated list of camera IDs to export. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. ---- +
-### `check_license_quota` +--- ---- +### `get_event_export_info_from_recording_server` +Retrieve event export information from the recording server. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Export` +
+ +#### Parameters +
+**_start_time_** `int` +Start time of the export range (UTC timestamp). + +**_stop_time_** `int` +End time of the export range (UTC timestamp). + +**_camlistid_** `str` +Comma-separated list of camera IDs. + +
+#### Returns +
+`dict[str, object] or str` +Export information or error details. -### `get_http_video_stream` +
--- -### `save_action_rule` +### `load_event_mount` +Load event mount information for export. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Mount` +
+ +#### Returns +
+`dict[str, object] or str` +Mount information or error details. + +
--- -### `download_action_rule` - +### `redirect_webapi_to_target_ds` +Redirect a WebAPI request to a target DiskStation. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_dsId_** `int` +Target DiskStation ID. + +**_webAPI_** `Any` +WebAPI information to redirect (array of webAPI_info). + +
+#### Returns +
+`dict[str, object] or str` +Result of the redirect operation or error details. ---- +
-### `send_data_2_player` +--- ---- +### `modify_share_privilege` +Modify the share privilege settings in Surveillance Station CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_privSet_** `int` +Privilege set value. + +**_shareName_** `str` +Name of the share to modify. + +
+#### Returns +
+`dict[str, object] or str` +Result of the privilege modification or error details. -### `delete_all_histories_of_action_rule` +
--- -### `list_action_rules` - +### `apply_option_settings` +Apply option settings for Surveillance Station CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_central_auto_video_relay_** `bool` +Enable or disable central auto video relay. + +**_central_enable_** `bool` +Enable or disable central management. + +**_central_mode_** `str` +Set the central management mode. + +**_central_rec_mask_mode_** `bool` +Enable or disable central recording mask mode. + +**_central_rec_sync_time_** `bool` +Enable or disable central recording time synchronization. + +**_nvr_enable_** `bool` +Enable or disable NVR. + +**_nvr_lang_** `str` +Set the NVR language. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the apply operation or error details. ---- +
-### `disable_action_rules` +--- ---- +### `get_cms_info` +Retrieve CMS (Central Management System) information. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_isPolling_** `bool` +Whether to poll for CMS information. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +CMS information or error details. -### `enable_action_rules` +
--- -### `list_history_action_rules` - +### `get_log_recording_data_from_target_ds` +Retrieve log recording data from a target DiskStation. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_syncType_** `int` +Type of synchronization. + +**_syncTargetId_** `int` +ID of the target DiskStation for synchronization. + +**_limit_** `int` +Limit the number of records returned. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Log recording data or error details. ---- +
-### `delete_action_rule` +--- ---- - +### `get_samba_service` +Check if the Samba service is enabled on the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Returns +
+`dict[str, object] or str` +Samba service status or error details. -### `get_list_of_emaps` +
--- -### `get_specific_emaps_setting` - - - ---- - +### `check_if_samba_on_and_rec_enabled` +Check if Samba is enabled and recording is enabled on the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Returns +
+`dict[str, object] or str` +Status of Samba and recording or error details. -### `get_emap_image` +
--- -### `get_autorized_ds_token` - - - ---- +### `get_encoded_single_image_of_camera` +Retrieve an encoded single image (snapshot) from a specified camera. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_camId_** `int` +ID of the camera to get the snapshot from. + +
+#### Returns +
+`dict[str, object] or str` +Encoded image data or error details. -### `set_message_event` +
--- -### `get_message_event` - - - ---- +### `get_cms_status` +Retrieve the status of the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_camId_** `int` +ID of the camera to check status for. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +CMS status or error details. -### `set_notification_sender_name` +
--- -### `get_notification_sender_name` - +### `enable_smb_service` +Enable the Samba service on the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the enable operation or error details. +
---- -### `set_advanced_notification_setting` +--- +### `notify_slave_ds_to_disconnect` +Notify a slave DiskStation to disconnect from the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the notification or error details. ---- +
-### `get_advanced_notification_setting` +--- ---- +### `lock_recording_server_prevent_setting_change` +Lock the recording server to prevent setting changes. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS` +
+ +#### Parameters +
+**_locked_** `bool` +Whether to lock the server. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation or error details. -### `send_test_mesg_to_primary_secondary_phone` +
--- -### `get_setting_notification_sms` - +### `enable_ds_into_recording_server` +Enable a DiskStation as a recording server in the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_adminUsername_** `str` +Administrator username. + +**_adminPasswd_** `str` +Administrator password. + +**_central_rec_mask_mode_** `str` +Central recording mask mode. + +**_central_rec_sync_time_** `str` +Central recording synchronization time. + +
+#### Returns +
+`dict[str, object] or str` +Result of the enable operation or error details. ---- +
-### `set_sms_service_setting` +--- ---- +### `unpair_recording_servers` +Unpair recording servers from the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_adminUsername_** `str` +Administrator username. + +**_key_** `str` +Key for unpairing. + +**_mac_** `str` +MAC address of the server. + +**_cmsMode_** `int` +CMS mode. + +
+#### Returns +
+`dict[str, object] or str` +Result of the unpair operation or error details. -### `send_test_sms` +
--- -### `send_test_mail` +### `get_free_memory_size` +Retrieve the free memory size from the target DiskStation. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Returns +
+`dict[str, object] or str` +Free memory size information or error details. +
---- +--- -### `list_mobile_paired_devices` +### `handle_slave_ds` +Handle slave DiskStation operations such as locking or authentication. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_lock_** `bool` +Whether to lock the slave DiskStation. + +**_adminUsername_** `str` +Administrator username. + +**_key_** `str` +Authentication key. + +**_mac_** `str` +MAC address of the slave DiskStation. + +**_masterAuthKey_** `str` +Master authentication key. (To check). + +
+#### Returns +
+`dict[str, object] or str` +Result of the operation or error details. ---- +
-### `unpair_device` +--- ---- +### `get_target_ds_info` +Retrieve information about the target slave DiskStation. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_slaveDslp_** `str` +Slave DiskStation IP or identifier. + +
+#### Returns +
+`dict[str, object] or str` +Target DiskStation information or error details. -### `get_controller_access_schedule` +
--- -### `get_camera_alarm_schedule` - +### `logout_slave_ds` +Log out a slave DiskStation from the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_adminUsername_** `str` +Administrator username. + +**_key_** `str` +Authentication key. + +**_mac_** `str` +MAC address of the slave DiskStation. + +
+#### Returns +
+`dict[str, object] or str` +Result of the logout operation or error details. ---- +
-### `get_sys_dependent_schedule` +--- ---- +### `pair_slave_ds` +Pair a slave DiskStation with the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_dsname_** `str` +Name of the slave DiskStation. + +**_slaveDslp_** `str` +Slave DiskStation IP or identifier. + +**_port_** `int` +Port number for connection. + +**_masterAuthKey_** `str` +Master authentication key. + +**_model_** `str` +Model of the slave DiskStation. + +**_mac_** `str` +MAC address of the slave DiskStation. + +**_cms_locked_** `bool` +Whether the CMS is locked. + +**_cms_masked_** `bool` +Whether the CMS is masked. + +**_cms_sync_time_** `bool` +Synchronize time with CMS. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the pairing operation or error details. -### `set_batch_schedule` +
--- -### `get_access_ctrl_door_schedule` +### `login_slave_ds` +Log in a slave DiskStation to the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_adminUsername_** `str` +Administrator username. + +**_key_** `str` +Authentication key. + +**_mac_** `str` +MAC address of the slave DiskStation. + +**_masterAuthKey_** `str` +Master authentication key. + +**_hostName_** `str` +Hostname of the slave DiskStation. + +**_hostPort_** `int` +Port number for connection. + +**_ignoreAuthError_** `str` +Ignore authentication errors. + +**_hostDisconnect_** `bool` +Whether to disconnect the host. + +**_blUpdateVolSpace_** `bool` +Update volume space information. + +**_enable_rec_** `bool` +Enable recording. + +**_cms_locked_** `bool` +Whether the CMS is locked. + +**_cms_masked_** `bool` +Whether the CMS is masked. + +**_cms_sync_time_** `bool` +Synchronize time with CMS. (Currently not working). + +
+#### Returns +
+`dict[str, object] or str` +Result of the login operation or error details. +
---- -### `get_camera_schedule` +--- + + +### `save_slave_ds` +Save or update a slave DiskStation's configuration in the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.GetDsStatus` +
+ +#### Parameters +
+**_slavedsName_** `str` +Name of the slave DiskStation. + +**_slavedsModel_** `str` +Model of the slave DiskStation. + +**_slavedsPort_** `int` +Port number used by the slave DiskStation. + +**_slavedsVersion_** `str` +Version of the slave DiskStation. + +**_slavedsMaxCamNum_** `int` +Maximum number of cameras supported by the slave DiskStation. + +**_slavedsId_** `str` +Identifier for the slave DiskStation. + +**_slavedsIP_** `str` +IP address of the slave DiskStation. + +**_slavedsEnable_** `int` +Enable status of the slave DiskStation. + +**_slavedsCamCnt_** `bool` +Number of cameras currently connected to the slave DiskStation. + +**_adminUsername_** `str` +Administrator username for authentication. + +**_adminPasswd_** `str` +Administrator password for authentication. + +**_cms_locked_** `bool` +Whether the CMS is locked. + +**_cms_masked_** `bool` +Whether the CMS is masked. + +**_cms_sync_time_** `bool` +Synchronize time with CMS. (Currently not working). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
+ + + +--- + + +### `load_slave_ds_list` +Load the list of slave DiskStations from the CMS. + +#### Internal API +
+`SYNO.SurveillanceStation.CMS.SlavedsList` +
+ +#### Parameters +
+**_blNeedStatus_** `bool` +Whether to include status information. + +**_blGetSortInfo_** `bool` +Whether to include sorting information. + +**_blRuntimeInfo_** `bool` +Whether to include runtime information. + +**_dslds_** `str` +Comma-separated list of DiskStation IDs to load. + +**_sortInfo_** `int` +Sorting information. + + +
+#### Returns +
+`dict[str, object] or str` +List of slave DiskStations or error details. + +
+ + + +--- + + +### `count_number_of_logs` +Count the number of logs in Surveillance Station based on various filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Log` +
+ +#### Parameters +
+**_slavedsName_** `str` +Name of the slave DiskStation. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of logs to count. + +**_level_** `str` +Log level filter. + +**_filterCamera_** `str` +Filter by camera. + +**_cameraIds_** `str` +Comma-separated list of camera IDs. + +**_dsfrom_** `int` +Start time (timestamp). + +**_to_** `int` +End time (timestamp). + +**_keyword_** `str` +Keyword to search in logs. + +**_keywordDsId_** `str` +DiskStation ID for keyword search. + +**_time2String_** `str` +Time string for filtering. + +**_dsId_** `str` +DiskStation ID. + +**_srcType_** `int` +Source type filter. + +**_timezoneOffset_** `int` +Timezone offset. + + +
+#### Returns +
+`dict[str, object] or str` +Count of logs or error details. + +
+ + + +--- + + +### `clear_selected_logs` +Clear selected logs from Surveillance Station based on various filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Log` +
+ +#### Parameters +
+**_blClearAll_** `bool` +Whether to clear all logs. + +**_level_** `int` +Log level filter. + +**_dsId_** `int` +DiskStation ID. + +**_filterCamera_** `str` +Filter by camera. + +**_cameraIds_** `str` +Comma-separated list of camera IDs. + +**_dsfrom_** `int` +Start time (timestamp). + +**_to_** `int` +End time (timestamp). + +**_keyword_** `str` +Keyword to search in logs. + +**_keywordDsId_** `str` +DiskStation ID for keyword search. + +**_srcType_** `int` +Source type filter. + +**_timezoneOffset_** `int` +Timezone offset. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the clear operation or error details. + +
+ + + +--- + + +### `get_information_log` +Retrieve information logs from Surveillance Station based on various filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Log` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of logs to retrieve. + +**_level_** `str` +Log level filter. + +**_filterCamera_** `str` +Filter by camera. + +**_cameraIds_** `str` +Comma-separated list of camera IDs. + +**_dsfrom_** `int` +Start time (timestamp). + +**_to_** `int` +End time (timestamp). + +**_keyword_** `str` +Keyword to search in logs. + +**_keywordDsId_** `str` +DiskStation ID for keyword search. + +**_time2String_** `str` +Time string for filtering. + +**_dsId_** `int` +DiskStation ID. + +**_srcType_** `int` +Source type filter. + +**_all_** `bool` +Whether to retrieve all logs. + +**_blIncludeRecCnt_** `str` +Include recording count information. + +**_blIncludeAuInfo_** `str` +Include additional information. + + +
+#### Returns +
+`dict[str, object] or str` +List of information logs or error details. + +
+ + + +--- + + +### `get_advanced_settings_logs` +Retrieve advanced log settings from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Log` +
+ +#### Returns +
+`dict[str, object] or str` +Advanced log settings or error details. + +
+ + + +--- + + +### `set_advanced_setting_logs` +Set advanced log settings in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Log` +
+ +#### Parameters +
+**_data_** `Any` +List of log type settings to apply. +Example: + data=\[\{"SSLogType":321912835,"enable":1\},\{"SSLogType":321912836,"enable":0\}\] + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `load_license_data` +Load license data from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.License` +
+ +#### Parameters +
+**_num_only_** `int` +If set, only the number of licenses will be returned. + + +
+#### Returns +
+`dict[str, object] or str` +License data or error details. + +
+ + + +--- + + +### `check_license_quota` +Check the license quota for cameras in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.License` +
+ +#### Parameters +
+**_camList_** `Any` +List of camera information dictionaries. +Example: + camList = \[\{"ip": "10.13.22.141", "model": "DCS-3110", "vendor": "DLink", "port": 80\}\] + +**_camServerId_** `int` +Camera server ID. + + +
+#### Returns +
+`dict[str, object] or str` +License quota information or error details. + +
+ + + +--- + + +### `get_http_video_stream` +Retrieve an HTTP video event stream from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Stream` +
+ +#### Parameters +
+**_writeHeader_** `bool` +Whether to include headers in the stream. + +**_analyevent_** `bool` +Whether to analyze events in the stream. + +**_mountId_** `int` +Mount ID for the stream. + + +
+#### Returns +
+`dict[str, object] or str` +Video stream data or error details. + +
+ + + +--- + + +### `save_action_rule` +Save or update an action rule in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_id_** `int` +Action rule ID. + +**_name_** `str` +Name of the action rule. + +**_ruleType_** `int` +Type of the rule. + +**_actType_** `int` +Action type. + +**_evtSrc_** `int` +Event source. + +**_evtDsId_** `int` +Event DiskStation ID. + +**_evtDevId_** `int` +Event device ID. + +**_evtId_** `int` +Event ID. + +**_evtItem_** `int` +Event item. + +**_evtMinIntvl_** `int` +Minimum interval between events. + +**_Actions_** `Any` +List of actions to perform. + +**_actSchedule_** `str` +Action schedule. + +**_Id_** `int` +Alternative action rule ID. + +**_actSrc_** `int` +Action source. + +**_actDsId_** `int` +Action DiskStation ID. + +**_actDevId_** `int` +Action device ID. + +**_actId_** `int` +Action ID. + +**_actTimes_** `int` +Number of times to perform the action. + +**_actTimeUnit_** `int` +Time unit for the action. + +**_actTimeDur_** `int` +Duration for the action. + +**_actItemId_** `int` +Action item ID. + +**_actRetPos_** `int` +Action return position. + +**_extUrl_** `str` +External URL for the action. + +**_userName_** `str` +Username for authentication. + +**_password_** `str` +Password for authentication. (Currently not working). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
+ + + +--- + + +### `download_action_rule` +Download the history of action rules from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Returns +
+`dict[str, object] or str` +Downloaded action rule history or error details. + +
+ + + +--- + + +### `send_data_2_player` +Send data to the Surveillance Station player. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the send operation or error details. + +
+ + + +--- + + +### `delete_all_histories_of_action_rule` +Delete all histories of specified action rules. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of action rule IDs to delete histories for. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `list_action_rules` +List action rules in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_start_** `str` +Start index for pagination. + +**_limit_** `int` +Maximum number of action rules to return. + + +
+#### Returns +
+`dict[str, object] or str` +List of action rules or error details. + +
+ + + +--- + + +### `disable_action_rules` +Disable specified action rules in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of action rule IDs to disable. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the disable operation or error details. + +
+ + + +--- + + +### `enable_action_rules` +Enable specified action rules in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of action rule IDs to enable. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the enable operation or error details. + +
+ + + +--- + + +### `list_history_action_rules` +List the history of action rules in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of history records to return. + + +
+#### Returns +
+`dict[str, object] or str` +List of action rule histories or error details. + +
+ + + +--- + + +### `delete_action_rule` +Delete specified action rules from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ActionRule` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of action rule IDs to delete. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `get_list_of_emaps` +Retrieve a list of eMaps from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Emap` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `str` +Maximum number of eMaps to return. + +**_emapIds_** `int` +Specific eMap IDs to retrieve. + +**_includeItems_** `int` +Whether to include items in the eMap. + + +
+#### Returns +
+`dict[str, object] or str` +List of eMaps or error details. + +
+ + + +--- + + +### `get_specific_emaps_setting` +Retrieve specific eMap settings from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Emap` +
+ +#### Parameters +
+**_emapIds_** `int` +The ID(s) of the eMap(s) to retrieve settings for. + +**_includeImage_** `int` +Whether to include the eMap image in the response. + + +
+#### Returns +
+`dict[str, object] or str` +The eMap settings or error details. + +
+ + + +--- + + +### `get_emap_image` +Retrieve an eMap image from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Emap.Image` +
+ +#### Parameters +
+**_filename_** `str` +The filename of the eMap image to retrieve. + + +
+#### Returns +
+`dict[str, object] or str` +The eMap image data or error details. + +
+ + + +--- + + +### `get_autorized_ds_token` +Retrieve an authorized DiskStation token for notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Returns +
+`dict[str, object] or str` +The authorized token or error details. + +
+ + + +--- + + +### `set_message_event` +Set a customized message event in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Parameters +
+**_eventTypes_** `str` +The type(s) of event(s) to set the message for. + +**_subject_** `str` +The subject of the message. + +**_content_** `str` +The content of the message. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `get_message_event` +Retrieve a customized message event from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Parameters +
+**_eventTypes_** `int` +The type(s) of event(s) to retrieve the message for. + + +
+#### Returns +
+`dict[str, object] or str` +The message event data or error details. + +
+ + + +--- + + +### `set_notification_sender_name` +Set the sender name for Surveillance Station notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Parameters +
+**_ss_pkg_name_** `str` +The sender name to set. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `get_notification_sender_name` +Retrieve the sender name for Surveillance Station notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Returns +
+`dict[str, object] or str` +The sender name or error details. + +
+ + + +--- + + +### `set_advanced_notification_setting` +Set advanced notification settings in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Parameters +
+**_blSyncDSMNotify_** `bool` +Whether to synchronize DSM notifications. + +**_blCompactMsg_** `bool` +Whether to enable compact message format. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `get_advanced_notification_setting` +Retrieve advanced notification settings from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification` +
+ +#### Returns +
+`dict[str, object] or str` +The advanced notification settings or error details. + +
+ + + +--- + + +### `send_test_mesg_to_primary_secondary_phone` +Send a test message to the primary and secondary phone numbers via SMS. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS` +
+ +#### Parameters +
+**_smsEnable_** `bool` +Whether SMS notifications are enabled. + +**_smsMethod_** `int` +The SMS sending method. + +**_smsProvider_** `str` +The SMS provider name. + +**_userName_** `str` +Username for SMS provider authentication. + +**_password_** `str` +Password for SMS provider authentication. + +**_confirmPassword_** `str` +Confirmation of the password. + +**_primaryPhoneCode_** `str` +Country code for the primary phone. + +**_primaryPhonePrefix_** `str` +Prefix for the primary phone. + +**_secondaryPhoneCode_** `str` +Country code for the secondary phone. + +**_secondaryPhonePrefix_** `str` +Prefix for the secondary phone. + +**_secondaryPhoneNumber_** `str` +The secondary phone number. + +**_setMinMessageInterval_** `bool` +Whether to set a minimum message interval. + +**_minMessageInterval_** `int` +The minimum interval between messages. + +**_hasSysSms_** `bool` +Whether system SMS is enabled. + +**_apiId_** `str` +The API ID for the SMS provider. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the test message operation or error details. + +
+ + + +--- + + +### `get_setting_notification_sms` +Retrieve the SMS notification settings from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS` +
+ +#### Returns +
+`dict[str, object] or str` +The SMS notification settings or error details. + +
+ + + +--- + + +### `set_sms_service_setting` +Set the SMS service settings for Surveillance Station notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS` +
+ +#### Parameters +
+**_smsEnable_** `bool` +Whether SMS notifications are enabled. + +**_smsMethod_** `int` +The SMS sending method. + +**_smsProvider_** `str` +The SMS provider name. + +**_userName_** `str` +Username for SMS provider authentication. + +**_password_** `str` +Password for SMS provider authentication. + +**_confirmPassword_** `str` +Confirmation of the password. + +**_primaryPhoneCode_** `str` +Country code for the primary phone. + +**_primaryPhonePrefix_** `str` +Prefix for the primary phone. + +**_secondaryPhoneCode_** `str` +Country code for the secondary phone. + +**_secondaryPhonePrefix_** `str` +Prefix for the secondary phone. + +**_secondaryPhoneNumber_** `str` +The secondary phone number. + +**_setMinMessageInterval_** `bool` +Whether to set a minimum message interval. + +**_minMessageInterval_** `int` +The minimum interval between messages. + +**_hasSysSms_** `bool` +Whether system SMS is enabled. + +**_apiId_** `str` +The API ID for the SMS provider. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `send_test_sms` +Send a test SMS notification from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS` +
+ +#### Parameters +
+**_attachSnapshot_** `bool` +Whether to attach a snapshot to the SMS. + +**_enableInterval_** `bool` +Whether to enable message interval. + +**_mobileEnable_** `bool` +Whether to enable mobile notifications. + +**_msgInterval_** `str` +The interval between messages. + +**_primaryEmail_** `str` +The primary email address for notifications. + +**_secondaryEmail_** `str` +The secondary email address for notifications. + +**_synoMailEnable_** `bool` +Whether to enable Synology Mail notifications. + +**_mail_recipient_** `str` +The recipient of the test mail. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the test SMS operation or error details. + +
+ + + +--- + + +### `send_test_mail` +Send a test verification mail for Surveillance Station notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.PushService` +
+ +#### Parameters +
+**_attachSnapshot_** `bool` +Whether to attach a snapshot to the email. + +**_enableInterval_** `bool` +Whether to enable message interval. + +**_mobileEnable_** `bool` +Whether to enable mobile notifications. + +**_msgInterval_** `str` +The interval between messages. + +**_primaryEmail_** `str` +The primary email address for notifications. + +**_secondaryEmail_** `str` +The secondary email address for notifications. + +**_synoMailEnable_** `bool` +Whether to enable Synology Mail notifications. + +**_mail_recipient_** `str` +The recipient of the test mail. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the test mail operation or error details. + +
+ + + +--- + + +### `list_mobile_paired_devices` +List mobile devices paired with Surveillance Station for push notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.PushService` +
+ +#### Parameters +
+**_attachSnapshot_** `bool` +Whether to attach a snapshot to the notification. + +**_enableInterval_** `bool` +Whether to enable message interval. + +**_mobileEnable_** `bool` +Whether to enable mobile notifications. + +**_msgInterval_** `str` +The interval between messages. + +**_primaryEmail_** `str` +The primary email address for notifications. + +**_secondaryEmail_** `str` +The secondary email address for notifications. + +**_synoMailEnable_** `bool` +Whether to enable Synology Mail notifications. + +**_mail_recipient_** `str` +The recipient of the notification. + + +
+#### Returns +
+`dict[str, object] or str` +List of paired mobile devices or error details. + +
+ + + +--- + + +### `unpair_device` +Unpair a mobile device from Surveillance Station notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.PushService` +
+ +#### Parameters +
+**_targetIds_** `str` +The ID(s) of the device(s) to unpair. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the unpair operation or error details. + +
+ + + +--- + + +### `get_controller_access_schedule` +Retrieve the access control controller schedule from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_targetIds_** `str` +The ID(s) of the controllers to retrieve the schedule for. + + +
+#### Returns +
+`dict[str, object] or str` +The controller access schedule or error details. + +
+ + + +--- + + +### `get_camera_alarm_schedule` +Retrieve the alarm schedule for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_cameraId_** `int` +The ID of the camera. + +**_alarmdx_** `int` +Additional alarm parameter (to check). + + +
+#### Returns +
+`dict[str, object] or str` +The camera alarm schedule or error details. + +
+ + + +--- + + +### `get_sys_dependent_schedule` +Retrieve the system dependent schedule for Surveillance Station events. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_eventGroupTypes_** `int` +The type(s) of event groups to retrieve the schedule for. + + +
+#### Returns +
+`dict[str, object] or str` +The system dependent schedule or error details. + +
+ + + +--- + + +### `set_batch_schedule` +Set batch schedules for events, cameras, or camera groups. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_eventTypes_** `str` +The type(s) of events to schedule. + +**_schedule_** `Any` +The schedule data to apply. + +**_cameraIds_** `str` +The IDs of cameras to apply the schedule to. + +**_cameraGroupIds_** `str` +The IDs of camera groups to apply the schedule to. + +**_filter_** `int` +Additional filter parameter (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the batch schedule operation or error details. + +
+ + + +--- + + +### `get_access_ctrl_door_schedule` +Retrieve the access control door schedule from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_doorId_** `str` +The ID of the door to retrieve the schedule for. + + +
+#### Returns +
+`dict[str, object] or str` +The door schedule or error details. + +
+ + + +--- + + +### `get_camera_schedule` +Retrieve the schedule for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_cameraId_** `str` +The ID of the camera to retrieve the schedule for. + + +
+#### Returns +
+`dict[str, object] or str` +The camera schedule or error details. + +
+ + + +--- + + +### `set_sys_dependent_schedule` +Set the system dependent schedule for Surveillance Station events. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_eventType_** `int` +The type of event to set the schedule for. + +**_schedule_** `Any` +The schedule data to apply. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `set_controller_access_schedule` +Set the access control schedule for a controller or door. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_eventType_** `int` +The type of event to set the schedule for. + +**_schedule_** `Any` +The schedule data to apply. + +**_doorId_** `int` +The ID of the door to set the schedule for. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `set_camera_schedule` +Set the schedule for a specific camera in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Schedule` +
+ +#### Parameters +
+**_eventType_** `int` +The type of event to set the schedule for. + +**_schedule_** `Any` +The schedule data to apply. + +**_cameraId_** `Any` +The ID of the camera to set the schedule for. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `get_notification_email_string` +Retrieve the notification email settings string from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Email` +
+ +#### Returns +
+`dict[str, object] or str` +The notification email settings or error details. + +
+ + + +--- + + +### `set_adv_tab_info_filter` +Set the advanced tab information filter for notification emails. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.Email` +
+ +#### Parameters +
+**_X_** `int` +The filter value to set (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `create_sms_service_provider` +Create a new SMS service provider for Surveillance Station notifications. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS.ServiceProvider` +
+ +#### Parameters +
+**_providerName_** `str` +The name of the SMS provider. + +**_providerPort_** `int` +The port used by the provider. + +**_providerUrl_** `str` +The URL of the provider. + +**_providerTemplate_** `str` +The message template for the provider. + +**_providerSepChar_** `str` +The separator character used by the provider. + +**_providerNeedSSL_** `bool` +Whether SSL is required for the provider. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the create operation or error details. + +
+ + + +--- + + +### `list_sms_provider` +List all SMS service providers configured in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS.ServiceProvider` +
+ +#### Returns +
+`dict[str, object] or str` +List of SMS providers or error details. + +
+ + + +--- + + +### `delete_sms_service_provider` +Delete an SMS service provider from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Notification.SMS.ServiceProvider` +
+ +#### Parameters +
+**_providerName_** `str` +The name of the SMS provider to delete. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `get_addson_to_update` +Retrieve information about add-ons that require updates in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Returns +
+`dict[str, object] or str` +Add-on update information or error details. + +
+ + + +--- + + +### `enable_specific_addon` +Enable a specific add-on in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to enable. + +**_servicename_** `str` +The name of the add-on service to enable. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the enable operation or error details. + +
+ + + +--- + + +### `get_specific_addon_update_info` +Retrieve update information for a specific add-on in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to check for updates. + + +
+#### Returns +
+`dict[str, object] or str` +Update information or error details. + +
+ + + +--- + + +### `get_specific_addon_info` +Retrieve information for a specific add-on in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to retrieve information for. + + +
+#### Returns +
+`dict[str, object] or str` +Add-on information or error details. + +
+ + + +--- + + +### `get_total_addon_info` +Retrieve information about all add-ons in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Returns +
+`dict[str, object] or str` +List of all add-ons or error details. + +
+ + + +--- + + +### `update_addon_package` +Update an add-on package in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to update. + +**_filePath_** `str` +The file path to the add-on package (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the update operation or error details. + +
+ + + +--- + + +### `check_addon_status` +Check the enable status of a specific add-on in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to check (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Status information or error details. + +
+ + + +--- + + +### `disable_addon` +Disable a specific add-on in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to disable. + +**_serviceName_** `str` +The name of the add-on service to disable (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the disable operation or error details. + +
+ + + +--- + + +### `set_addon_autoupdate` +Set the auto-update setting for a specific add-on in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AddOns` +
+ +#### Parameters +
+**_service_** `int` +The ID of the add-on service to configure. + +**_BlEnabled_** `Any` +Whether auto-update is enabled (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. + +
+ + + +--- + + +### `delete_specific_camera_recording_server` +Delete a specific camera recording server in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_camIdList_** `str` +List of camera IDs to delete from the recording server (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `get_camera_event_analytic` +Retrieve camera event analytics from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_camIdList_** `str` +List of camera IDs to retrieve analytics for (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Analytics data or error details. + +
+ + + +--- + + +### `delete_selected_events` +Delete selected events from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_dsIdList_** `str` +List of DS IDs for which to delete events. + +**_idList_** `str` +List of event IDs to delete (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `delete_specific_camera_events` +Delete events for specific cameras in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_camIdList_** `str` +List of camera IDs for which to delete events (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `get_analytic_history` +Retrieve analytic history for cameras in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_camIdList_** `str` +List of camera IDs to retrieve history for. + +**_typeListstring_** `str` +List of analytic types as a string (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Analytic history data or error details. + +
+ + + +--- + + +### `get_analytic_history_by_filter` +Retrieve analytic history for cameras by filter in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_camIdList_** `str` +List of camera IDs to filter. + +**_dsId_** `int` +The DS ID to filter. + +**_lock_** `int` +Lock status to filter. + +**_typeList_** `str` +List of analytic types as a string (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Filtered analytic history data or error details. + +
+ + + +--- + + +### `unklock_selected_events` +Unlock selected events in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_dsId_** `int` +The DS ID for which to unlock events. + +**_idList_** `str` +List of event IDs to unlock (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation or error details. + +
+ + + +--- + + +### `set_camera_analytic_trigger` +Trigger camera analytics for specified cameras in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_trigCamIdList_** `str` +List of camera IDs to trigger analytics for (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the trigger operation or error details. + +
+ + + +--- + + +### `flush_event_header` +Flush the header of a specific event in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_eventId_** `str` +The ID of the event to flush the header for (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the flush operation or error details. + +
+ + + +--- + + +### `lock_selected_events` +Lock selected events in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_dsId_** `int` +The DS ID for which to lock events. + +**_idList_** `str` +List of event IDs to lock (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation or error details. + +
+ + + +--- + + +### `get_analytic_event_from_rec_server` +Retrieve analytic event counts from the recording server for specified cameras. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert` +
+ +#### Parameters +
+**_camIdList_** `str` +Comma-separated list of camera IDs to query. + +**_idList_** `int` +Additional ID list parameter (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Analytic event count data or error details. + +
+ + + +--- + + +### `save_analytic_settings` +Save analytic settings for a specific camera. + +#### Internal API +
+`SYNO.SurveillanceStation.Alert.Setting` +
+ +#### Parameters +
+**_camId_** `int` +Camera ID to apply settings to. + +**_type_** `int` +Type of analytic. + +**_showFrame_** `bool` +Whether to display the frame. + +**_showLine_** `bool` +Whether to display lines. + +**_showVirtualFence_** `bool` +Whether to display virtual fences. + +**_beep_** `bool` +Whether to enable beep on event. + +**_sens_** `int` +Sensitivity setting. + +**_dwellTime_** `int` +Dwell time setting. + +**_direction_** `int` +Direction setting. + +**_objSize_** `int` +Object size setting. + +**_region_** `str` +Region definition (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
+ + + +--- + + +### `check_if_snapshot_exist` +Check if a snapshot exists for a given ID. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_id_** `int` +Snapshot ID to check (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Existence status or error details. + +
+ + + +--- + + +### `save_snapshot_modification` +Save modifications to a snapshot. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_id_** `int` +Snapshot ID to modify. + +**_createCopy_** `bool` +Whether to create a copy of the snapshot. + +**_width_** `int` +Width of the snapshot. + +**_height_** `int` +Height of the snapshot. + +**_byteSize_** `int` +Size of the snapshot in bytes. + +**_imageData_** `str` +Image data (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the modification or error details. + +
+ + + +--- + + +### `count_snapshot_by_category` +Count snapshots by category within a specified range. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_keyword_** `str` +Keyword to filter snapshots. + +**_dsfrom_** `int` +Start timestamp. + +**_to_** `int` +End timestamp. + +**_timezoneOffset_** `int` +Timezone offset. + +**_byteSize_** `int` +Size of the snapshot in bytes. + +**_imageData_** `str` +Image data (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Count data or error details. + +
+ + + +--- + + +### `check_any_locked_snapshot` +Check if any locked snapshots exist within a specified range. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_id_** `str` +Snapshot ID(s) to check. + +**_dsfrom_** `int` +Start timestamp. + +**_to_** `int` +End timestamp. + +**_keyword_** `str` +Keyword to filter snapshots (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Lock status or error details. + +
+ + + +--- + + +### `unlock_snapshot_by_filter` +Unlock snapshots by filter within a specified range. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_dsfrom_** `int` +Start timestamp. + +**_to_** `int` +End timestamp. + +**_keyword_** `str` +Keyword to filter snapshots (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation or error details. + +
+ + + +--- + + +### `list_snapshot_information` +List snapshot information with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_idList_** `str` +Comma-separated list of snapshot IDs. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_dsfrom_** `int` +Start timestamp. + +**_to_** `int` +End timestamp. + +**_keyword_** `str` +Keyword to filter snapshots. + +**_imgSize_** `int` +Image size filter. + +**_blIncludeAuInfo_** `bool` +Whether to include additional info. + +**_blIncludeRecCnt_** `bool` +Whether to include recording count. + +**_camId_** `int` +Camera ID filter (to check). + + +
+#### Returns +
+`dict[str, object] or str` +List of snapshot information or error details. + +
+ + + +--- + + +### `unlock_snapshot` +Unlock specific snapshots. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_objList_** `Any` +List of snapshot objects to unlock (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation or error details. + +
+ + + +--- + + +### `take_snapshot` +Take a snapshot for a specific camera and DS. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_dsId_** `int` +DS ID for the snapshot. + +**_camId_** `int` +Camera ID for the snapshot. + +**_blSave_** `bool` +Whether to save the snapshot (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the snapshot operation or error details. + +
+ + + +--- + + +### `get_snapshot_setting_function` +Retrieve the snapshot setting function. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Returns +
+`dict[str, object] or str` +Snapshot setting information or error details. + +
+ + + +--- + + +### `delete_snapshot_by_filter` +Delete snapshots by filter within a specified range. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_deleteAllCommand_** `bool` +Whether to delete all snapshots. + +**_dsfrom_** `int` +Start timestamp. + +**_to_** `int` +End timestamp. + +**_keyword_** `str` +Keyword to filter snapshots (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `get_snapshot_image` +Retrieve a snapshot image by ID. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_id_** `int` +Snapshot ID to retrieve. + +**_imgSize_** `int` +Image size (to modify for download?). + + +
+#### Returns +
+`dict[str, object] or str` +Snapshot image data or error details. + +
+ + + +--- + + +### `lock_snapshot_image` +Lock specific snapshot images. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_objList_** `Any` +List of snapshot objects to lock. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation or error details. + +
+ + + +--- + + +### `downld_single_snapshot` +Download a single snapshot by ID. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_id_** `int` +Snapshot ID to download (not working). + + +
+#### Returns +
+`dict[str, object] or str` +Download result or error details. + +
+ + + +--- + + +### `save_new_snapshot_setting` +Save new snapshot settings. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_dispSnapshot_** `bool` +Whether to display snapshots. + +**_dispDuration_** `int` +Display duration for snapshots. + +**_limitTotalSize_** `bool` +Whether to limit total snapshot size. + +**_limitSizeInGb_** `int` +Limit size in GB. + +**_addTimestamp_** `bool` +Whether to add a timestamp to snapshots. + +**_timestampPosition_** `int` +Position of the timestamp. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
+ + + +--- + + +### `save_snapshot` +Save a new snapshot. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_camName_** `str` +Name of the camera. + +**_createdTm_** `int` +Creation timestamp. + +**_width_** `int` +Width of the snapshot. + +**_height_** `int` +Height of the snapshot. + +**_byteSize_** `int` +Size of the snapshot in bytes. + +**_imageData_** `str` +Image data (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
+ + + +--- + + +### `check_snapshot_status` +Check the status of snapshot display. + +#### Internal API +
+`SYNO.SurveillanceStation.SnapShot` +
+ +#### Parameters +
+**_dispSnapshot_** `bool` +Whether to display snapshots. + + +
+#### Returns +
+`dict[str, object] or str` +Status information or error details. + +
+ + + +--- + + +### `enable_visualstation` +Enable VisualStation devices. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Parameters +
+**_vslist_** `str` +Comma-separated list of VisualStation IDs to enable (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the enable operation or error details. + +
+ + + +--- + + +### `update_vs_network_config` +Update the network configuration for a VisualStation device. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Parameters +
+**_vsMAc_** `str` +MAC address of the VisualStation. + +**_ip_** `str` +IP address to assign. + +**_mask_** `str` +Subnet mask. + +**_gateway_** `str` +Gateway address. + +**_blDhcp_** `bool` +Whether to use DHCP. + +**_name_** `str` +Name of the VisualStation (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the update operation or error details. + +
+ + + +--- + + +### `lock_visualstation_by_id` +Lock VisualStation devices by ID. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Parameters +
+**_vslist_** `str` +Comma-separated list of VisualStation IDs to lock (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation or error details. + +
+ + + +--- + + +### `enumerate_vs_owner_info` +Enumerate VisualStation owner information. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Returns +
+`dict[str, object] or str` +Owner information or error details. + +
+ + + +--- + + +### `unlock_visualstation_by_id` +Unlock VisualStation devices by ID. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Parameters +
+**_vslist_** `str` +Comma-separated list of VisualStation IDs to unlock (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation or error details. + +
+ + + +--- + + +### `disable_visualstation_by_id` +Disable VisualStation devices by ID. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Parameters +
+**_vslist_** `str` +Comma-separated list of VisualStation IDs to disable (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the disable operation or error details. + +
+ + + +--- + + +### `delete_specific_visualstation` +Delete specific VisualStation devices by ID. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation` +
+ +#### Parameters +
+**_vslist_** `str` +Comma-separated list of VisualStation IDs to delete (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `enumerate_layout_visualstation` +Enumerate VisualStation layouts. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Layout` +
+ +#### Parameters +
+**_vsId_** `int` +VisualStation ID to filter layouts (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Layout information or error details. + +
+ + + +--- + + +### `save_layout_information` +Save layout information for a VisualStation. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Layout` +
+ +#### Parameters +
+**_id_** `int` +Layout ID. + +**_vsId_** `int` +VisualStation ID. + +**_name_** `str` +Name of the layout. + +**_canGrpId_** `int` +Camera group ID. + +**_isDefault_** `int` +Whether this is the default layout. + +**_isFixAspectRatio_** `int` +Whether to fix the aspect ratio. + +**_layoutType_** `int` +Type of the layout. + +**_channelList_** `Any` +List of channels in the layout. + +**_customPosList_** `str` +Custom position list (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
+ + + +--- + + +### `delete_layout_visualstation` +Delete a VisualStation layout. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Layout` +
+ +#### Parameters +
+**_id_** `int` +Layout ID to delete. + +**_vsId_** `int` +VisualStation ID (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. + +
+ + + +--- + + +### `clear_visualstation_search_result` +Clear VisualStation search results. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Search` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the clear operation or error details. + +
+ + + +--- + + +### `get_visualstation_ip_info` +Retrieve VisualStation IP information. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Search` +
+ +#### Parameters +
+**_ip_** `int` +IP address to search for (to check). + + +
+#### Returns +
+`dict[str, object] or str` +IP information or error details. + +
+ + + +--- + + +### `stop_previous_visualstation_search` +Stop the previous VisualStation search operation. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Search` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the stop operation or error details. + +
--- -### `set_sys_dependent_schedule` +### `get_visualstation_list` +Retrieve the list of VisualStation devices. + +#### Internal API +
+`SYNO.SurveillanceStation.VisualStation.Layout` +
+ +#### Parameters +
+**_offset_** `int` +Offset for pagination (to check). + + +
+#### Returns +
+`dict[str, object] or str` +List of VisualStation devices or error details. + +
--- -### `set_controller_access_schedule` +### `get_number_of_controller` +Get the number of controllers in the system. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Returns +
+`dict[str, object] or str` +Number of controllers or error details. + +
--- -### `set_camera_schedule` +### `get_cardholder_count` +Get the count of cardholders, optionally filtered by keyword. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_filterKeyword_** `str` +Keyword to filter cardholders. + +
+#### Returns +
+`dict[str, object] or str` +Cardholder count or error details. +
---- -### `get_notification_email_string` +--- +### `enum_all_controllers_logger` +Enumerate all controller logger configurations. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Returns +
+`dict[str, object] or str` +Logger configuration information or error details. ---- +
-### `set_adv_tab_info_filter` +--- ---- +### `get_cardholder_photo` +Retrieve a cardholder's photo. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_photo_name_** `str` +Name of the photo file. + +**_isRedirectCgi_** `bool` +Whether to redirect to CGI for the photo (to check). + +
+#### Returns +
+`dict[str, object] or str` +Photo data or error details. -### `create_sms_service_provider` +
--- -### `list_sms_provider` - +### `get_log_count` +Get the count of logs with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_filterType_** `int` +Type of filter to apply. + +**_filterEventSource_** `Any` +Event source filter. + +**_filterSource_** `int` +Source filter. + +**_filterEventSourceItem_** `int` +Event source item filter. + +**_filterTimeFrom_** `int` +Start time for filtering. + +**_filterTimeTo_** `int` +End time for filtering. + +**_filterKeyword_** `str` +Keyword to filter logs. + +**_timezoneOffset_** `int` +Timezone offset. + +**_doorIds_** `str` +Door IDs filter. + +**_eventTypes_** `str` +Event types filter. + +**_update_** `int` +Update flag. + +
+#### Returns +
+`dict[str, object] or str` +Log count or error details. ---- +
-### `delete_sms_service_provider` +--- ---- +### `get_cardholder_info` +Retrieve cardholder information with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_filterKeyword_** `str` +Keyword to filter cardholders. + +**_filterStatus_** `int` +Status filter. + +**_filterCtrlerId_** `int` +Controller ID filter. + +
+#### Returns +
+`dict[str, object] or str` +Cardholder information or error details. -### `get_addson_to_update` +
--- -### `enable_specific_addon` - +### `retrieve_last_access_credential` +Retrieve the last access credential for a controller. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_ctrlerId_** `int` +Controller ID. + +**_idPtId_** `int` +ID/point ID (to check). + +
+#### Returns +
+`dict[str, object] or str` +Last access credential information or error details. ---- +
-### `get_specific_addon_update_info` +--- ---- +### `enable_disable_controller` +Enable or disable controllers. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_blEnable_** `bool` +Whether to enable (True) or disable (False) controllers. + +**_arrayJson_** `str` +JSON array of controller IDs. + +
+#### Returns +
+`dict[str, object] or str` +Result of the operation or error details. -### `get_specific_addon_info` +
--- -### `get_total_addon_info` - +### `acknowledge_all_alarm_level_log` +Acknowledge all alarm level logs with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_filterEventSource_** `Any` +Event source filter. + +**_filterSource_** `int` +Source filter. + +**_filterEventSourceItem_** `str` +Event source item filter. + +**_filterTimeFrom_** `int` +Start time for filtering. + +**_filterKeyword_** `str` +Keyword to filter logs. + +**_doorIds_** `str` +Door IDs filter. + +**_eventTypes_** `str` +Event types filter. + +**_update_** `int` +Update flag. + +
+#### Returns +
+`dict[str, object] or str` +Result of the acknowledge operation or error details. ---- +
-### `update_addon_package` +--- ---- +### `modify_controller_logger_config` +Modify the logger configuration for a controller. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_data_** `Any` +Logger configuration data (see example in docstring). + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. -### `check_addon_status` +
--- -### `disable_addon` +### `save_controller_settings` +Save controller settings for Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_arrayJson_** `str` +JSON string representing controller settings. Example: +\[\{"enable": true, "id": 97, "name": "ctrler1", "host": "10.13.12.173", "port": 80, + "model": "A1001", "username": "root", "password": "Q__Q-__-", "time_server": + "SurveillanceStation", "time_zone": "Fiji", "door": \[\{"id": 231, "name": "FrontDoor", + "enable_cam": true, "cam_ds_id": 0, "cam_id": 13\}\]\}\] + + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. + +
--- -### `set_addon_autoupdate` +### `download_filtered_logs` +Download filtered logs from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_filterType_** `int` +Type of filter to apply. + +**_filterEventSource_** `int` +Event source filter. + +**_filterSource_** `int` +Source filter. + +**_filterEventSourceItem_** `str` +Event source item filter. + +**_filterTimeFrom_** `int` +Start time for filtering. + +**_filterTimeTo_** `int` +End time for filtering. + +**_filterKeyword_** `str` +Keyword to filter logs. + +**_doorIds_** `str` +Door IDs filter. + +**_eventTypes_** `str` +Event types filter. + +**_update_** `int` +Update flag. + + +
+#### Returns +
+`dict[str, object] or str` +Downloaded log data or error details. + +
--- -### `delete_specific_camera_recording_server` +### `get_door_name_from_controller` +Retrieve door names from a specific controller. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_ctrlerId_** `int` +Controller ID. + +**_ip_** `str` +Controller IP address. + +**_port_** `int` +Controller port. + +**_userName_** `str` +Username for authentication. + +**_password_** `int` +Password for authentication (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Door names or error details. + +
--- -### `get_camera_event_analytic` +### `test_connection_and_authentication` +Test connection and authentication to a controller. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_ctrlerId_** `int` +Controller ID. + +**_ip_** `str` +Controller IP address. + +**_port_** `int` +Controller port. + +**_userName_** `str` +Username for authentication. + +**_password_** `int` +Password for authentication (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Result of the test or error details. + +
--- -### `delete_selected_events` +### `enumerate_controller_list_info` +Enumerate controller list information. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_update_** `int` +Update flag. + +**_blIncludeRecCnt_** `bool` +Whether to include record count. + +**_blIncludeAuInfo_** `bool` +Whether to include additional info (to check). + + +
+#### Returns +
+`dict[str, object] or str` +Controller list information or error details. + +
--- -### `delete_specific_camera_events` - - - ---- +### `save_cardholder_setting` +Save cardholder settings. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_arrayJson_** `str` +JSON string representing cardholder settings. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. -### `get_analytic_history` +
--- -### `get_analytic_history_by_filter` - - - ---- +### `enumerate_door_info` +Enumerate door information. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_DoorIds_** `str` +Comma-separated list of door IDs. + +
+#### Returns +
+`dict[str, object] or str` +Door information or error details. -### `unklock_selected_events` +
--- -### `set_camera_analytic_trigger` - - - ---- +### `clear_logs_surveillance_station` +Clear logs in Surveillance Station with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_filterType_** `int` +Type of filter to apply. + +**_filterEventSource_** `Any` +Event source filter. + +**_filterSource_** `int` +Source filter. + +**_filterEventSourceItem_** `str` +Event source item filter. + +**_filterTimeFrom_** `int` +Start time for filtering. + +**_filterTimeTo_** `int` +End time for filtering. + +**_filterKeyword_** `str` +Keyword to filter logs. + +**_doorIds_** `str` +Door IDs filter. + +**_eventTypes_** `str` +Event types filter. + +**_update_** `int` +Update flag. + +
+#### Returns +
+`dict[str, object] or str` +Result of the clear operation or error details. -### `flush_event_header` +
--- -### `lock_selected_events` +### `list_all_user_privilege` +List all user privileges in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Returns +
+`dict[str, object] or str` +List of user privileges or error details. +
---- +--- -### `get_analytic_event_from_rec_server` +### `manual_lock_operation` +Perform a manual lock or unlock operation on a door. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_doorId_** `int` +Door ID to operate on. + +**_operation_** `int` +Operation code (to check). + +
+#### Returns +
+`dict[str, object] or str` +Result of the operation or error details. ---- +
-### `save_analytic_settings` +--- ---- +### `save_user_door_priv_setting` +Save user door privilege settings. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_arrayJson_** `str` +JSON string representing user door privilege settings. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. -### `check_if_snapshot_exist` +
--- -### `save_snapshot_modification` - +### `list_all_logs` +List all logs in Surveillance Station with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_filterType_** `int` +Type of filter to apply. + +**_filterEventSource_** `Any` +Event source filter. + +**_filterSource_** `int` +Source filter. + +**_filterEventSourceItem_** `str` +Event source item filter. + +**_filterTimeFrom_** `int` +Start time for filtering. + +**_filterTimeTo_** `int` +End time for filtering. + +**_filterKeyword_** `str` +Keyword to filter logs. + +**_timezoneOffset_** `int` +Timezone offset. + +**_doorIds_** `str` +Door IDs filter. + +**_eventTypes_** `str` +Event types filter. + +**_update_** `int` +Update flag. + +**_blIncludeRecCnt_** `bool` +Whether to include record count. + +**_blIncludeAuInfo_** `bool` +Whether to include additional info. + +
+#### Returns +
+`dict[str, object] or str` +List of logs or error details. ---- +
-### `count_snapshot_by_category` +--- ---- +### `delete_selected_controller` +Delete selected controllers from Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated string of controller IDs to delete. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. -### `check_any_locked_snapshot` +
--- -### `unlock_snapshot_by_filter` - +### `retrieve_data_from_controller` +Retrieve data from a specific controller. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_ctrlerId_** `str` +ID of the controller to retrieve data from. + +
+#### Returns +
+`dict[str, object] or str` +Retrieved data or error details. ---- +
-### `list_snapshot_information` +--- ---- +### `block_cardholder` +Block cardholders in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Parameters +
+**_arrayJson_** `str` +JSON string representing cardholder(s) to block. + +
+#### Returns +
+`dict[str, object] or str` +Result of the block operation or error details. -### `unlock_snapshot` +
--- -### `take_snapshot` +### `get_controller_count` +Get the count of controllers by category. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler` +
+ +#### Returns +
+`dict[str, object] or str` +Controller count or error details. + +
--- -### `get_snapshot_setting_function` +### `start_controller_search` +Start searching for controllers. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler.Search` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the search operation or error details. +
---- +--- -### `delete_snapshot_by_filter` +### `get_controller_search_info` +Get information about the current controller search. + +#### Internal API +
+`SYNO.SurveillanceStation.AxisAcsCtrler.Search` +
+ +#### Parameters +
+**_pid_** `int` +Process ID of the search. + +**_offset_** `int` +Offset for paginated results. + +
+#### Returns +
+`dict[str, object] or str` +Search information or error details. ---- +
-### `get_snapshot_image` +--- ---- +### `enumerate_digital_output` +Enumerate digital output devices. + +#### Internal API +
+`SYNO.SurveillanceStation.DigitalOutput` +
+ +#### Parameters +
+**_camId_** `int` +Camera ID to filter digital outputs. + +
+#### Returns +
+`dict[str, object] or str` +List of digital outputs or error details. -### `lock_snapshot_image` +
--- -### `downld_single_snapshot` - +### `save_digital_output_parameters` +Save parameters for a digital output device. + +#### Internal API +
+`SYNO.SurveillanceStation.DigitalOutput` +
+ +#### Parameters +
+**_camId_** `int` +Camera ID. + +**_idx_** `int` +Index of the digital output. + +**_keep_setting_** `bool` +Whether to keep the current setting. + +**_normal_state_** `int` +Normal state value. + +**_trigger_state_** `bool` +Trigger state value. + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. ---- +
-### `save_new_snapshot_setting` +--- ---- +### `long_polling_digital_output_status` +Perform long polling to get the status of a digital output. + +#### Internal API +
+`SYNO.SurveillanceStation.DigitalOutput` +
+ +#### Parameters +
+**_camId_** `int` +Camera ID. + +**_idx_** `int` +Index of the digital output. + +**_keep_** `bool` +Whether to keep polling. + +**_setNormalCap_** `bool` +Set normal capability. + +**_normal_** `int` +Normal state value. + +**_trigger_** `bool` +Trigger state value. + +**_timeOut_** `int` +Timeout for polling. + +
+#### Returns +
+`dict[str, object] or str` +Status information or error details. -### `save_snapshot` +
--- -### `check_snapshot_status` - - - ---- +### `trigger_external_event` +Trigger an external event in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.ExternalEvent` +
+ +#### Parameters +
+**_eventId_** `int` +ID of the event to trigger. + +**_eventName_** `str` +Name of the event to trigger. + +
+#### Returns +
+`dict[str, object] or str` +Result of the trigger operation or error details. -### `enable_visualstation` +
--- -### `update_vs_network_config` - - - ---- +### `get_list_io_modules` +Get a list of I/O modules. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_blFromList_** `bool` +Whether to get from list. + +**_ownerDsId_** `int` +Owner device station ID. + +
+#### Returns +
+`dict[str, object] or str` +List of I/O modules or error details. -### `lock_visualstation_by_id` +
--- -### `enumerate_vs_owner_info` - - - ---- +### `get_io_port_list` +Get a list of I/O ports for a module. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_Id_** `int` +Module ID. + +**_Port_** `int` +Port number. + +**_IP_** `str` +IP address. + +**_User_** `str` +Username. + +**_Pass_** `str` +Password. + +**_Vendor_** `str` +Vendor name. + +**_Model_** `str` +Model name. + +
+#### Returns +
+`dict[str, object] or str` +List of I/O ports or error details. -### `unlock_visualstation_by_id` +
--- -### `disable_visualstation_by_id` +### `get_supported_list_io_modules` +Get a list of supported I/O module vendor models. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Returns +
+`dict[str, object] or str` +List of supported vendor models or error details. + +
--- -### `delete_specific_visualstation` - +### `save_setting_io_module` +Save or update the settings for an I/O module in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_name_** `str` +Name of the I/O module. + +**_id_** `int` +ID of the I/O module. + +**_ownerDsId_** `int` +Owner device station ID. + +**_vendor_** `str` +Vendor name of the I/O module. + +**_model_** `str` +Model name of the I/O module. + +**_ip_** `str` +IP address of the I/O module. + +**_port_** `int` +Port number for the I/O module. + +**_userName_** `str` +Username for authentication. + +**_enabled_** `bool` +Whether the I/O module is enabled. + +**_status_** `int` +Status code of the I/O module. + +**_timeServer_** `str` +Time server address. + +**_passWord_** `str` +Password for authentication. + +**_ntpEnable_** `bool` +Whether NTP is enabled. + +**_DIOdata_** `Any` +Digital I/O data (structure to be checked). + +
+#### Returns +
+`dict[str, object] or str` +Result of the save operation or error details. ---- +
-### `enumerate_layout_visualstation` +--- ---- +### `enable_io_modules` +Enable specified I/O modules. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_iomlist_** `str` +Comma-separated list of I/O module IDs to enable. + +
+#### Returns +
+`dict[str, object] or str` +Result of the enable operation or error details. -### `save_layout_information` +
--- -### `delete_layout_visualstation` - +### `disable_io_modules` +Disable specified I/O modules. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_iomlist_** `str` +Comma-separated list of I/O module IDs to disable. + +
+#### Returns +
+`dict[str, object] or str` +Result of the disable operation or error details. ---- +
-### `clear_visualstation_search_result` +--- ---- +### `delete_io_modules` +Delete specified I/O modules. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_iomlist_** `str` +Comma-separated list of I/O module IDs to delete. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. -### `get_visualstation_ip_info` +
--- -### `stop_previous_visualstation_search` - +### `test_connection_to_io_module` +Test the connection to a specified I/O module. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_id_** `int` +ID of the I/O module. + +**_port_** `str` +Port number for the I/O module. + +**_ip_** `str` +IP address of the I/O module. + +**_userName_** `str` +Username for authentication. + +**_passWord_** `str` +Password for authentication. + +**_model_** `str` +Model name of the I/O module. + +
+#### Returns +
+`dict[str, object] or str` +Result of the connection test or error details. ---- +
-### `get_visualstation_list` +--- ---- +### `get_capability_io_module` +Get the capability information for a specified I/O module. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_vendor_** `str` +Vendor name of the I/O module. + +**_model_** `str` +Model name of the I/O module. + +
+#### Returns +
+`dict[str, object] or str` +Capability information or error details. -### `get_number_of_controller` +
--- -### `get_cardholder_count` - +### `configure_io_port_setting` +Configure the port settings for a specified I/O module. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_id_** `int` +ID of the I/O module. + +**_DIOdata_** `Any` +Digital I/O data for port configuration (structure to be checked). + +
+#### Returns +
+`dict[str, object] or str` +Result of the configuration or error details. ---- +
-### `enum_all_controllers_logger` +--- ---- +### `poll_trigger_state_io_module` +Poll the trigger state of digital input (DI) ports for a specified I/O module. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_Id_** `int` +ID of the I/O module. + +**_list_** `Any` +List of DI ports to poll (structure to be checked). + +**_timeOut_** `int` +Timeout for polling operation. + +
+#### Returns +
+`dict[str, object] or str` +Polling result or error details. -### `get_cardholder_photo` +
--- -### `get_log_count` +### `poll_do_trigger_module` +Poll the trigger state of digital output (DO) ports for a specified I/O module. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_id_** `int` +ID of the I/O module. + +**_idx_** `int` +Index of the DO port. + +**_normal_** `int` +Normal state value. + +**_trigger_** `bool` +Trigger state. + +**_timeOut_** `int` +Timeout for polling operation. + +
+#### Returns +
+`dict[str, object] or str` +Polling result or error details. +
---- -### `get_cardholder_info` +--- +### `get_number_of_devices` +Get the number of I/O devices for each device station. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Returns +
+`dict[str, object] or str` +Number of devices or error details. ---- +
-### `retrieve_last_access_credential` +--- ---- +### `get_category_count_io_module` +Get the count of I/O modules by category. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule` +
+ +#### Parameters +
+**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +**_ownerDsId_** `int` +Owner device station ID. + +**_blFromList_** `bool` +Whether to get count from a list (to be checked). + +
+#### Returns +
+`dict[str, object] or str` +Count by category or error details. -### `enable_disable_controller` +
--- -### `acknowledge_all_alarm_level_log` +### `start_search_io_module` +Start searching for I/O modules. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule.Search` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the search operation or error details. + +
--- -### `modify_controller_logger_config` - +### `get_search_io_module_info` +Get information about the current I/O module search. + +#### Internal API +
+`SYNO.SurveillanceStation.IOModule.Search` +
+ +#### Parameters +
+**_pid_** `int` +Process ID of the search. + +
+#### Returns +
+`dict[str, object] or str` +Search information or error details. ---- +
-### `save_controller_settings` +--- ---- +### `get_current_camera_status` +Get the current status of specified cameras. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Status` +
+ +#### Parameters +
+**_id_list_** `str` +Comma-separated list of camera IDs. + +
+#### Returns +
+`dict[str, object] or str` +Camera status information or error details. -### `download_filtered_logs` +
--- -### `get_door_name_from_controller` - +### `enum_preset_camera_list` +Enumerate the list of presets for a specified camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Preset` +
+ +#### Parameters +
+**_cameraId_** `Any` +ID of the camera. + +
+#### Returns +
+`dict[str, object] or str` +List of camera presets or error details. ---- +
-### `test_connection_and_authentication` +--- ---- +### `get_preset_camera_capability` +Get the capability information for camera presets. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Preset` +
+ +#### Parameters +
+**_cameraId_** `int` +ID of the camera. + +
+#### Returns +
+`dict[str, object] or str` +Preset capability information or error details. -### `enumerate_controller_list_info` +
--- -### `save_cardholder_setting` - +### `record_current_camera_position` +Record the current position of a camera as a preset. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Preset` +
+ +#### Parameters +
+**_cameraId_** `int` +ID of the camera. + +**_position_** `int` +Preset position index. + +**_speed_** `int` +Speed for moving to the preset. + +**_name_** `str` +Name for the preset. + +
+#### Returns +
+`dict[str, object] or str` +Result of the record operation or error details. ---- +
-### `enumerate_door_info` +--- ---- +### `delete_list_preset_camera` +Delete specified presets from a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Preset` +
+ +#### Parameters +
+**_cameraId_** `Any` +ID of the camera. + +**_position_** `str` +Preset position(s) to delete. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. -### `clear_logs_surveillance_station` +
--- -### `list_all_user_privilege` - +### `go_specific_preset_by_given_speed` +Move a camera to a specific preset position at a given speed. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Preset` +
+ +#### Parameters +
+**_cameraId_** `Any` +ID of the camera. + +**_position_** `int` +Preset position index. + +**_speed_** `int` +Speed for moving to the preset. + +**_type_** `int` +Type of preset move (to be checked). + +
+#### Returns +
+`dict[str, object] or str` +Result of the move operation or error details. ---- +
-### `manual_lock_operation` +--- ---- +### `set_current_camera_position` +Set the current position of a camera as the home position. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Preset` +
+ +#### Parameters +
+**_cameraId_** `Any` +ID of the camera. + +**_bindPosition_** `int` +Position to bind as home. + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error details. -### `save_user_door_priv_setting` +
--- -### `list_all_logs` - +### `enum_patrol_list` +Enumerate the list of patrols for a specified camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_cam_** `Any` +Camera identifier. + +
+#### Returns +
+`dict[str, object] or str` +List of patrols or error details. ---- +
-### `delete_selected_controller` +--- ---- +### `enum_patrol_name_list` +Enumerate the list of patrol names for a specified camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_camId_** `Any` +Camera identifier. + +
+#### Returns +
+`dict[str, object] or str` +List of patrol names or error details. -### `retrieve_data_from_controller` +
--- -### `block_cardholder` - +### `load_patrol_detail` +Load the details of a specific patrol. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_id_** `int` +Patrol ID. + +
+#### Returns +
+`dict[str, object] or str` +Patrol details or error information. ---- +
-### `get_controller_count` +--- ---- +### `add_or_modify_patrol` +Add or modify a patrol for a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_camId_** `Any` +Camera identifier. + +**_id_** `int` +Patrol ID. + +**_stayTime_** `int` +Stay time at each preset. + +**_speed_** `int` +Patrol speed. + +**_name_** `str` +Name of the patrol. + +**_presetList_** `Any` +List of presets for the patrol (structure to be checked). + +
+#### Returns +
+`dict[str, object] or str` +Result of the add/modify operation or error details. -### `start_controller_search` +
--- -### `get_controller_search_result` - +### `delete_specific_patrol` +Delete a specific patrol from a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_camId_** `Any` +Camera identifier. + +**_patrolId_** `str` +Patrol ID to delete. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. ---- +
-### `enumerate_digital_output` +--- ---- +### `run_patrol` +Run a specified patrol on a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_camId_** `Any` +Camera identifier. + +**_id_** `int` +Patrol ID. + +
+#### Returns +
+`dict[str, object] or str` +Result of the run operation or error details. -### `save_digital_output_parameters` +
--- -### `long_polling_digital_output_status` +### `stop_patrol` +Stop the currently running patrol on a camera. + +#### Internal API +
+`SYNO.SurveillanceStation.PTZ.Patrol` +
+ +#### Parameters +
+**_camId_** `Any` +Camera identifier. + +
+#### Returns +
+`dict[str, object] or str` +Result of the stop operation or error details. +
---- -### `trigger_external_event` +--- +### `start_camera_search_process` +Start searching for cameras. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Search` +
+ +#### Returns +
+`dict[str, object] or str` +Result of the search operation or error details. ---- +
-### `get_list_io_modules` +--- ---- +### `get_camera_search_info` +Get information about the current camera search. + +#### Internal API +
+`SYNO.SurveillanceStation.Camera.Search` +
+ +#### Parameters +
+**_pid_** `int` +Process ID of the search. + +**_offset_** `int` +Offset for pagination. + +
+#### Returns +
+`dict[str, object] or str` +Search information or error details. -### `get_io_port_list` +
--- -### `get_supported_list_io_modules` - +### `toggle_home_mode` +Toggle the Home Mode in Surveillance Station. + +#### Internal API +
+`SYNO.SurveillanceStation.HomeMode` +
+ +#### Parameters +
+**_on_** `bool` +Whether to enable (True) or disable (False) Home Mode. + +
+#### Returns +
+`dict[str, object] or str` +Result of the toggle operation or error details. ---- +
-### `save_setting_io_module` +--- ---- +### `get_home_mode_settings` +Get the current Home Mode settings. + +#### Internal API +
+`SYNO.SurveillanceStation.HomeMode` +
+ +#### Parameters +
+**_need_mobiles_** `bool` +Whether to include mobile device information. + +
+#### Returns +
+`dict[str, object] or str` +Home Mode settings or error details. -### `enable_io_modules` +
--- -### `disable_io_modules` - +### `get_transaction_list` +Get a list of device transactions with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Device` +
+ +#### Parameters +
+**_filterIds_** `str` +Comma-separated list of transaction IDs to filter. + +**_filterDsIds_** `str` +Comma-separated list of device station IDs to filter. + +**_filterEnable_** `bool` +Filter by enabled status. + +**_filterStatus_** `int` +Filter by status code. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +
+#### Returns +
+`dict[str, object] or str` +List of transactions or error details. ---- +
-### `delete_io_modules` +--- ---- +### `get_all_transaction_list` +Get a list of all transactions with optional filters. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_filterIds_** `str` +Comma-separated list of transaction IDs to filter. + +**_dsId_** `int` +Device station ID. + +**_filterTimeFrom_** `Any` +Start time for filtering. + +**_filterStatus_** `int` +Filter by status code. + +**_filterLock_** `bool` +Filter by lock status. + +**_filterTimeTo_** `Any` +End time for filtering. + +**_filterTimeRangeIntersect_** `bool` +Whether to intersect time ranges. + +**_filterKeyword_** `str` +Keyword for filtering. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +
+#### Returns +
+`dict[str, object] or str` +List of transactions or error details. -### `test_connection_to_io_module` +
--- -### `get_capability_io_module` - +### `lock_history_records` +Lock specified history records. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_filterIds_** `str` +Comma-separated list of record IDs to lock. + +**_dsId_** `int` +Device station ID. + +**_filterStatus_** `int` +Filter by status code. + +**_filterLock_** `bool` +Filter by lock status. + +**_filterTimeFrom_** `Any` +Start time for filtering. + +**_filterTimeTo_** `Any` +End time for filtering. + +**_filterTimeRangeIntersect_** `bool` +Whether to intersect time ranges. + +**_filterKeyword_** `str` +Keyword for filtering. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +
+#### Returns +
+`dict[str, object] or str` +Result of the lock operation or error details. ---- +
-### `configure_io_port_setting` +--- ---- +### `unlock_history_records` +Unlock specified history records. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_filterIds_** `str` +Comma-separated list of record IDs to unlock. + +**_dsId_** `int` +Device station ID. + +**_filterStatus_** `int` +Filter by status code. + +**_filterLock_** `bool` +Filter by lock status. + +**_filterTimeFrom_** `Any` +Start time for filtering. + +**_filterTimeTo_** `Any` +End time for filtering. + +**_filterTimeRangeIntersect_** `bool` +Whether to intersect time ranges. + +**_filterKeyword_** `str` +Keyword for filtering. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +
+#### Returns +
+`dict[str, object] or str` +Result of the unlock operation or error details. -### `poll_trigger_state_io_module` +
--- -### `poll_do_trigger_module` - +### `delete_history_records` +Delete specified history records. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_filterIds_** `str` +Comma-separated list of record IDs to delete. + +**_dsId_** `int` +Device station ID. + +**_filterStatus_** `int` +Filter by status code. + +**_filterLock_** `bool` +Filter by lock status. + +**_filterTimeFrom_** `Any` +Start time for filtering. + +**_filterTimeTo_** `Any` +End time for filtering. + +**_filterTimeRangeIntersect_** `bool` +Whether to intersect time ranges. + +**_filterKeyword_** `str` +Keyword for filtering. + +**_start_** `int` +Start index for pagination. + +**_limit_** `int` +Maximum number of results to return. + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error details. ---- +
-### `get_number_of_devices` +--- ---- +### `start_session_with_specified_session_id` +Start a session with a specified session ID. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_device_name_** `str` +Name of the device. + +**_session_id_** `str` +Session ID to start. + +**_timeout_** `int` +Timeout for the session. + +
+#### Returns +
+`dict[str, object] or str` +Result of the start operation or error details. -### `get_category_count_io_module` +
--- -### `start_search_io_module` - +### `complete_session_with_specified_id` +Complete a session with a specified session ID. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_device_name_** `str` +Name of the device. + +**_session_id_** `str` +Session ID to complete. + +
+#### Returns +
+`dict[str, object] or str` +Result of the complete operation or error details. ---- +
-### `get_search_io_module_info` +--- ---- +### `cancel_session_with_specified_session_id` +Cancel a session with a specified session ID. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_device_name_** `str` +Name of the device. + +**_session_id_** `str` +Session ID to cancel. + +
+#### Returns +
+`dict[str, object] or str` +Result of the cancel operation or error details. -### `get_current_camera_status` +
--- -### `enum_preset_camera_list` - +### `carry_data_into_session_id` +Append data to a session with a specified session ID. + +#### Internal API +
+`SYNO.SurveillanceStation.Transactions.Transaction` +
+ +#### Parameters +
+**_device_name_** `str` +Name of the device. + +**_session_id_** `str` +Session ID to append data to. + +**_content_** `str` +Data content to append. + +
+#### Returns +
+`dict[str, object] or str` +Result of the append operation or error details. ---- +
-### `get_preset_camera_capability` +--- ---- +### `add_edit_active_vault_task` +Add or edit an active vault task for archiving. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_blCustomFolder_** `bool` +Whether to use a custom folder for storage. + +**_blLimitBySize_** `bool` +Whether to limit the archive by size. + +**_blRotateFile_** `bool` +Whether to enable file rotation. + +**_blSrcRecNoOverlap_** `bool` +Whether to avoid overlapping source recordings. + +**_blUseRecDet_** `bool` +Whether to use recording detection. + +**_camId_** `Any` +Camera ID. + +**_camInfo_** `Any` +Camera information. + +**_dayLimit_** `int` +Day limit for the archive. + +**_didCode_** `str` +Device code. + +**_dsSerial_** `str` +Device serial number. + +**_execTime_** `Any` +Execution time. + +**_hostname_** `str` +Hostname of the source server. + +**_id_** `int` +Task ID (for editing). + +**_name_** `str` +Name of the task. + +**_passwd_** `str` +Password for authentication. + +**_port_** `str` +Port number. + +**_recEndTm_** `Any` +Recording end time. + +**_recMode_** `str` +Recording mode. + +**_recSchedule_** `str` +Recording schedule. + +**_recStartTm_** `Any` +Recording start time. + +**_schedule_** `str` +Task schedule. + +**_storagePath_** `str` +Path for storage. + +**_type_** `int` +Type of the task. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `record_current_camera_position` +
--- -### `delete_list_preset_camera` - - - ---- +### `login_source_server_get_info` +Log in to the source server and retrieve information. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_port_** `str` +Port number of the source server. + +**_hostname_** `str` +Hostname of the source server. + +**_protocol_** `bool` +Protocol to use (e.g., HTTPS). + +**_username_** `str` +Username for authentication. + +**_passwd_** `str` +Password for authentication. + +**_archId_** `int` +Archive ID. + +**_didCode_** `str` +Device code. + +**_srcDsId_** `int` +Source device ID (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `go_specific_preset_by_given_speed` +
--- -### `set_current_camera_position` - - - ---- +### `delete_archive_vault_task` +Delete an archive vault task. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_id_** `int` +Task ID to delete. + +**_keepRec_** `bool` +Whether to keep the recordings. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `enum_patrol_list` +
--- -### `enum_patrol_name_list` - - - ---- - +### `list_exist_archive_vault` +List all existing archive vault tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Returns +
+`dict of str to object or str` +API response from the request. -### `load_patrol_detail` +
--- -### `add_or_modify_patrol` - - - ---- +### `enable_archive_vault_task` +Enable an archive vault task. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_id_** `int` +Task ID to enable. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `delete_specific_patrol` +
--- -### `run_patrol` - - - ---- +### `disable_archive_vault_task` +Disable an archive vault task. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_id_** `int` +Task ID to disable. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `stop_patrol` +
--- -### `start_camera_search_process` - - - ---- +### `disable_archive_vault_batchedit_task` +Batch edit (disable) archive vault tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_taskIds_** `str` +Comma-separated list of task IDs. + +**_attrs_** `Any` +Additional attributes for batch edit (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_camera_search_info` +
--- -### `toggle_home_mode` - - - ---- +### `get_batch_edit_progress` +Get the progress of a batch edit operation. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_pid_** `int` +Process ID of the batch edit operation (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_home_mode_settings` +
--- -### `get_transaction_list` - - - ---- +### `get_batchedit_proress_info` +Get detailed information about batch edit progress. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_pid_** `int` +Process ID of the batch edit operation (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_all_transaction_list` +
--- -### `lock_history_records` - - - ---- +### `clean_batchedit_progress_data` +Clean up batch edit progress data. + +#### Internal API +
+`SYNO.SurveillanceStation.Archiving.Pull` +
+ +#### Parameters +
+**_pid_** `int` +Process ID of the batch edit operation. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `unlock_history_records` +
--- -### `delete_history_records` - - +### `get_youtube_live_broadcast_setting` +Get the current YouTube Live broadcast settings. + +#### Internal API +
+`SYNO.SurveillanceStation.YoutubeLive` +
+ +#### Returns +
+`dict of str to object or str` +API response from the request. ---- +
-### `start_session_with_specified_session_id` +--- ---- +### `set_youtube_live_broadcast_info` +Set YouTube Live broadcast information. + +#### Internal API +
+`SYNO.SurveillanceStation.YoutubeLive` +
+ +#### Parameters +
+**_rtmp_path_** `str` +RTMP path for the broadcast. + +**_key_** `str` +Stream key. + +**_cam_id_** `int` +Camera ID. + +**_stream_profile_** `int` +Stream profile. + +**_live_on_** `bool` +Whether to enable live broadcast. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `complete_session_with_specified_id` +
--- -### `cancel_session_with_specified_session_id` - +### `close_youtube_live_broadcast` +Close the current YouTube Live broadcast. + +#### Internal API +
+`SYNO.SurveillanceStation.YoutubeLive` +
+ +#### Returns +
+`dict of str to object or str` +API response from the request. +
---- -### `carry_data_into_session_id` +--- +### `get_deep_video_analytic` +Get the list of deep video analytic tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA` +
+ +#### Returns +
+`dict of str to object or str` +API response from the request. ---- +
-### `add_edit_active_vault_task` +--- ---- +### `create_edit_DVA_task` +Create or edit a Deep Video Analytics (DVA) task. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA` +
+ +#### Parameters +
+**_analyze_type_** `int` +Type of analysis to perform. + +**_actFromHost_** `bool` +Whether the action is triggered from the host. + +**_name_** `str` +Name of the DVA task. + +**_camera_id_** `int` +ID of the camera associated with the task. + +**_enable_** `bool` +Whether to enable the task. + +**_enable_recording_** `bool` +Whether to enable recording for the task. + +**_pre_rec_time_** `int` +Pre-recording time in seconds. + +**_post_rec_time_** `int` +Post-recording time in seconds. + +**_event_integration_** `int` +Event integration setting. + +**_region_type_** `int` +Type of detection region. + +**_det_region_cnt_** `int` +Number of detection regions. + +**_det_region_** `int` +Detection region configuration. + +**_people_mode_** `int` +People counting mode. + +**_reset_cnt_frequency_** `int` +Frequency for resetting the counter. + +**_reset_weekday_** `int` +Weekday for counter reset. + +**_reset_date_** `int` +Date for counter reset. + +**_reset_time_minute_** `int` +Minute for counter reset. + +**_reset_time_hour_** `int` +Hour for counter reset. + +**_fence_dir_flag_** `int` +Fence direction flag. + +**_people_display_pos_** `int` +Display position for people counting. + +**_stream_profile_** `int` +Stream profile to use. + +**_people_enable_stay_max_** `bool` +Whether to enable maximum stay for people. + +**_intrusion_detect_target_** `int` +Target for intrusion detection. + +**_min_obj_size_** `Any` +Minimum object size for detection. + +**_min_obj_size_option_** `int` +Option for minimum object size. + +**_enable_min_duration_** `int` +Enable minimum duration for detection. + +**_people_display_info_** `int` +Display information for people counting. + +**_people_enter_** `int` +Number of people entering. + +**_people_stay_max_** `int` +Maximum number of people staying. + +**_people_region_** `str` +Region for people counting. + +**_people_hint_pos_** `str` +Hint position for people counting. + +**_blEditMode_** `bool` +Edit mode flag (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `login_source_server_get_info` +
--- -### `delete_archive_vault_task` - - - ---- +### `delete_dva_task` +Delete a Deep Video Analytics (DVA) task. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of DVA task IDs to delete. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `list_exist_archive_vault` +
--- -### `enable_archive_vault_task` - - - ---- +### `enable_dva_task` +Enable one or more Deep Video Analytics (DVA) tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of DVA task IDs to enable. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `disable_archive_vault_task` +
--- -### `disable_archive_vault_batchedit_task` - - - ---- +### `disable_dva_task` +Disable one or more Deep Video Analytics (DVA) tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of DVA task IDs to disable. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_batch_edit_progress` +
--- -### `get_batchedit_proress_info` - - - ---- +### `reset_counter_people_counting_task` +Reset the people counting counter for a specific DVA task. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA` +
+ +#### Parameters +
+**_taskId_** `str` +ID of the people counting task to reset. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `clean_batchedit_progress_data` +
--- -### `get_youtube_live_broadcast_setting` - - - ---- +### `get_people_enter_leave_count` +Get the count of people entering and leaving for specified DVA tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Report` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of DVA task IDs. + +**_timeStart_** `str` +Start time for the count (ISO format or timestamp). + +**_timeEnd_** `str` +End time for the count (ISO format or timestamp). + +**_timezone_** `int` +Timezone offset. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `set_youtube_live_broadcast_info` +
--- -### `close_youtube_live_broadcast` - - - ---- +### `get_people_count_of_day` +Get the people count report for a specific day. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Report` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of DVA task IDs. + +**_interval_** `int` +Interval for the report. + +**_intervalUnit_** `int` +Unit for the interval. + +**_timezone_** `int` +Timezone offset. + +**_timestamp_** `int` +Timestamp for the report. + +**_blOccupancy_** `int` +Occupancy flag (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_deep_video_analytic` +
--- -### `create_edit_DVA_task` - - - ---- +### `list_people_counting_task` +List people counting tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Recording` +
+ +#### Parameters +
+**_taskList_** `str` +Comma-separated list of task IDs to list. + +**_limit_** `int` +Limit the number of tasks returned (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `delete_dva_task` +
--- -### `enable_dva_task` - - - ---- +### `delete_recording_file_of_detection` +Delete recording files associated with detection events. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Recording` +
+ +#### Parameters +
+**_slaveDsParam_** `str` +Parameters for the slave device. + +**_deleteMethod_** `int` +Method for deletion (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `disable_dva_task` +
--- -### `reset_counter_people_counting_task` - - - ---- +### `get_info_of_task_and_frame` +Get analytic result information for a specific task and frame. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Recording` +
+ +#### Parameters +
+**_eventId_** `int` +Event ID to query. + +**_taskId_** `int` +Task ID to query. + +**_blAlertEvt_** `bool` +Alert event flag (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_people_enter_leave_count` +
--- -### `get_people_count_of_day` - +### `lock_recording_file_of_detection` +Lock recording files associated with detection events. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Recording` +
+ +#### Parameters +
+**_dsId_** `int` +Device server ID. + +**_idList_** `int` +List of recording file IDs to lock (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. ---- +
-### `list_people_counting_task` +--- ---- +### `unlock_recording_file_of_detection` +Unlock recording files associated with detection events. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.Recording` +
+ +#### Parameters +
+**_dsId_** `int` +Device server ID. + +**_idList_** `str` +List of recording file IDs to unlock (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `delete_recording_file_of_detection` +
--- -### `get_info_of_task_and_frame` +### `get_info_people_counting_task` +Get information about people counting tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Returns +
+`dict of str to object or str` +API response from the request. +
---- +--- -### `lock_recording_file_of_detection` +### `create_people_counting_task` +Create a new people counting task. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_enable_** `bool` +Whether to enable the task. + +**_task_ids_** `str` +Comma-separated list of task IDs. + +**_owner_ds_id_** `int` +Owner device server ID. + +**_name_** `str` +Name of the task. + +**_people_display_info_** `str` +Display information for people counting. + +**_people_enable_stay_max_** `int` +Enable maximum stay for people. + +**_reset_cnt_frequency_** `int` +Frequency for resetting the counter. + +**_resert_date_** `int` +Date for counter reset. + +**_resert_weekday_** `int` +Weekday for counter reset. + +**_resert_tome_hour_** `int` +Hour for counter reset. + +**_resert_tome_minute_** `int` +Minute for counter reset (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. ---- +
-### `unlock_recording_file_of_detection` +--- ---- +### `modify_setting_of_people_counting_task` +Modify the settings of an existing people counting task. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_enable_** `bool` +Whether to enable the task. + +**_id_** `int` +ID of the task to modify. + +**_task_ids_** `str` +Comma-separated list of task IDs. + +**_name_** `str` +Name of the task. + +**_people_display_info_** `int` +Display information for people counting. + +**_people_enable_max_** `int` +Enable maximum stay for people. + +**_reset_cnt_frequency_** `int` +Frequency for resetting the counter. + +**_resert_date_** `int` +Date for counter reset. + +**_resert_weekday_** `int` +Weekday for counter reset. + +**_resert_tome_hour_** `int` +Hour for counter reset. + +**_resert_tome_minute_** `int` +Minute for counter reset (not working). + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `get_info_people_counting_task` +
--- -### `create_people_counting_task` - - - ---- +### `delete_task_group` +Delete a people counting task group. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task group IDs to delete. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `modify_setting_of_people_counting_task` +
--- -### `delete_task_group` - - - ---- +### `start_count_people_task_in_groups` +Enable people counting tasks in specified groups. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task group IDs to enable. + +
+#### Returns +
+`dict of str to object or str` +API response from the request. -### `start_count_people_task_in_groups` +
@@ -2168,6 +10064,26 @@ Code Description ### `stop_count_people_task_in_groups` +Disable people counting tasks in specified groups. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task group IDs to disable. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2175,6 +10091,26 @@ Code Description ### `get_number_counting_task_group` +Get the people count for a specific task group. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_id_** `int` +ID of the task group. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2182,6 +10118,26 @@ Code Description ### `lock_recording_file_result` +Reset the people count for a specific IVA task group. + +#### Internal API +
+`SYNO.SurveillanceStation.IVA.TaskGroup` +
+ +#### Parameters +
+**_id_** `int` +ID of the IVA task group. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2189,6 +10145,32 @@ Code Description ### `get_face_list_task` +Retrieve the list of face detection tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task IDs to filter. + +**_ownerDsId_** `int` +ID of the owner DiskStation. + +**_blOnlyEnableDs_** `bool` +Whether to include only enabled DiskStations. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2196,6 +10178,119 @@ Code Description ### `create_or_edit_task` +Create or edit a face detection task. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_id_** `int` +Task ID. + +**_id_on_rec_server_** `int` +Task ID on the recording server. + +**_camera_id_** `int` +Camera ID. + +**_camera_id_on_rec_** `int` +Camera ID on the recording server. + +**_owner_ds_id_** `int` +Owner DiskStation ID. + +**_enable_** `bool` +Whether to enable the task. + +**_blEditMode_** `bool` +Edit mode flag. + +**_stream_profile_** `int` +Stream profile index. + +**_name_** `str` +Name of the task. + +**_similarity_** `float` +Similarity threshold for face recognition. + +**_allowed_color_** `int` +Color code for allowed faces. + +**_allowed_list_** `Any` +List of allowed faces. + +**_blocked_color_** `int` +Color code for blocked faces. + +**_blocked_list_** `Any` +List of blocked faces. + +**_vip_color_** `int` +Color code for VIP faces. + +**_vip_list_** `Any` +List of VIP faces. + +**_recognized_color_** `int` +Color code for recognized faces. + +**_unrecognized_color_** `int` +Color code for unrecognized faces. + +**_deleted_** `bool` +Whether the task is deleted. + +**_det_region_** `str` +Detection region. + +**_det_region_cnt_** `int` +Number of detection regions. + +**_region_type_** `int` +Type of region. + +**_display_info_** `int` +Display information. + +**_display_type_** `int` +Display type. + +**_frame_display_info_** `int` +Frame display information. + +**_enable_min_ogj_size_** `bool` +Enable minimum object size. + +**_min_ogj_size_** `float` +Minimum object size. + +**_post_rec_time_** `int` +Post-recording time in seconds. + +**_pre_rec_time_** `int` +Pre-recording time in seconds. + +**_schedule_** `str` +Task schedule. + +**_scheduleOn_** `bool` +Whether the schedule is enabled. + +**_ignore_bad_quality_** `bool` +Ignore bad quality flag (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2203,6 +10298,29 @@ Code Description ### `delete_face_task` +Delete one or more face detection tasks. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task IDs to delete. + +**_keepRecording_** `bool` +Whether to keep the associated recordings (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2210,6 +10328,26 @@ Code Description ### `enable_task_to_start_detection_recording` +Enable face detection tasks to start detection and recording. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task IDs to enable. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2217,6 +10355,26 @@ Code Description ### `disable_task_to_stop_detection_recording` +Disable face detection tasks to stop detection and recording. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of task IDs to disable. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2224,6 +10382,26 @@ Code Description ### `list_task_with_privilege_to_watch` +List face detection tasks with privilege to watch. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `int` +Task group ID to filter. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2231,6 +10409,32 @@ Code Description ### `create_face_group` +Create a new face group. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_name_** `str` +Name of the face group. + +**_description_** `str` +Description of the face group. + +**_update_registered_face_** `Any` +Registered face update information (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2238,6 +10442,26 @@ Code Description ### `disable_face_grooup` +Delete (disable) one or more face groups. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `Any` +IDs of the face groups to delete (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2245,6 +10469,35 @@ Code Description ### `edit_face_group` +Edit an existing face group. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_name_** `str` +Name of the face group. + +**_description_** `str` +Description of the face group. + +**_update_registered_face_** `Any` +Registered face update information. + +**_id_** `int` +ID of the face group to edit. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2252,6 +10505,29 @@ Code Description ### `get_face_group_list` +Retrieve the list of face groups. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_id_only_** `bool` +Whether to return only IDs. + +**_filter_** `Any` +Filter criteria (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2259,13 +10535,56 @@ Code Description ### `count_face_groups` +Count the number of face groups. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_filter_** `Any` +Filter criteria (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
--- -### `detect_faces_image` +### `detect_faces_image` +Detect faces in an image. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_image_data_** `str` +Base64-encoded image data. + +**_image_size_** `int` +Size of the image (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2273,6 +10592,53 @@ Code Description ### `create_registered_face` +Create a new registered face. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_account_** `str` +Account associated with the face. + +**_name_** `str` +Name of the person. + +**_description_** `str` +Description of the face. + +**_image_data_** `str` +Base64-encoded image data. + +**_image_size_** `int` +Size of the image. + +**_face_** `Any` +Face data. + +**_update_face_group_** `Any` +Face group update information. + +**_captured_face_id_** `int` +ID of the captured face. + +**_update_unrecognized_captured_face_** `bool` +Whether to update unrecognized captured face. + +**_append_image_data_** `bool` +Append image data flag (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2280,6 +10646,26 @@ Code Description ### `delete_registered_face` +Delete one or more registered faces. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_ids_** `Any` +IDs of the registered faces to delete (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2287,6 +10673,56 @@ Code Description ### `edit_registered_face` +Edit an existing registered face. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_id_** `int` +ID of the registered face. + +**_account_** `str` +Account associated with the face. + +**_name_** `str` +Name of the person. + +**_description_** `str` +Description of the face. + +**_image_data_** `str` +Base64-encoded image data. + +**_image_size_** `int` +Size of the image. + +**_face_** `Any` +Face data. + +**_update_face_group_** `Any` +Face group update information. + +**_captured_face_id_** `int` +ID of the captured face. + +**_update_unrecognized_captured_face_** `bool` +Whether to update unrecognized captured face. + +**_append_image_data_** `bool` +Append image data flag. + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2294,6 +10730,32 @@ Code Description ### `list_registered_face` +List registered faces. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_id_only_** `bool` +Whether to return only IDs. + +**_filter_** `Any` +Filter criteria. + +**_append_image_data_** `bool` +Whether to append image data (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2301,6 +10763,26 @@ Code Description ### `count_registered_face` +Count the number of registered faces. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_filter_** `Any` +Filter criteria (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2308,6 +10790,29 @@ Code Description ### `search_registered_face` +Search for registered faces by keywords. + +#### Internal API +
+`SYNO.SurveillanceStation.Face` +
+ +#### Parameters +
+**_keywords_** `str` +Search keywords. + +**_append_image_data_** `bool` +Whether to append image data (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response from the request. + +
@@ -2315,6 +10820,38 @@ Code Description ### `get_face_result_list` +Retrieve a list of face recognition results. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_filter_** `Any` +Filter criteria for the face results. + +**_blIncludeSnapshot_** `bool` +Whether to include snapshot images in the results. + +**_blIncludeRegisteredFace_** `bool` +Whether to include registered face information. + +**_limit_** `int` +Maximum number of results to return. + +**_slaveDsParam_** `int` +Additional parameter for slave DiskStation (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response containing the list of face recognition results. + +
@@ -2322,6 +10859,29 @@ Code Description ### `delete_face_result` +Delete face recognition results. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_filter_** `Any` +Filter criteria for selecting face results to delete. + +**_slaveDsParam_** `Any` +Additional parameter for slave DiskStation (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the delete operation. + +
@@ -2329,6 +10889,29 @@ Code Description ### `lock_face_result` +Lock face recognition results to prevent modification or deletion. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_filter_** `Any` +Filter criteria for selecting face results to lock. + +**_slaveDsParam_** `Any` +Additional parameter for slave DiskStation (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the lock operation. + +
@@ -2336,6 +10919,29 @@ Code Description ### `unlock_face_result` +Unlock face recognition results to allow modification or deletion. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_filter_** `Any` +Filter criteria for selecting face results to unlock. + +**_slaveDsParam_** `Any` +Additional parameter for slave DiskStation (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the unlock operation. + +
@@ -2343,6 +10949,26 @@ Code Description ### `get_recording_file_of_face_info` +Retrieve the recording file associated with a specific captured face. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_capturedFaceId_** `int` +ID of the captured face (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response containing the recording file information. + +
@@ -2350,6 +10976,38 @@ Code Description ### `get_recognition_face_information` +Retrieve analytic results for face recognition events. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_taskId_** `int` +ID of the face recognition task. + +**_eventId_** `int` +ID of the event. + +**_startTime_** `int` +Start time for the query (timestamp). + +**_endTime_** `int` +End time for the query (timestamp). + +**_blIncludeRegisteredFace_** `int` +Whether to include registered face information (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response containing analytic results. + +
@@ -2357,6 +11015,29 @@ Code Description ### `correct_face_result` +Correct the result of a face recognition event by associating it with a registered face. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_id_** `int` +ID of the face recognition result to correct. + +**_registered_face_id_** `int` +ID of the registered face to associate (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the correction. + +
@@ -2364,6 +11045,26 @@ Code Description ### `mark_face_result_as_stranger` +Mark one or more face recognition results as strangers. + +#### Internal API +
+`SYNO.SurveillanceStation.Face.Result` +
+ +#### Parameters +
+**_ids_** `str` +Comma-separated list of face result IDs to mark as strangers (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the operation. + +
@@ -2371,6 +11072,44 @@ Code Description ### `add_new_bookmark` +Add a new bookmark to a recording. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Bookmark` +
+ +#### Parameters +
+**_id_** `int` +ID of the bookmark. + +**_eventId_** `int` +ID of the associated event. + +**_cameraId_** `int` +ID of the camera. + +**_archId_** `int` +ID of the archive. + +**_name_** `str` +Name of the bookmark. + +**_timestamp_** `Any` +Timestamp for the bookmark. + +**_comment_** `str` +Comment for the bookmark. + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the add operation. + +
@@ -2378,6 +11117,26 @@ Code Description ### `delete_bookmark` +Delete one or more bookmarks from recordings. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Bookmark` +
+ +#### Parameters +
+**_bookmarkIds_** `Any` +IDs of the bookmarks to delete (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response indicating the result of the delete operation. + +
@@ -2385,6 +11144,38 @@ Code Description ### `list_bookmark_detail` +List details of bookmarks for recordings. + +#### Internal API +
+`SYNO.SurveillanceStation.Recording.Bookmark` +
+ +#### Parameters +
+**_offset_** `int` +Offset for pagination. + +**_limit_** `int` +Maximum number of bookmarks to return. + +**_cameraIds_** `str` +Comma-separated list of camera IDs to filter. + +**_fromTime_** `int` +Start time for filtering bookmarks (timestamp). + +**_toTime_** `int` +End time for filtering bookmarks (not working). + + +
+#### Returns +
+`dict of str to object or str` +API response containing bookmark details. + +
diff --git a/documentation/docs/apis/classes/task_scheduler.md b/documentation/docs/apis/classes/task_scheduler.md index 70863178..edac4d1c 100644 --- a/documentation/docs/apis/classes/task_scheduler.md +++ b/documentation/docs/apis/classes/task_scheduler.md @@ -11,24 +11,24 @@ title: ✅ TaskScheduler ## Overview Task Scheduler API implementation. -This API provides the functionality to get information related to the scheduler settings and current tasks. - -### Supported methods - -- **Getters** : - - Get all tasks - - Get task information - - Get task results - - Get output path for task results -- **Setters** : - - Set output path for task results - - Set task settings -- **Actions** : - - Run task - - Create task - - Delete task - - Enable task - - Disable task + This API provides the functionality to get information related to the scheduler settings and current tasks. + + ### Supported methods + + - **Getters** : + - Get all tasks + - Get task information + - Get task results + - Get output path for task results + - **Setters** : + - Set output path for task results + - Set task settings + - **Actions** : + - Run task + - Create task + - Delete task + - Enable task + - Disable task ## Methods ### `get_output_config` Retrieve tasks output configuration. @@ -44,6 +44,20 @@ Retrieve tasks output configuration. A dictionary containing a list of the tasks and information related to them.
+#### Example return +
+Click to expand +```json +{ + "data": { + "enable_output": true, + "output_path": "share/scripts_output", + "type": "esynoscheduler", + }, + "success": true +} +``` +
@@ -60,7 +74,7 @@ List all present scheduled tasks and event triggered tasks. #### Parameters
-**_sort_by_** `str, optional ` +**_sort_by_** `str` The field to sort tasks by. Defaults to `"next_trigger_time"`. Possible values: - "next_trigger_time" @@ -69,16 +83,16 @@ Possible values: - "action" - "owner" -**_sort_direction_** `str, optional ` +**_sort_direction_** `str` The sort direction. Defaults to `"ASC"`. Possible values: - "ASC" - "DESC" -**_offset_** `int, optional ` +**_offset_** `int` Task offset for pagination. Defaults to `0`. -**_limit_** `int, optional ` +**_limit_** `int` Number of tasks to retrieve. Defaults to `50`. @@ -136,7 +150,7 @@ A dictionary containing a list of the tasks and information related to them. ### `get_task_config` -Retrieve the configuration for a specific task or list of all the available services and their corresponding IDs. +Retrieve the configuration for a specific task or list all available services and their corresponding IDs. #### Internal API
@@ -145,14 +159,14 @@ Retrieve the configuration for a specific task or list of all the available serv #### Parameters
-**_task_id_** `int ` +**_task_id_** `int` The ID of the task to retrieve the configuration for. Pass `-1` to get a list of all available services with their IDs. -**_real_owner_** `str ` -The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. +**_real_owner_** `str` +The real owner of the task, usually `root`. You can double check from the result of `get_task_config()`. -**_type_** `str, optional ` -The type of task (e.g., 'service'). Pass "service" to get a list of all available services with their IDs. Defaults to `""`. +**_type_** `str` +The type of task (e.g., 'service'). Pass `"service"` to get a list of all available services with their IDs. Defaults to `""`.
@@ -224,7 +238,7 @@ Retrieve the results list for a specific task. #### Parameters
-**_task_id_** `int ` +**_task_id_** `int` The ID of the task to retrieve the results for. @@ -276,11 +290,11 @@ Configure the output settings for tasks results. #### Parameters
-**_enable_output_** `bool ` +**_enable_output_** `bool` Whether to enable result logging or not. -**_output_path_** `str, optional ` -The path where the result logs will be stored, e.g. `share/scripts_output'`. Defaults to `""`. +**_output_path_** `str` +The path where the result logs will be stored, e.g. `share/scripts_output`. Defaults to `""`.
@@ -294,10 +308,10 @@ A dictionary containing the result of the output configuration.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -315,10 +329,10 @@ Enable or disable a task. #### Parameters
-**_task_id_** `int ` +**_task_id_** `int` The ID of the task to be enabled. -**_real_owner_** `str ` +**_real_owner_** `str` The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. **_enable_** `bool` @@ -336,10 +350,10 @@ A dictionary containing the result of the task enabling.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -357,10 +371,10 @@ Run a specific task. #### Parameters
-**_task_id_** `int ` +**_task_id_** `int` The ID of the task to be run. -**_real_owner_** `str ` +**_real_owner_** `str` The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. @@ -375,10 +389,10 @@ A dictionary containing the result of the task execution.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -396,10 +410,10 @@ Delete a specific task. #### Parameters
-**_task_id_** `int ` +**_task_id_** `int` The ID of the task to be deleted. -**_real_owner_** `str ` +**_real_owner_** `str` The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. @@ -414,10 +428,10 @@ A dictionary containing the result of the task deletion.
Click to expand ```json -{ - "success": true -} -``` + { + "success": true + } + ```
@@ -426,7 +440,7 @@ A dictionary containing the result of the task deletion. ### `create_script_task` -Create a new Script task with the provided schedule and notification settings. +Create a new Script task with the provided schedule and notification settings. :::tip If the task needs to run with root privileges, please specify the owner as "root". @@ -440,28 +454,28 @@ Create a new Script task with the provided schedule and notification settings. #### Parameters
-**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_owner_** `str ` +**_owner_** `str` The task owner. If the task needs to run with root privileges, please specify the owner as "root". -**_script_** `str ` +**_script_** `str` The script to be executed. -**_enable_** `bool, optional ` +**_enable_** `bool` Whether the task should be enabled upon creation. Defaults to `True`. -**_run_frequently_** `bool, optional ` +**_run_frequently_** `bool` Determines whether the task runs on a recurring schedule (`True`) or only on a specific date (`False`). Defaults to `True`. -**_run_days_** `str, optional ` +**_run_days_** `str` Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). -**_run_date_** `str, optional ` +**_run_date_** `str` The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. -**_repeat_** `str, optional ` +**_repeat_** `str` How often the task should repeat. Defaults to `daily`. Possible values: - `daily` -> Only when 'run_frequently=True' @@ -472,35 +486,35 @@ Possible values: - `every_6_months` -> Only when 'run_frequently=False' - `yearly` -> Only when 'run_frequently=False' -**_monthly_week_** `list[str], optional ` -If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. +**_monthly_week_** `list[str]` +If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. -**_start_time_h_** `int, optional ` +**_start_time_h_** `int` Hour at which the task should start. Defaults to `0`. -**_start_time_m_** `int, optional ` +**_start_time_m_** `int` Minute at which the task should start. Defaults to `0`. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). Possible values: `0..23` The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). Posible values: `1`, `5`, `10`, `15`, `20`, `30` The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. -**_same_day_repeat_until_** `int, optional ` +**_same_day_repeat_until_** `int` Last hour of the day when the task can repeat. Defaults to `start_time_h`. -**_notify_email_** `str, optional ` +**_notify_email_** `str` Email address to send notifications to. Defaults to `""`, thus disabling the notification feature. -**_notify_only_on_error_** `bool, optional ` +**_notify_only_on_error_** `bool` If `True`, notifications are only sent when an error occurs. Defaults to `False`. @@ -515,13 +529,13 @@ A dictionary with the id of the created task.
Click to expand ```json -{ - "data": { - "id": 20 - }, - "success": true -} -``` + { + "data": { + "id": 20 + }, + "success": true + } + ```
@@ -530,14 +544,13 @@ A dictionary with the id of the created task. ### `modify_script_task` -Modify settings of a Script task. +Modify settings of a Script task. :::warning - This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. + This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. ::: - :::tip If the task needs to run with root privileges, please specify the owner as "root". @@ -554,31 +567,31 @@ Modify settings of a Script task. **_task_id_** `int` The ID of the task. -**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_owner_** `str ` +**_owner_** `str` The task owner. If the task needs to run with root privileges, please specify the owner as "root". -**_real_owner_** `str ` +**_real_owner_** `str` The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. -**_script_** `str ` +**_script_** `str` The script to be executed. -**_enable_** `bool, optional ` +**_enable_** `bool` Whether the task should be enabled upon creation. Defaults to `True`. -**_run_frequently_** `bool, optional ` +**_run_frequently_** `bool` Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. -**_run_days_** `str, optional ` +**_run_days_** `str` Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). -**_run_date_** `str, optional ` +**_run_date_** `str` The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. -**_repeat_** `str, optional ` +**_repeat_** `str` How often the task should repeat. Defaults to `'daily'`. Possible values: - `daily` -> Only when 'run_frequently=True' @@ -589,34 +602,34 @@ Possible values: - `every_6_months` -> Only when 'run_frequently=False' - `yearly` -> Only when 'run_frequently=False' -**_monthly_week_** `list[str], optional ` +**_monthly_week_** `list[str]` If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. -**_start_time_h_** `int, optional ` +**_start_time_h_** `int` Hour at which the task should start. Defaults to `0`. -**_start_time_m_** `int, optional ` +**_start_time_m_** `int` Minute at which the task should start. Defaults to `0`. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. Set to `0` to disable same-day repeats. Defaults to `0`. Possible values: `0..23` The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. Set to `0` to disable same-day repeats. Defaults to `0`. Posible values: `1`, `5`, `10`, `15`, `20`, `30` The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. -**_same_day_repeat_until_** `int, optional ` +**_same_day_repeat_until_** `int` Last hour of the day when the task can repeat. Defaults to `start_time_h`. -**_notify_email_** `str, optional ` +**_notify_email_** `str` Email address to send notifications to. Defaults to `""`, thus disabling the notification feature. -**_notify_only_on_error_** `bool, optional ` +**_notify_only_on_error_** `bool` If `True`, notifications are only sent when an error occurs. Defaults to `False`. @@ -631,13 +644,13 @@ A dictionary with the id of the created task.
Click to expand ```json -{ - "data": { - "id": 20 - }, - "success": true -} -``` + { + "data": { + "id": 20 + }, + "success": true + } + ```
@@ -655,62 +668,61 @@ Create a new Beep Control task with the provided schedule and beep duration. #### Parameters
-**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_owner_** `str ` +**_owner_** `str` The task owner. -**_beep_duration_** `int, optional ` -The amount of seconds the beep will be triggered for, in seconds. Defaults to `60`. +**_enable_** `bool` +Whether the task should be enabled upon creation. Defaults to True. -**_enable_** `bool, optional ` -Whether the task should be enabled upon creation. Defaults to `True`. +**_beep_duration_** `int` +The amount of seconds the beep will be triggered for. Defaults to 60. -**_run_frequently_** `bool, optional ` -Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. +**_run_frequently_** `bool` +Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to True. -**_run_days_** `str, optional ` -Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). +**_run_days_** `str` +Days of the week when the task should run, used if `run_frequently` is set to True, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to '0,1,2,3,4,5,6'. -**_run_date_** `str, optional ` -The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. +**_run_date_** `str` +The specific date the task should run, used if `run_frequently` is set to False. Format: yyyy/m/d (no prefix zeros). Defaults to "". -**_repeat_** `str, optional ` -How often the task should repeat. Defaults to `'daily'`. +**_repeat_** `str` +How often the task should repeat. Defaults to 'daily'. Possible values: -- `daily` -> Only when 'run_frequently=True' -- `weekly` -> Only when 'run_frequently=True' -- `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' -- `no_repeat` -> Only when 'run_frequently=False' -- `every_3_months` -> Only when 'run_frequently=False' -- `every_6_months` -> Only when 'run_frequently=False' -- `yearly` -> Only when 'run_frequently=False' + - 'daily' -> Only when run_frequently=True + - 'weekly' -> Only when run_frequently=True + - 'monthly' -> Works for both run_frequently=True and run_frequently=False + - 'no_repeat' -> Only when run_frequently=False + - 'every_3_months' -> Only when run_frequently=False + - 'every_6_months' -> Only when run_frequently=False + - 'yearly' -> Only when run_frequently=False -**_monthly_week_** `list[str], optional ` -If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. -Defaults to `[]`. +**_monthly_week_** `list[str]` +If run_frequently=True and repeat='monthly', specifies the weeks the task should run, e.g., ['first', 'third']. Defaults to []. -**_start_time_h_** `int, optional ` -Hour at which the task should start. Defaults to `0`. +**_start_time_h_** `int` +Hour at which the task should start. Defaults to 0. -**_start_time_m_** `int, optional ` -Minute at which the task should start. Defaults to `0`. +**_start_time_m_** `int` +Minute at which the task should start. Defaults to 0. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0`. -Possible values: `0..23` -The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +Set to 0 to disable same-day repeats. Defaults to 0. +Possible values: 0..23 +The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time, if both are passed, same_day_repeat_h will be prioritized. -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0`. -Posible values: `1`, `5`, `10`, `15`, `20`, `30` -The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +Set to 0 to disable same-day repeats. Defaults to 0. +Possible values: 1, 5, 10, 15, 20, 30 +The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time, if both are passed, same_day_repeat_h will be prioritized. -**_same_day_repeat_until_** `int, optional ` -Last hour of the day when the task can repeat. Defaults to `start_time_h`. +**_same_day_repeat_until_** `int` +Last hour of the day when the task can repeat. Defaults to start_time_h.
@@ -739,13 +751,8 @@ A dictionary with the id of the created task. ### `modify_beep_control_task` -Modify settings of a Beep Control task. -:::warning - - This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. - -::: - +Modify settings of a Beep Control task. + #### Internal API
`SYNO.Core.TaskScheduler` @@ -753,49 +760,52 @@ Modify settings of a Beep Control task. #### Parameters
-**_task_name_** `str ` +**_task_id_** `int` +The ID of the task to modify. + +**_task_name_** `str` The name of the task. -**_real_owner_** `str ` +**_real_owner_** `str` The task owner. -**_beep_duration_** `int, optional ` -The amount of seconds the beep will be triggered for, in seconds. Defaults to `60`. +**_enable_** `bool` +Whether the task should be enabled upon modification. Defaults to `True`. -**_enable_** `bool, optional ` -Whether the task should be enabled upon creation. Defaults to `True`. +**_beep_duration_** `int` +The amount of seconds the beep will be triggered for, in seconds. Defaults to `60`. -**_run_frequently_** `bool, optional ` -Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. +**_run_frequently_** `bool` +Determines whether the task runs on a recurring schedule (`True`) or only on a specific date (`False`). Defaults to `True`. -**_run_days_** `str, optional ` +**_run_days_** `str` Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). -**_run_date_** `str, optional ` +**_run_date_** `str` The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. -**_repeat_** `str, optional ` +**_repeat_** `str` How often the task should repeat. Defaults to `'daily'`. Possible values: -- `daily` -> Only when 'run_frequently=True' -- `weekly` -> Only when 'run_frequently=True' -- `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' -- `no_repeat` -> Only when 'run_frequently=False' -- `every_3_months` -> Only when 'run_frequently=False' -- `every_6_months` -> Only when 'run_frequently=False' -- `yearly` -> Only when 'run_frequently=False' - -**_monthly_week_** `list[str], optional ` + - `daily` -> Only when `run_frequently=True` + - `weekly` -> Only when `run_frequently=True` + - `monthly` -> Works for both `run_frequently=True` and `run_frequently=False` + - `no_repeat` -> Only when `run_frequently=False` + - `every_3_months` -> Only when `run_frequently=False` + - `every_6_months` -> Only when `run_frequently=False` + - `yearly` -> Only when `run_frequently=False` + +**_monthly_week_** `list[str]` If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. -**_start_time_h_** `int, optional ` +**_start_time_h_** `int` Hour at which the task should start. Defaults to `0`. -**_start_time_m_** `int, optional ` +**_start_time_m_** `int` Minute at which the task should start. Defaults to `0`. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. Set to `0` to disable same-day repeats. Defaults to `0`. Possible values: `0..23` :::info @@ -805,10 +815,10 @@ Possible values: `0..23` ::: -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. Set to `0` to disable same-day repeats. Defaults to `0`. -Posible values: `1`, `5`, `10`, `15`, `20`, `30` +Possible values: `1`, `5`, `10`, `15`, `20`, `30` :::info The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. @@ -816,7 +826,7 @@ Posible values: `1`, `5`, `10`, `15`, `20`, `30` ::: -**_same_day_repeat_until_** `int, optional ` +**_same_day_repeat_until_** `int` Last hour of the day when the task can repeat. Defaults to `start_time_h`. @@ -824,7 +834,7 @@ Last hour of the day when the task can repeat. Defaults to `start_time_h`. #### Returns
`dict[str, object]` -A dictionary with the id of the created task. +A dictionary with the id of the modified task.
#### Example return @@ -855,15 +865,15 @@ Create a new Service Control task with the provided schedule and services to sta #### Parameters
-**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_owner_** `str ` +**_owner_** `str` The task owner. -**_services (list)_** `` +**_services_** `list[dict]` A list containing the services and their type to be influenced by the specified action (start / stop). -To get a list of all the available services and their corresponding IDs, call `get_task_config(task_id=-1, real_owner=your_username, type='service')`. +To get a list of all the available services and their corresponding IDs, call `get_task_config(task_id=-1, real_owner=your_username, type='service')`. E.g.: ```python [ @@ -873,23 +883,23 @@ E.g.: ] ``` -**_action_** `str ` +**_action_** `str` The action to apply to the services. Either `'start'` or `'stop'`. -**_enable_** `bool, optional ` +**_enable_** `bool` Whether the task should be enabled upon creation. Defaults to `True`. -**_run_frequently_** `bool, optional ` +**_run_frequently_** `bool` Determines whether the task runs on a recurring schedule (`True`) or only on a specific date (`False`). Defaults to `True`. -**_run_days_** `str, optional ` +**_run_days_** `str` Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). -**_run_date_** `str, optional ` +**_run_date_** `str` The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. -**_repeat_** `str, optional ` -How often the task should repeat. Defaults to `'daily'`. +**_repeat_** `str` +How often the task should repeat. Defaults to `'daily'`. Possible values: - `daily` -> Only when 'run_frequently=True' - `weekly` -> Only when 'run_frequently=True' @@ -899,18 +909,18 @@ Possible values: - `every_6_months` -> Only when 'run_frequently=False' - `yearly` -> Only when 'run_frequently=False' -**_monthly_week_** `list[str], optional ` +**_monthly_week_** `list[str]` If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. -**_start_time_h_** `int, optional ` +**_start_time_h_** `int` Hour at which the task should start. Defaults to `0`. -**_start_time_m_** `int, optional ` +**_start_time_m_** `int` Minute at which the task should start. Defaults to `0`. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0`. +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0`. Possible values: `0..23` :::info @@ -919,9 +929,9 @@ Possible values: `0..23` ::: -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0`. +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0`. Posible values: `1`, `5`, `10`, `15`, `20`, `30` :::info @@ -930,7 +940,7 @@ Posible values: `1`, `5`, `10`, `15`, `20`, `30` ::: -**_same_day_repeat_until_** `int, optional ` +**_same_day_repeat_until_** `int` Last hour of the day when the task can repeat. Defaults to `start_time_h`. @@ -945,13 +955,13 @@ A dictionary with the id of the created task.
Click to expand ```json -{ - "data": { - "id": 20 - }, - "success": true -} -``` + { + "data": { + "id": 20 + }, + "success": true + } + ```
@@ -960,7 +970,7 @@ A dictionary with the id of the created task. ### `modify_service_control_task` -Modify settings of a Service Control task. +Modify settings of a Service Control task. :::warning This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. @@ -977,15 +987,15 @@ Modify settings of a Service Control task. **_task_id_** `int` The ID of the task. -**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_real_owner_** `str ` +**_real_owner_** `str` The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. -**_services (list)_** `` +**_services_** `list[dict]` A list containing the services and their type to be influenced by the specified action (start / stop). -To get a list of all the available services and their corresponding IDs, call `get_task_config(task_id=-1, real_owner=your_username, type='service')`. +To get a list of all the available services and their corresponding IDs, call `get_task_config(task_id=-1, real_owner=your_username, type='service')`. E.g.: ```python [ @@ -995,25 +1005,25 @@ E.g.: ] ``` -**_action_** `str ` +**_action_** `str` The action to apply to the services. Either `'start'` or `'stop'`. -**_enable_** `bool, optional ` +**_enable_** `bool` Whether the task should be enabled upon creation. Defaults to `True`. -**_run_frequently_** `bool, optional ` +**_run_frequently_** `bool` Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. -**_run_days_** `str, optional ` -Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list +**_run_days_** `str` +Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). -**_run_date_** `str, optional ` -The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). +**_run_date_** `str` +The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. -**_repeat_** `str, optional ` -How often the task should repeat. Defaults to `'daily'`. +**_repeat_** `str` +How often the task should repeat. Defaults to `'daily'`. Possible values: - `daily` -> Only when 'run_frequently=True' - `weekly` -> Only when 'run_frequently=True' @@ -1023,19 +1033,19 @@ Possible values: - `every_6_months` -> Only when 'run_frequently=False' - `yearly` -> Only when 'run_frequently=False' -**_monthly_week_** `list[str], optional ` -If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. +**_monthly_week_** `list[str]` +If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to `[]`. -**_start_time_h_** `int, optional ` +**_start_time_h_** `int` Hour at which the task should start. Defaults to `0`. -**_start_time_m_** `int, optional ` +**_start_time_m_** `int` Minute at which the task should start. Defaults to `0`. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0`. +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0`. Possible values: `0..23` :::info @@ -1044,9 +1054,9 @@ Possible values: `0..23` ::: -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0`. +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0`. Posible values: `1`, `5`, `10`, `15`, `20`, `30` :::info @@ -1055,7 +1065,7 @@ Posible values: `1`, `5`, `10`, `15`, `20`, `30` ::: -**_same_day_repeat_until_** `int, optional ` +**_same_day_repeat_until_** `int` Last hour of the day when the task can repeat. Defaults to `start_time_h`. @@ -1070,13 +1080,13 @@ A dictionary with the id of the created task.
Click to expand ```json -{ - "data": { - "id": 20 - }, - "success": true -} -``` + { + "data": { + "id": 20 + }, + "success": true + } + ```
@@ -1085,7 +1095,7 @@ A dictionary with the id of the created task. ### `create_recycle_bin_task` -Create a new Recycle Bin Control task with the provided schedule and services to start/stop. +Create a new Recycle Bin Control task with the provided schedule and policy. #### Internal API
@@ -1094,86 +1104,84 @@ Create a new Recycle Bin Control task with the provided schedule and services to #### Parameters
-**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_owner_** `str ` +**_owner_** `str` The task owner. -**_clean_all_shares_** `bool ` -Whether the task should empty the recycle bins of all shares or not, if set to `False`, shares must be specified. +**_clean_all_shares_** `bool` +Whether the task should empty the recycle bins of all shares. If set to False, `shares` must be specified. -**_shares_** `list[str]` -List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to `[]`. - -**_policy (dict)_** `` -Determines what files will be deleted from the recycle bins. +**_policy_** `dict` +Determines what files will be deleted from the recycle bins. Possible values are: -- `{"policy": "clean_all"}` -> Clean all files -- `{"policy": "time", "time": int}` -> Clean all files older than X days, days being possed as value for "time" key. -- `{"policy": "size", "size": int , "sort_type": int}` -> Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". -Possible values for "sort_type" are: -- `0` -> Delete bigger files first -- `1` -> Delete older files first - -**_enable_** `bool, optional ` -Whether the task should be enabled upon creation. Defaults to `True`. - -**_run_frequently_** `bool, optional ` -Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. - -**_run_days_** `str, optional ` -Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). + - \{"policy": "clean_all"\}: Clean all files. + - \{"policy": "time", "time": int\}: Clean all files older than X days, where X is the value for "time". + - \{"policy": "size", "size": int, "sort_type": int\}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". +Possible values for "sort_type": + - 0: Delete bigger files first. + - 1: Delete older files first. -**_run_date_** `str, optional ` -The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). -Defaults to `""`. +**_shares_** `list[str]` +List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to []. -**_repeat_** `str, optional ` -How often the task should repeat. Defaults to `'daily'`. -Possible values: -- `daily` -> Only when 'run_frequently=True' -- `weekly` -> Only when 'run_frequently=True' -- `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' -- `no_repeat` -> Only when 'run_frequently=False' -- `every_3_months` -> Only when 'run_frequently=False' -- `every_6_months` -> Only when 'run_frequently=False' -- `yearly` -> Only when 'run_frequently=False' +**_enable_** `bool` +Whether the task should be enabled upon creation. Defaults to True. -**_monthly_week_** `list[str], optional ` -If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. -Defaults to `[]`. +**_run_frequently_** `bool` +Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to True. -**_start_time_h_** `int, optional ` -Hour at which the task should start. Defaults to `0`. +**_run_days_** `str` +Days of the week when the task should run, used if `run_frequently` is True, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to '0,1,2,3,4,5,6'. -**_start_time_m_** `int, optional ` -Minute at which the task should start. Defaults to `0`. +**_run_date_** `str` +The specific date the task should run, used if `run_frequently` is False. Format: yyyy/m/d (no prefix zeros). Defaults to "". -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). -Possible values: `0..23` -:::info +**_repeat_** `str` +How often the task should repeat. Defaults to 'daily'. +Possible values: + - 'daily' (only when run_frequently=True) + - 'weekly' (only when run_frequently=True) + - 'monthly' (works for both run_frequently=True and run_frequently=False) + - 'no_repeat' (only when run_frequently=False) + - 'every_3_months' (only when run_frequently=False) + - 'every_6_months' (only when run_frequently=False) + - 'yearly' (only when run_frequently=False) + +**_monthly_week_** `list[str]` +If run_frequently=True and repeat='monthly', specifies the weeks the task should run, e.g., ['first', 'third']. Defaults to []. + +**_start_time_h_** `int` +Hour at which the task should start. Defaults to 0. + +**_start_time_m_** `int` +Minute at which the task should start. Defaults to 0. + +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +Set to 0 to disable same-day repeats. Defaults to 0. +Possible values: 0..23 +:::note - The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. + The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time; if both are passed, same_day_repeat_h will be prioritized. ::: -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). -Posible values: `1`, `5`, `10`, `15`, `20`, `30` -:::info +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +Set to 0 to disable same-day repeats. Defaults to 0. +Possible values: 1, 5, 10, 15, 20, 30 +:::note - The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. + The args same_day_repeat_h and same_day_repeat_m cannot be used at the same time; if both are passed, same_day_repeat_h will be prioritized. ::: -**_same_day_repeat_until_** `int, optional ` -Last hour of the day when the task can repeat. Defaults to `start_time_h`. +**_same_day_repeat_until_** `int` +Last hour of the day when the task can repeat. Defaults to start_time_h.
@@ -1181,11 +1189,8 @@ Last hour of the day when the task can repeat. Defaults to `start_time_h`.
`dict[str, object]` A dictionary with the id of the created task. - -
-#### Example return -
-Click to expand +Examples +-------- ```json { "data": { @@ -1193,7 +1198,20 @@ A dictionary with the id of the created task. }, "success": true } -``` +``` + +
+#### Example return +
+Click to expand +```json + { + "data": { + "id": 20 + }, + "success": true + } + ```
@@ -1202,13 +1220,8 @@ A dictionary with the id of the created task. ### `modify_recycle_bin_task` -Modify settings of a Recycle Bin Control task. -:::warning - - This method overwrites all the settings of the task, so if you only want to change one setting, you can fetch the current task configuration with `get_task_config()` and pass all the settings to this method. - -::: - +Modify settings of a Recycle Bin Control task. + #### Internal API
`SYNO.Core.TaskScheduler` @@ -1219,65 +1232,63 @@ Modify settings of a Recycle Bin Control task. **_task_id_** `int` The ID of the task. -**_task_name_** `str ` +**_task_name_** `str` The name of the task. -**_real_owner_** `str ` -The task real owner, usually it is `root`, you can double check from the result of `get_task_config()`. +**_real_owner_** `str` +The task real owner, usually it is `root`. You can double check from the result of `get_task_config()`. + +**_clean_all_shares_** `bool` +Whether the task should empty the recycle bins of all shares. If set to `False`, `shares` must be specified. -**_clean_all_shares_** `bool ` -Whether the task should empty the recycle bins of all shares or not, if set to `False`, shares must be specified. +**_policy_** `dict` +Determines what files will be deleted from the recycle bins. +Possible values are: + - \{"policy": "clean_all"\}: Clean all files. + - \{"policy": "time", "time": int\}: Clean all files older than X days, where X is the value for "time". + - \{"policy": "size", "size": int, "sort_type": int\}: Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". +Possible values for "sort_type": + - 0: Delete bigger files first. + - 1: Delete older files first. **_shares_** `list[str]` -List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to `[]`. +List of shares of which to clean the recycle bins. Pass only the name of the shares without slashes, e.g. `shares=['photo', 'web']`. Defaults to []. -**_policy (dict)_** `` -Determines what files will be deleted from the recycle bins. -Possible values are: -- `{"policy": "clean_all"}` -> Clean all files -- `{"policy": "time", "time": int}` -> Clean all files older than X days, days being possed as value for "time" key. -- `{"policy": "size", "size": int , "sort_type": int}` -> Clean files until recycle bin size reaches given "size" in MB, delete files by "sort_type". -Possible values for "sort_type" are: -- `0` -> Delete bigger files first -- `1` -> Delete older files first - -**_enable_** `bool, optional ` -Whether the task should be enabled upon creation. Defaults to `True`. +**_enable_** `bool` +Whether the task should be enabled upon modification. Defaults to `True`. -**_run_frequently_** `bool, optional ` +**_run_frequently_** `bool` Determines whether the task runs on a recurring schedule (True) or only on a specific date (False). Defaults to `True`. -**_run_days_** `str, optional ` -Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'` (Daily). +**_run_days_** `str` +Days of the week when the task should run, used if `run_frequently` is set to `True`, specified as a comma-separated list (e.g., '0,1,2' for Sunday, Monday, Tuesday). Defaults to `'0,1,2,3,4,5,6'`. -**_run_date_** `str, optional ` -The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). -Defaults to `""`. +**_run_date_** `str` +The specific date the task should run, used if `run_frequently` is set to `False`. Format: `yyyy/m/d` (no prefix zeros). Defaults to `""`. -**_repeat_** `str, optional ` +**_repeat_** `str` How often the task should repeat. Defaults to `'daily'`. Possible values: -- `daily` -> Only when 'run_frequently=True' -- `weekly` -> Only when 'run_frequently=True' -- `monthly` -> Works for both 'run_frequently=True' and 'run_frequently=False' -- `no_repeat` -> Only when 'run_frequently=False' -- `every_3_months` -> Only when 'run_frequently=False' -- `every_6_months` -> Only when 'run_frequently=False' -- `yearly` -> Only when 'run_frequently=False' - -**_monthly_week_** `list[str], optional ` -If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. -Defaults to `[]`. - -**_start_time_h_** `int, optional ` + - `daily` (only when run_frequently=True) + - `weekly` (only when run_frequently=True) + - `monthly` (works for both run_frequently=True and run_frequently=False) + - `no_repeat` (only when run_frequently=False) + - `every_3_months` (only when run_frequently=False) + - `every_6_months` (only when run_frequently=False) + - `yearly` (only when run_frequently=False) + +**_monthly_week_** `list[str]` +If `run_frequently=True` and `repeat='monthly'`, specifies the weeks the task should run, e.g., `['first', 'third']`. Defaults to []. + +**_start_time_h_** `int` Hour at which the task should start. Defaults to `0`. -**_start_time_m_** `int, optional ` +**_start_time_m_** `int` Minute at which the task should start. Defaults to `0`. -**_same_day_repeat_h_** `int, optional ` -Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). +**_same_day_repeat_h_** `int` +Number of hours between repeated executions on the same day (run every x hours), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0`. Possible values: `0..23` :::info @@ -1286,10 +1297,10 @@ Possible values: `0..23` ::: -**_same_day_repeat_m_** `int, optional ` -Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. -Set to `0` to disable same-day repeats. Defaults to `0` (disable same day repeat). -Posible values: `1`, `5`, `10`, `15`, `20`, `30` +**_same_day_repeat_m_** `int` +Number of minutes between repeated executions on the same day (run every x minutes), if "Continue running within the same day" is desired. +Set to `0` to disable same-day repeats. Defaults to `0`. +Possible values: `1`, `5`, `10`, `15`, `20`, `30` :::info The args `same_day_repeat_h` and `same_day_repeat_m` cannot be used at the same time, if both are passed, `same_day_repeat_h` will be prioritized. @@ -1297,7 +1308,7 @@ Posible values: `1`, `5`, `10`, `15`, `20`, `30` ::: -**_same_day_repeat_until_** `int, optional ` +**_same_day_repeat_until_** `int` Last hour of the day when the task can repeat. Defaults to `start_time_h`. @@ -1305,7 +1316,7 @@ Last hour of the day when the task can repeat. Defaults to `start_time_h`. #### Returns
`dict[str, object]` -A dictionary with the id of the created task. +A dictionary with the id of the modified task.
#### Example return diff --git a/documentation/docs/apis/classes/universal_search.md b/documentation/docs/apis/classes/universal_search.md index fb1b5917..328ab16a 100644 --- a/documentation/docs/apis/classes/universal_search.md +++ b/documentation/docs/apis/classes/universal_search.md @@ -14,9 +14,31 @@ This API is not documented yet. ::: ## Overview +API wrapper for Synology Universal Search. +Provides methods to perform keyword-based searches using Synology's Universal Search API. ## Methods ### `search` +Search for files and metadata matching the given keyword. + +#### Internal API +
+`SYNO.Finder.FileIndexing.Search` +
+ +#### Parameters +
+**_keyword_** `str` +The search keyword. + + +
+#### Returns +
+`dict[str, object] or str` +Search results as a dictionary, or a string with error details. + +
diff --git a/documentation/docs/apis/classes/usb_copy.md b/documentation/docs/apis/classes/usb_copy.md index 2ccbab77..06214515 100644 --- a/documentation/docs/apis/classes/usb_copy.md +++ b/documentation/docs/apis/classes/usb_copy.md @@ -9,17 +9,17 @@ title: ✅ USBCopy # USBCopy ## Overview -USB Copy Implementation. +USB Copy API wrapper for Synology NAS. -### Supported methods +Methods +------- +**Getters** : + - Get package settings + - Get package logs + - Get task settings - - **Getters** : - - Get package settings - - Get package logs - - Get task settings - - - **Actions** : - - Enable / Disable task +**Actions** : + - Enable / Disable task ## Methods ### `get_package_settings` Retrieve package settings. @@ -32,21 +32,21 @@ Retrieve package settings. #### Returns
`dict[str, object]` -Parsed JSON into `dict` +Parsed JSON into a dictionary.
#### Example return
Click to expand ```python -{ - "data" : { - "beep_on_task_start_end" : True, - "log_rotate_count" : 100000, - "repo_volume_path" : "/volume2" - }, - "success" : True -} + { + "data": { + "beep_on_task_start_end": True, + "log_rotate_count": 100000, + "repo_volume_path": "/volume2" + }, + "success": True + } ```
@@ -66,39 +66,39 @@ Retrieve package logs. #### Parameters
**_offset_** `int` -Defaults to `0`. +Offset for logs. Defaults to 0. **_limit_** `int` -Defaults to `200`. +Maximum number of logs to retrieve. Defaults to 200.
#### Returns
`dict[str, object]` -Parsed response JSON into `dict` +Parsed response JSON into a dictionary.
#### Example return
Click to expand ```python -{ - "data" : { - "count" : 1, - "log_list" : [ - { - "description_id" : 101, - "description_parameter" : "["asdf"]", - "error" : 0, - "log_type" : 1, - "task_id" : 2, - "timestamp" : 1738341351 - }, - ] - }, - "success" : True -} + { + "data": { + "count": 1, + "log_list": [ + { + "description_id": 101, + "description_parameter": "["asdf"]", + "error": 0, + "log_type": 1, + "task_id": 2, + "timestamp": 1738341351 + } + ] + }, + "success": True + } ```
@@ -108,7 +108,7 @@ Parsed response JSON into `dict` ### `get_task_settings` -Retrieve task settings +Retrieve task settings. #### Internal API
@@ -118,54 +118,54 @@ Retrieve task settings #### Parameters
**_task_id_** `int` -Task ID to retrieve info for +Task ID to retrieve info for.
#### Returns
`dict[str, object]` -Parsed response JSON into `dict` +Parsed response JSON into a dictionary.
#### Example return
Click to expand ```python -{ - "data" : { - "task" : { - "conflict_policy" : "rename", - "copy_file_path" : "", - "copy_strategy" : "versioning", - "default_device_port" : "NA", - "destination_path" : "[USB]", - "eject_when_task_done" : True, - "enable_rotation" : False, - "error_code" : 0, - "id" : 2, - "is_default_task" : False, - "is_ds_mounted" : False, - "is_task_runnable" : False, - "is_usb_mounted" : False, - "latest_finish_time" : 1738341351, - "max_version_count" : 256, - "name" : "asdf", - "next_run_time" : "N/A", - "not_keep_dir_structure" : False, - "remove_src_file" : False, - "rename_photo_video" : False, - "rotation_policy" : "oldest_version", - "run_when_plug_in" : False, - "schedule_id" : 13, - "smart_create_date_dir" : False, - "source_path" : "/music", - "status" : "unmounted", - "type" : "export_general" - } - }, - "success" : True -} + { + "data": { + "task": { + "conflict_policy": "rename", + "copy_file_path": "", + "copy_strategy": "versioning", + "default_device_port": "NA", + "destination_path": "[USB]", + "eject_when_task_done": True, + "enable_rotation": False, + "error_code": 0, + "id": 2, + "is_default_task": False, + "is_ds_mounted": False, + "is_task_runnable": False, + "is_usb_mounted": False, + "latest_finish_time": 1738341351, + "max_version_count": 256, + "name": "asdf", + "next_run_time": "N/A", + "not_keep_dir_structure": False, + "remove_src_file": False, + "rename_photo_video": False, + "rotation_policy": "oldest_version", + "run_when_plug_in": False, + "schedule_id": 13, + "smart_create_date_dir": False, + "source_path": "/music", + "status": "unmounted", + "type": "export_general" + } + }, + "success": True + } ```
@@ -175,7 +175,7 @@ Parsed response JSON into `dict` ### `toggle_task` -Enable or disable USB Copy task +Enable or disable a USB Copy task. #### Internal API
@@ -188,23 +188,23 @@ Enable or disable USB Copy task Task ID to apply the setting to. **_enable_** `bool` -Whether to enable (`True`) or disable (`False`) USB Copy. Defaults to `True`. +Whether to enable (True) or disable (False) the USB Copy task. Defaults to True.
#### Returns
`dict[str, object]` -Parsed response JSON into `dict` +Parsed response JSON into a dictionary.
#### Example return
Click to expand ```python -{ - "success": True -} + { + "success": True + } ```
diff --git a/documentation/docs/apis/classes/virtualization.md b/documentation/docs/apis/classes/virtualization.md index b1a462af..06f255c8 100644 --- a/documentation/docs/apis/classes/virtualization.md +++ b/documentation/docs/apis/classes/virtualization.md @@ -14,9 +14,45 @@ This API is not documented yet. ::: ## Overview - +API wrapper for Synology Virtual Machine Manager. + +Provides methods to manage tasks, networks, storage, hosts, VMs, and images. + +Parameters +---------- +ip_address : str + IP address of the Synology NAS. +port : str + Port number to connect to. +username : str + DSM username. +password : str + DSM password. +secure : bool, optional + Use HTTPS if True. Default is False. +cert_verify : bool, optional + Verify SSL certificate if True. Default is False. +dsm_version : int, optional + DSM version. Default is 7. +debug : bool, optional + Enable debug mode. Default is True. +otp_code : str, optional + One-time password for 2FA, if required. ## Methods ### `get_task_list` +Get the list of virtualization tasks. + +#### Internal API +
+`SYNO.Virtualization.API.Task.Info` +
+ +#### Returns +
+`list of str` +List of task IDs. + +
@@ -24,6 +60,26 @@ This API is not documented yet. ### `clear_task` +Clear a specific task by its ID. + +#### Internal API +
+`SYNO.Virtualization.API.Task.Info` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID to clear. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the clear operation or error message. + +
@@ -31,6 +87,26 @@ This API is not documented yet. ### `get_task_info` +Get information about a specific task. + +#### Internal API +
+`SYNO.Virtualization.API.Task.Info` +
+ +#### Parameters +
+**_taskid_** `str` +Task ID to retrieve information for. + + +
+#### Returns +
+`dict[str, object] or str` +Task information or error message. + +
@@ -38,6 +114,19 @@ This API is not documented yet. ### `get_network_group_list` +Get the list of network groups. + +#### Internal API +
+`SYNO.Virtualization.API.Network` +
+ +#### Returns +
+`list of dict` +List of network group information. + +
@@ -45,6 +134,19 @@ This API is not documented yet. ### `get_storage_operation` +Get the list of storage operations. + +#### Internal API +
+`SYNO.Virtualization.API.Storage` +
+ +#### Returns +
+`list of str` +List of storage operation information. + +
@@ -52,6 +154,19 @@ This API is not documented yet. ### `get_host_operation` +Get the list of host operations. + +#### Internal API +
+`SYNO.Virtualization.API.Host` +
+ +#### Returns +
+`list of str` +List of host operation information. + +
@@ -59,6 +174,26 @@ This API is not documented yet. ### `get_vm_operation` +Get the list of virtual machines. + +#### Internal API +
+`SYNO.Virtualization.API.Guest` +
+ +#### Parameters +
+**_additional_** `bool` +Whether to include additional information. Default is False. + + +
+#### Returns +
+`list of dict` +List of VM information. + +
@@ -66,6 +201,32 @@ This API is not documented yet. ### `get_specific_vm_info` +Get information about a specific virtual machine. + +#### Internal API +
+`SYNO.Virtualization.API.Guest` +
+ +#### Parameters +
+**_additional_** `str or list of str` +Additional fields to include. + +**_guest_id_** `str` +Guest VM ID. + +**_guest_name_** `str` +Guest VM name. + + +
+#### Returns +
+`dict[str, object] or str` +VM information or error message. + +
@@ -73,6 +234,44 @@ This API is not documented yet. ### `set_vm_property` +Set properties for a virtual machine. + +#### Internal API +
+`SYNO.Virtualization.API.Guest` +
+ +#### Parameters +
+**_guest_id_** `str` +Guest VM ID. + +**_guest_name_** `str` +Guest VM name. + +**_autorun_** `int` +Autorun setting (0: off, 1: last state, 2: on). + +**_description_** `str` +VM description. + +**_new_guest_name_** `str` +New VM name. + +**_vcpu_num_** `int` +Number of virtual CPUs. + +**_vram_size_** `int` +RAM size in MB. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the set operation or error message. + +
@@ -80,6 +279,29 @@ This API is not documented yet. ### `delete_vm` +Delete a virtual machine. + +#### Internal API +
+`SYNO.Virtualization.API.Guest` +
+ +#### Parameters +
+**_guest_id_** `str` +Guest VM ID. + +**_guest_name_** `str` +Guest VM name. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error message. + +
@@ -87,6 +309,35 @@ This API is not documented yet. ### `vm_power_on` +Power on a virtual machine. + +#### Internal API +
+`SYNO.Virtualization.API.Guest.Action` +
+ +#### Parameters +
+**_guest_id_** `str` +Guest VM ID. + +**_guest_name_** `str` +Guest VM name. + +**_host_id_** `str` +Host ID. + +**_host_name_** `str` +Host name. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the power on operation or error message. + +
@@ -94,6 +345,29 @@ This API is not documented yet. ### `vm_force_power_off` +Force power off a virtual machine. + +#### Internal API +
+`SYNO.Virtualization.API.Guest.Action` +
+ +#### Parameters +
+**_guest_id_** `str` +Guest VM ID. + +**_guest_name_** `str` +Guest VM name. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the power off operation or error message. + +
@@ -101,6 +375,29 @@ This API is not documented yet. ### `vm_shut_down` +Shut down a virtual machine. + +#### Internal API +
+`SYNO.Virtualization.API.Guest.Action` +
+ +#### Parameters +
+**_guest_id_** `str` +Guest VM ID. + +**_guest_name_** `str` +Guest VM name. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the shutdown operation or error message. + +
@@ -108,6 +405,19 @@ This API is not documented yet. ### `get_images_list` +Get the list of VM images. + +#### Internal API +
+`SYNO.Virtualization.API.Guest.Image` +
+ +#### Returns +
+`dict[str, object]` +Dictionary containing image information. + +
@@ -115,6 +425,29 @@ This API is not documented yet. ### `delete_image` +Delete a VM image. + +#### Internal API +
+`SYNO.Virtualization.API.Guest.Image` +
+ +#### Parameters +
+**_image_id_** `str` +Image ID. + +**_image_name_** `str` +Image name. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the delete operation or error message. + +
@@ -122,6 +455,41 @@ This API is not documented yet. ### `create_image` +Create a new VM image. + +#### Internal API +
+`SYNO.Virtualization.API.Guest.Image` +
+ +#### Parameters +
+**_auto_clean_task_** `bool` +Whether to auto-clean the task after creation. Default is True. + +**_storage_names_** `str` +Storage names. + +**_storage_ids_** `str` +Storage IDs. + +**_type_** `str` +Image type ('disk', 'vdsm', or 'iso'). + +**_ds_file_path_** `str` +File path (should begin with a shared folder). + +**_image_name_** `str` +Name of the image. + + +
+#### Returns +
+`dict[str, object] or str` +Result of the create operation or error message. + +
diff --git a/documentation/docs/apis/classes/vpn.md b/documentation/docs/apis/classes/vpn.md index a0ca683e..33872cb0 100644 --- a/documentation/docs/apis/classes/vpn.md +++ b/documentation/docs/apis/classes/vpn.md @@ -14,9 +14,25 @@ This API is not documented yet. ::: ## Overview +API wrapper for Synology VPN Server. +Provides methods to retrieve VPN settings, active connections, logs, network interfaces, +security autoblock settings, permissions, and VPN protocol-specific settings. ## Methods ### `settings_list` +Retrieve VPN server settings. + +#### Internal API +
+`SYNO.VPNServer.Settings.Config` +
+ +#### Returns +
+`dict[str, object] or str` +VPN server settings as a dictionary, or an error message as a string. + +
@@ -24,6 +40,35 @@ This API is not documented yet. ### `active_connections_list` +Retrieve a list of active VPN connections. + +#### Internal API +
+`SYNO.VPNServer.Management.Connection` +
+ +#### Parameters +
+**_sort_** `str` +Field to sort by. Default is 'login_time'. + +**_sort_dir_** `str` +Sort direction ('ASC' or 'DESC'). Default is 'DESC'. + +**_start_** `int` +Pagination start index. Default is 0. + +**_limit_** `int` +Maximum number of results to return. Default is 100. + + +
+#### Returns +
+`dict[str, object] or str` +Active connections as a dictionary, or an error message as a string. + +
@@ -31,6 +76,32 @@ This API is not documented yet. ### `log_list` +Retrieve VPN server logs. + +#### Internal API +
+`SYNO.VPNServer.Management.Log` +
+ +#### Parameters +
+**_start_** `int` +Pagination start index. Default is 0. + +**_limit_** `int` +Maximum number of logs to return. Default is 50. + +**_prtltype_** `int` +Protocol type filter. Default is 0 (all). + + +
+#### Returns +
+`dict[str, object] or str` +Logs as a dictionary, or an error message as a string. + +
@@ -38,6 +109,19 @@ This API is not documented yet. ### `network_interface_setting` +Retrieve VPN network interface settings. + +#### Internal API +
+`SYNO.VPNServer.Management.Interface` +
+ +#### Returns +
+`dict[str, object] or str` +Network interface settings as a dictionary, or an error message as a string. + +
@@ -45,6 +129,19 @@ This API is not documented yet. ### `security_autoblock_setting` +Retrieve security autoblock settings. + +#### Internal API +
+`SYNO.Core.Security.AutoBlock` +
+ +#### Returns +
+`dict[str, object] or str` +Autoblock settings as a dictionary, or an error message as a string. + +
@@ -52,6 +149,29 @@ This API is not documented yet. ### `permission_setting` +Retrieve VPN permission settings. + +#### Internal API +
+`SYNO.VPNServer.Management.Account` +
+ +#### Parameters +
+**_start_** `int` +Pagination start index. Default is 0. + +**_limit_** `int` +Maximum number of results to return. Default is 100. + + +
+#### Returns +
+`dict[str, object] or str` +Permission settings as a dictionary, or an error message as a string. + +
@@ -59,6 +179,19 @@ This API is not documented yet. ### `pptp_settings_info` +Retrieve PPTP VPN settings. + +#### Internal API +
+`SYNO.VPNServer.Settings.Config` +
+ +#### Returns +
+`dict[str, object] or str` +PPTP settings as a dictionary, or an error message as a string. + +
@@ -66,6 +199,19 @@ This API is not documented yet. ### `openvpn_settings_info` +Retrieve OpenVPN settings. + +#### Internal API +
+`SYNO.VPNServer.Settings.Config` +
+ +#### Returns +
+`dict[str, object] or str` +OpenVPN settings as a dictionary, or an error message as a string. + +
@@ -73,6 +219,46 @@ This API is not documented yet. ### `l2tp_settings_info` +Retrieve L2TP VPN settings. + +#### Internal API +
+`SYNO.VPNServer.Settings.Config` +
+ +#### Returns +
+`dict[str, object] or str` +L2TP settings as a dictionary, or an error message as a string. + +
+ + + +--- + + +### `openvpn_export_configuration` +Download the OpenVPN configuration as a zip file or bytes. + +#### Internal API +
+`SYNO.VPNServer.Settings.Certificate` +
+ +#### Parameters +
+**_as_zip_file_** `bool` +If True, return a ZipFile object. If False, return bytes. Default is False. + + +
+#### Returns +
+`bytes or ZipFile` +The OpenVPN configuration file as bytes, or a ZipFile object if `as_zip_file` is True. + +
diff --git a/documentation/docs/apis/readme.md b/documentation/docs/apis/readme.md index c51368e9..a8630c4a 100644 --- a/documentation/docs/apis/readme.md +++ b/documentation/docs/apis/readme.md @@ -63,24 +63,28 @@ At the moment there are quite a few APIs implemented. They could be totally or p ### [Share](./apis/classes/core_share) - `SYNO.Core.Share` +- `SYNO.Core.Share.Crypto` - `SYNO.Core.Share.Permission` - `SYNO.Core.Share.KeyManager.Store` - `SYNO.Core.Share.KeyManager.AutoKey` ### [SharePermission](./apis/classes/core_share) - `SYNO.Core.Share` +- `SYNO.Core.Share.Crypto` - `SYNO.Core.Share.Permission` - `SYNO.Core.Share.KeyManager.Store` - `SYNO.Core.Share.KeyManager.AutoKey` ### [KeyManagerStore](./apis/classes/core_share) - `SYNO.Core.Share` +- `SYNO.Core.Share.Crypto` - `SYNO.Core.Share.Permission` - `SYNO.Core.Share.KeyManager.Store` - `SYNO.Core.Share.KeyManager.AutoKey` ### [KeyManagerAutoKey](./apis/classes/core_share) - `SYNO.Core.Share` +- `SYNO.Core.Share.Crypto` - `SYNO.Core.Share.Permission` - `SYNO.Core.Share.KeyManager.Store` - `SYNO.Core.Share.KeyManager.AutoKey` @@ -148,7 +152,6 @@ At the moment there are quite a few APIs implemented. They could be totally or p - `SYNO.Core.ExternalDevice.Storage.eSATA` - `SYNO.Finder.FileIndexing.Status` - `SYNO.Core.CMS.Info` -- `SYNO.Core.Service.PortInfo` - `SYNO.Core.PortForwarding.Rules` - `SYNO.Core.PortForwarding.RouterConf` - `SYNO.Core.Polling.Data` @@ -215,12 +218,17 @@ At the moment there are quite a few APIs implemented. They could be totally or p - `SYNO.Docker.Image` - `SYNO.Docker.Registry` - `SYNO.Docker.Network` +- `SYNO.Docker.Project` +- `SYNO.Docker.Container.Profile` +- `SYNO.Docker.Container.Log` ### [DownloadStation](./apis/classes/downloadstation) - `SYNO.DownloadStation.Info` - `SYNO.DownloadStation.Schedule` - `SYNO.DownloadStation{DOWNLOAD_ST_VERSION}.Task` - `SYNO.DownloadStation2.Task.Source` +- `SYNO.DownloadStation{DOWNLOAD_ST_VERSION}.Task.List` +- `SYNO.DownloadStation{DOWNLOAD_ST_VERSION}.Task.List.Polling` - `SYNO.DownloadStation.Statistic` - `SYNO.DownloadStation.RSS.Site` - `SYNO.DownloadStation{DOWNLOAD_ST_VERSION}.RSS.Feed` From 7c2b45770d12ae6aac6d0cc55886dca407b6b334 Mon Sep 17 00:00:00 2001 From: joeperpetua Date: Wed, 1 Oct 2025 20:59:38 +0200 Subject: [PATCH 095/126] chore: fix trailing whitespaces --- synology_api/downloadstation.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 8cfb7a40..eeb88192 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -433,7 +433,8 @@ def get_task_list(self, list_id: str) -> dict[str, any]: api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task.List' info = self.download_list[api_name] api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'get', 'list_id': list_id} + req_param = {'version': info['maxVersion'], + 'method': 'get', 'list_id': list_id} return self.request_data(api_name, api_path, req_param) @@ -564,12 +565,12 @@ def edit_task(self, task_id: str, destination: str = 'sharedfolder') -> dict[str param['id'] = ",".join(task_id) return self.request_data(api_name, api_path, param) - + def download_task_list( - self, - list_id: str, - file_indexes: list[int], - destination: str, + self, + list_id: str, + file_indexes: list[int], + destination: str, create_subfolder: bool = True ) -> dict[str, object] | str: """ @@ -602,7 +603,8 @@ def download_task_list( } ``` """ - api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task.List.Polling' + api_name = 'SYNO.DownloadStation' + \ + self.download_st_version + '.Task.List.Polling' info = self.download_list[api_name] api_path = info['path'] param = { From bf208b467c64d49fd9149ad77fb290eeba93562e Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Mon, 6 Oct 2025 03:00:21 +0200 Subject: [PATCH 096/126] #fix `task_info` not working and additional parameters. added download station unit test --- synology_api/downloadstation.py | 17 +++++++---------- tests/test_syno_api.py | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index eeb88192..c3cbc184 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -6,6 +6,8 @@ """ from __future__ import annotations + +import json from typing import Optional, Any from . import base_api @@ -323,8 +325,7 @@ def tasks_list(self, additional_param = ['detail', 'transfer', 'file', 'tracker', 'peer'] - if type(additional_param) is list: - req_param['additional'] = ",".join(additional_param) + req_param['additional'] = json.dumps(additional_param if isinstance(additional_param, list) else [additional_param]) return self.request_data(api_name, api_path, req_param) @@ -347,18 +348,14 @@ def tasks_info(self, task_id, additional_param: Optional[str | list[str]] = None api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'getinfo', + req_param = {'version': info['maxVersion'], 'method': 'get', 'id': task_id, 'additional': additional_param} if additional_param is None: - additional_param = ['detail', 'transfer', - 'file', 'tracker', 'peer'] + additional_param = ['detail', 'transfer', 'file', 'tracker', 'peer'] - if type(additional_param) is list: - req_param['additional'] = ",".join(additional_param) - - if type(task_id) is list: - req_param['id'] = ",".join(task_id) + req_param['additional'] = json.dumps(additional_param if isinstance(additional_param, list) else [additional_param]) + req_param['id'] = json.dumps(task_id if isinstance(task_id, list) else [task_id]) return self.request_data(api_name, api_path, req_param) diff --git a/tests/test_syno_api.py b/tests/test_syno_api.py index eb6321fc..ceb6ad68 100644 --- a/tests/test_syno_api.py +++ b/tests/test_syno_api.py @@ -3,6 +3,7 @@ from unittest import TestCase import unittest from synology_api.filestation import FileStation +from synology_api.downloadstation import DownloadStation from synology_api.surveillancestation import SurveillanceStation import os import pathlib @@ -43,6 +44,21 @@ def test_syno_filestation_login(self): self.assertIsNotNone(shares_list) self.assertEqual(shares_list.__len__(), 2) + def test_syno_downloadstation_login(self): + ds = DownloadStation (ip_address=self.config["synology_ip"], port=self.config["synology_port"], + username=self.config["synology_user"], + password=self.config["synology_password"], + secure=bool(self.config["synology_secure"]), cert_verify=False, + dsm_version=int(self.config["dsm_version"]), debug=True, + otp_code=self.config["otp_code"]) + self.assertIsNotNone(ds) + self.assertIsNotNone(ds.session) + self.assertIsNotNone(ds.session.sid) + self.assertIsNot(ds.session.sid, '') + tasks_list = ds.tasks_list() + self.assertIsNotNone(tasks_list) + self.assertEqual(tasks_list.__len__(), 2) + def test_syno_surveillancestation_login(self): ss = SurveillanceStation(ip_address=self.config["synology_ip"], port=self.config["synology_port"], username=self.config["synology_user"], From 2e1d41661de56ee40b00f715e21d23f807a3204b Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Mon, 6 Oct 2025 10:56:30 +0200 Subject: [PATCH 097/126] style: reformat with autopep8 --- .gitignore | 3 ++- synology_api/downloadstation.py | 12 ++++++++---- tests/test_syno_api.py | 12 ++++++------ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index dc74be3f..4179e4ab 100644 --- a/.gitignore +++ b/.gitignore @@ -401,4 +401,5 @@ FodyWeavers.xsd *.sln.iml # Test resources -tests/resources/config-test.json \ No newline at end of file +tests/resources/config-test.json +/tests/code.py diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index c3cbc184..da200c56 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -325,7 +325,8 @@ def tasks_list(self, additional_param = ['detail', 'transfer', 'file', 'tracker', 'peer'] - req_param['additional'] = json.dumps(additional_param if isinstance(additional_param, list) else [additional_param]) + req_param['additional'] = json.dumps(additional_param if isinstance( + additional_param, list) else [additional_param]) return self.request_data(api_name, api_path, req_param) @@ -352,10 +353,13 @@ def tasks_info(self, task_id, additional_param: Optional[str | list[str]] = None 'id': task_id, 'additional': additional_param} if additional_param is None: - additional_param = ['detail', 'transfer', 'file', 'tracker', 'peer'] + additional_param = ['detail', 'transfer', + 'file', 'tracker', 'peer'] - req_param['additional'] = json.dumps(additional_param if isinstance(additional_param, list) else [additional_param]) - req_param['id'] = json.dumps(task_id if isinstance(task_id, list) else [task_id]) + req_param['additional'] = json.dumps(additional_param if isinstance( + additional_param, list) else [additional_param]) + req_param['id'] = json.dumps( + task_id if isinstance(task_id, list) else [task_id]) return self.request_data(api_name, api_path, req_param) diff --git a/tests/test_syno_api.py b/tests/test_syno_api.py index ceb6ad68..e30b0be6 100644 --- a/tests/test_syno_api.py +++ b/tests/test_syno_api.py @@ -45,12 +45,12 @@ def test_syno_filestation_login(self): self.assertEqual(shares_list.__len__(), 2) def test_syno_downloadstation_login(self): - ds = DownloadStation (ip_address=self.config["synology_ip"], port=self.config["synology_port"], - username=self.config["synology_user"], - password=self.config["synology_password"], - secure=bool(self.config["synology_secure"]), cert_verify=False, - dsm_version=int(self.config["dsm_version"]), debug=True, - otp_code=self.config["otp_code"]) + ds = DownloadStation(ip_address=self.config["synology_ip"], port=self.config["synology_port"], + username=self.config["synology_user"], + password=self.config["synology_password"], + secure=bool(self.config["synology_secure"]), cert_verify=False, + dsm_version=int(self.config["dsm_version"]), debug=True, + otp_code=self.config["otp_code"]) self.assertIsNotNone(ds) self.assertIsNotNone(ds.session) self.assertIsNotNone(ds.session.sid) From 38034033a6d29f5505a95a26349c9d4bf2c0eb8d Mon Sep 17 00:00:00 2001 From: Steve707-AE <72551650+Steve707-AE@users.noreply.github.com> Date: Mon, 6 Oct 2025 11:01:37 +0200 Subject: [PATCH 098/126] .gitignore remove edit --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4179e4ab..46964152 100644 --- a/.gitignore +++ b/.gitignore @@ -402,4 +402,3 @@ FodyWeavers.xsd # Test resources tests/resources/config-test.json -/tests/code.py From 5e8d661e2f02deb4bf19ff3f55790c108bb5bdff Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sat, 11 Oct 2025 03:13:26 +0200 Subject: [PATCH 099/126] feat: added the feature to create a task from a torrent file instead of an url. --- synology_api/auth.py | 18 +++++++++++--- synology_api/downloadstation.py | 36 ++++++++++++++++++++++++--- synology_api/utils.py | 43 +++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 6 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index 02a3f6d1..96518c2b 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -1,9 +1,12 @@ """Provides authentication and API request handling for Synology DSM, including session management, encryption utilities, and error handling for various Synology services.""" from __future__ import annotations from random import randint -from typing import Optional +from typing import Optional, Any, Union import requests import json + +from requests_toolbelt import MultipartEncoder + from .error_codes import error_codes, CODE_SUCCESS, download_station_error_codes, file_station_error_codes from .error_codes import auth_error_codes, virtualization_error_codes from urllib3 import disable_warnings @@ -623,6 +626,7 @@ def request_data(self, api_path: str, req_param: dict[str, object], method: Optional[str] = None, + data: Optional[Union[MultipartEncoder, str]] = None, response_json: bool = True ) -> dict[str, object] | str | list | requests.Response: # 'post' or 'get' """ @@ -634,6 +638,8 @@ def request_data(self, The name of the Synology API to call. api_path : str The path to the API endpoint. + data: str, Optional. + The data to send to upload a file like a torrent file. req_param : dict[str, object] The parameters to include in the request. method : str, optional @@ -676,8 +682,14 @@ def request_data(self, response = requests.get(url, req_param, verify=self._verify, headers={ "X-SYNO-TOKEN": self._syno_token}) elif method == 'post': - response = requests.post(url, req_param, verify=self._verify, headers={ - "X-SYNO-TOKEN": self._syno_token}) + if data is None: + response = requests.post(url, req_param, verify=self._verify, headers={ + "X-SYNO-TOKEN": self._syno_token}) + else: + url = ('%s%s' % (self._base_url, api_path)) + \ + '/' + api_name + response = requests.post(url, data=data, params=req_param, verify=self._verify, headers={ + "Content-Type": data.content_type, "X-SYNO-TOKEN": self._syno_token}) except requests.exceptions.ConnectionError as e: raise SynoConnectionError(error_message=e.args[0]) except requests.exceptions.HTTPError as e: diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index da200c56..e2414226 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -8,8 +8,13 @@ from __future__ import annotations import json +import secrets from typing import Optional, Any + +from requests_toolbelt import MultipartEncoder + from . import base_api +from .utils import get_data_for_request_from_file class DownloadStation(base_api.BaseApi): @@ -439,14 +444,21 @@ def get_task_list(self, list_id: str) -> dict[str, any]: return self.request_data(api_name, api_path, req_param) - def create_task(self, url, destination) -> dict[str, object] | str: + def create_task(self, + url: Optional[str] = None, + file_path: Optional[str] = None, + destination: str = "", + ) -> dict[str, object] | str: """ Create a new download task. + You can choose between a url or a file path (.torrent) Parameters ---------- - url : str + url : str, Optional Download URL. + file_path: str, Optional + Download through file. destination : str Download destination. @@ -455,12 +467,30 @@ def create_task(self, url, destination) -> dict[str, object] | str: dict[str, object] or str API response. """ + # Validazione: esattamente uno tra url e file + if bool(url) == bool(file_path): + raise ValueError("You can't specify both 'url' and 'file_path'") + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.Task' info = self.download_list[api_name] api_path = info['path'] + + if file_path: + fields = [ + ("api", api_name), + ("method", "create"), + ("version", str(info["maxVersion"])), + ("type", '"file"'), + ("file", '["torrent"]'), + ("destination", f'"{destination}"'), + ("create_list", "true") + ] + data = get_data_for_request_from_file(file_path, fields) + + return self.request_data(api_name, api_path, method='post', data=data, response_json=True, req_param={}) + req_param = {'version': info['maxVersion'], 'method': 'create', 'type': 'url', 'create_list': 'true', 'destination': destination, 'url': f'["{url}"]'} - return self.request_data(api_name, api_path, req_param) def delete_task(self, task_id: str, force: bool = False) -> dict[str, object] | str: diff --git a/synology_api/utils.py b/synology_api/utils.py index bf40049e..8c00b3a3 100644 --- a/synology_api/utils.py +++ b/synology_api/utils.py @@ -1,9 +1,14 @@ """Utility functions for Synology API operations.""" import json +import secrets import sys # my_package/my_module.py __all__ = ['merge_dicts', 'make_folder_meta_list_from_path', 'parse_config'] +from pathlib import Path + +from requests_toolbelt import MultipartEncoder + def merge_dicts(x, y): """ @@ -56,3 +61,41 @@ def make_folder_meta_list_from_path(path): }) return folder_list + + +def get_data_for_request_from_file(file_path: str, fields: list[tuple]): + """ + Receive a file path and return a MultiPartEncoder for uploading it inside a request_data. + + Parameters + ---------- + file_path : str + The file path to be parsed. + fields : list of tuple[str, str] containing data + + Returns + ------- + MultiPartEncoder Object to send to the post request + + """ + + p = Path(file_path).expanduser().resolve() + if not p.is_file(): + raise FileNotFoundError(f"File not found: {p}") + + size_value = p.stat().st_size + boundary = generate_gecko_boundary() + fields.append(("size", str(size_value))) + fields.append( + ("torrent", (p.name, p.open("rb"), "application/x-bittorrent"))) + + enc = MultipartEncoder(fields=fields, boundary=boundary) + return enc + + +def generate_gecko_boundary(): + """ + Generate a boundary for MultiPartEncoder. + """ + random_hex = secrets.token_hex(16) # 16 byte = 32 caratteri esadecimali + return f"----geckoformboundary{random_hex}" From be9b862e502e7f3306355ae1b3cd4cb0b012c2c1 Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sun, 12 Oct 2025 01:31:13 +0200 Subject: [PATCH 100/126] #fix request_json explicit in create_task --- synology_api/downloadstation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index e2414226..bed6b8d7 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -487,7 +487,7 @@ def create_task(self, ] data = get_data_for_request_from_file(file_path, fields) - return self.request_data(api_name, api_path, method='post', data=data, response_json=True, req_param={}) + return self.request_data(api_name, api_path, method='post', data=data, req_param={}) req_param = {'version': info['maxVersion'], 'method': 'create', 'type': 'url', 'create_list': 'true', 'destination': destination, 'url': f'["{url}"]'} From df530866463ed360fc2f9a6b9e3e8270348dfcb7 Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sun, 12 Oct 2025 12:25:24 +0200 Subject: [PATCH 101/126] #fix numpydoc --- synology_api/downloadstation.py | 12 ++++++------ synology_api/utils.py | 12 +++++++++--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index bed6b8d7..2ed1f267 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -455,12 +455,12 @@ def create_task(self, Parameters ---------- - url : str, Optional - Download URL. - file_path: str, Optional - Download through file. - destination : str - Download destination. + url: str, optional + Download URL. Use either `url` or `file_path`. + file_path: str, optional + Path to a file (e.g. a .torrent) to download. + destination: str, optional + Download destination folder (default is ""). Returns ------- diff --git a/synology_api/utils.py b/synology_api/utils.py index 8c00b3a3..a4de5d07 100644 --- a/synology_api/utils.py +++ b/synology_api/utils.py @@ -71,12 +71,13 @@ def get_data_for_request_from_file(file_path: str, fields: list[tuple]): ---------- file_path : str The file path to be parsed. - fields : list of tuple[str, str] containing data + fields : list of tuple[str, str] + Fields to create the MultiPartEncoder. Returns ------- - MultiPartEncoder Object to send to the post request - + MultiPartEncoder + MultiPartEncoder Object to send to the post request """ p = Path(file_path).expanduser().resolve() @@ -96,6 +97,11 @@ def get_data_for_request_from_file(file_path: str, fields: list[tuple]): def generate_gecko_boundary(): """ Generate a boundary for MultiPartEncoder. + + Returns + ------- + str: + The random boundary ----geckoformboundary{random_hex} for the MultiPartEncoder. """ random_hex = secrets.token_hex(16) # 16 byte = 32 caratteri esadecimali return f"----geckoformboundary{random_hex}" From 10518398e2e27e12b0b061d9814bd3e92e9d1f28 Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sun, 12 Oct 2025 12:31:15 +0200 Subject: [PATCH 102/126] #fix .pre-commit-config.yaml `stages` --- .pre-commit-config.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 81a8ef31..403aaca6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,11 @@ ci: - skip: [ pytest ] + skip: [pytest] default_language_version: python: python3.13 -default_install_hook_types: [ pre-commit, pre-push, commit-msg ] -default_stages: [ pre-commit, pre-push, commit-msg ] +default_install_hook_types: [pre-commit, pre-push, commit-msg] +default_stages: [pre-commit, pre-push, commit-msg] repos: # general checks (see here: https://pre-commit.com/hooks.html) @@ -23,7 +23,7 @@ repos: - repo: https://github.com/numpy/numpydoc rev: v1.9.0 - stages: [ pre-commit ] hooks: - id: numpydoc-validation + stages: [pre-commit, manual] files: ^synology_api/ From 8b26a0089e7ea8ba89f6e216b0fba24f82c4728e Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sun, 12 Oct 2025 12:49:25 +0200 Subject: [PATCH 103/126] #fix numpydocs --- synology_api/auth.py | 2 +- synology_api/downloadstation.py | 3 ++- synology_api/utils.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index 96518c2b..2424f8fd 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -638,7 +638,7 @@ def request_data(self, The name of the Synology API to call. api_path : str The path to the API endpoint. - data: str, Optional. + data : str, optional The data to send to upload a file like a torrent file. req_param : dict[str, object] The parameters to include in the request. diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 2ed1f267..a1c1e22f 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -451,7 +451,8 @@ def create_task(self, ) -> dict[str, object] | str: """ Create a new download task. - You can choose between a url or a file path (.torrent) + + You can choose between a url or a file path (.torrent). Parameters ---------- diff --git a/synology_api/utils.py b/synology_api/utils.py index a4de5d07..690512d4 100644 --- a/synology_api/utils.py +++ b/synology_api/utils.py @@ -77,7 +77,7 @@ def get_data_for_request_from_file(file_path: str, fields: list[tuple]): Returns ------- MultiPartEncoder - MultiPartEncoder Object to send to the post request + MultiPartEncoder Object to send to the post request. """ p = Path(file_path).expanduser().resolve() From b0f7e5c488d2aa71ec4adf383cfdfaf2e34c927c Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sun, 12 Oct 2025 12:51:28 +0200 Subject: [PATCH 104/126] #fix numpydocs --- synology_api/auth.py | 4 ++-- synology_api/downloadstation.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index 2424f8fd..d7f95d4a 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -638,12 +638,12 @@ def request_data(self, The name of the Synology API to call. api_path : str The path to the API endpoint. - data : str, optional - The data to send to upload a file like a torrent file. req_param : dict[str, object] The parameters to include in the request. method : str, optional The HTTP method to use ('get' or 'post'). Defaults to 'get' if not specified. + data : str, optional + The data to send to upload a file like a torrent file. response_json : bool, optional Whether to return the response as JSON. If False, returns the raw response object. diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index a1c1e22f..3f6ba8b8 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -456,11 +456,11 @@ def create_task(self, Parameters ---------- - url: str, optional + url : str, optional Download URL. Use either `url` or `file_path`. - file_path: str, optional + file_path : str, optional Path to a file (e.g. a .torrent) to download. - destination: str, optional + destination : str, optional Download destination folder (default is ""). Returns From 69275a6cb90810eae1069526447fa6f8dd0cfccc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:07:50 +0000 Subject: [PATCH 105/126] chore(deps): bump cryptography in the python-packages group Bumps the python-packages group with 1 update: [cryptography](https://github.com/pyca/cryptography). Updates `cryptography` from 46.0.2 to 46.0.3 - [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst) - [Commits](https://github.com/pyca/cryptography/compare/46.0.2...46.0.3) --- updated-dependencies: - dependency-name: cryptography dependency-version: 46.0.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e9d9cde4..29cf0066 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,6 +8,6 @@ docstring-extractor==0.4.0 treelib==1.8.0 PyYAML==6.0.3 cffi==2.0.0 -cryptography==46.0.2 +cryptography==46.0.3 noiseprotocol==0.3.1 pycparser==2.23 From 080f43e3f8451c21a6616236e4cb053f066421ce Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Fri, 17 Oct 2025 01:12:38 +0200 Subject: [PATCH 106/126] #feat: ability to rename a file, validation on path while renaming, some docstrings --- synology_api/downloadstation.py | 2 +- synology_api/filestation.py | 67 +++++++++++++++--------- synology_api/utils.py | 90 ++++++++++++++++++++++++++++++++- 3 files changed, 134 insertions(+), 25 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 3f6ba8b8..a3ef9586 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -468,7 +468,7 @@ def create_task(self, dict[str, object] or str API response. """ - # Validazione: esattamente uno tra url e file + # Validate only a url or a file path. if bool(url) == bool(file_path): raise ValueError("You can't specify both 'url' and 'file_path'") diff --git a/synology_api/filestation.py b/synology_api/filestation.py index 993ca8aa..c60d0703 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -6,6 +6,8 @@ """ from __future__ import annotations + +import json from typing import Optional, Any import os import io @@ -20,6 +22,7 @@ from urllib import parse from treelib import Tree from . import base_api +from .utils import validate_path class FileStation(base_api.BaseApi): @@ -55,6 +58,13 @@ class FileStation(base_api.BaseApi): Name of the device. Default is None. interactive_output : bool, optional If True, enables interactive output. Default is False. + + Methods + ------- + get_info() + Get FileStation information. + get_list_share() + List shared folderss. """ def __init__(self, @@ -1387,14 +1397,14 @@ def rename_folder(self, search_taskid: Optional[str] = None ) -> dict[str, object] | str: """ - Rename a folder. + Rename a file or a folder. Parameters ---------- path : str or list of str - Current path or list of paths of the folder(s) to rename. + Current path or list of paths of the files or folder(s) to rename. name : str or list of str - New name or list of new names for the folder(s). + New name or list of new names for the file or folder(s). additional : str or list of str, optional Additional attributes to include. search_taskid : str, optional @@ -1404,33 +1414,32 @@ def rename_folder(self, ------- dict[str, object] or str Response from the API or error message. + + Examples + -------- + >>> rename_folder('/Downloads/script.log', 'script1.log') + >>> rename_folder(['/Downloads/script.log','/Downloads/script.log'],['a.log', 'b.log']) + >>> rename_folder('/Downloads/script', 'code') """ api_name = 'SYNO.FileStation.Rename' info = self.file_station_list[api_name] api_path = info['path'] req_param = {'version': info['maxVersion'], 'method': 'rename'} - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path + if isinstance(path, list) and isinstance(name, list): + if len(path) != len(name): + raise ValueError("Path and name must have the same length.") + elif isinstance(path, str) and isinstance(name, str): + pass # ok, both are strings else: - return 'Enter a valid folder path (folder path only ex. "/home/Drive/Downloads")' + raise TypeError( + "Path and name must be both lists or both strings.") - if type(name) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in name] - name = new_path - name = '[' + ','.join(name) + ']' - req_param['name'] = name - elif name is not None: - req_param['name'] = name - else: - return 'Enter a valid new folder name (new folder name only ex. "New Folder")' + if validate_path(path) == False: + return 'Enter a valid folder path or file path (ex. /Downloads/script.log)' + + req_param['path'] = json.dumps(path) + req_param['name'] = json.dumps(name) if additional is None: additional = ['real_path', 'size', 'owner', 'time'] @@ -1443,7 +1452,7 @@ def rename_folder(self, if search_taskid is not None: req_param['search_taskid'] = search_taskid - return self.request_data(api_name, api_path, req_param) + return self.request_data(api_name, api_path, req_param, method='post') def start_copy_move(self, path: str | list[str], @@ -1475,6 +1484,18 @@ def start_copy_move(self, ------- str or dict[str, object] Task ID or error message. + + Examples + -------- + Start a simple move task: + You have to specify only the file on the path and not the dest folder. + + >>> fs = FileStation(**params) + >>> task_id = fs.start_copy_task( + ... path="/Media/Film/Action/movie1.mkv", + ... dest_folder_path="/Media/Film/Drama", + ... overwrite=True + ... ) """ api_name = 'SYNO.FileStation.CopyMove' info = self.file_station_list[api_name] diff --git a/synology_api/utils.py b/synology_api/utils.py index 690512d4..bf0d78f9 100644 --- a/synology_api/utils.py +++ b/synology_api/utils.py @@ -1,9 +1,11 @@ """Utility functions for Synology API operations.""" import json +import re import secrets import sys # my_package/my_module.py -__all__ = ['merge_dicts', 'make_folder_meta_list_from_path', 'parse_config'] +__all__ = ['merge_dicts', 'make_folder_meta_list_from_path', + 'get_data_for_request_from_file', 'generate_gecko_boundary', 'validate_path'] from pathlib import Path @@ -105,3 +107,89 @@ def generate_gecko_boundary(): """ random_hex = secrets.token_hex(16) # 16 byte = 32 caratteri esadecimali return f"----geckoformboundary{random_hex}" + + +def validate_path(path: str | list[str]) -> bool: + """ + Validate the format of a Synology FileStation path. + + The function checks whether a given path string (or list of paths) follows + the basic formatting rules required by Synology FileStation APIs. + + Parameters + ---------- + path : str or list of str + The path or list of paths to validate. Each path can represent + either a file or directory. + + Returns + ------- + bool + True if the path (or all paths in the list) are valid according to + FileStation rules, False otherwise. + + Notes + ----- + - Must start with a forward slash ('/'). + - Must not contain any of the forbidden characters: * ? " < > | + - May contain internal spaces (e.g., '/My Folder/file name.txt'). + - Must not end with a space, tab, or slash. + - If the path contains a file extension, no spaces or characters are allowed + after the last period (e.g., '/Media/script.log extra' is invalid). + - Optionally allows paths without extensions (e.g., '/Media/script'). + + Examples + -------- + >>> validate_path('/Downloads/script.log') + True + >>> validate_path('/Downloads/script log.txt') + True + >>> validate_path('/Downloads/script') + True + >>> validate_path('/Downloads/script.log extra') + False + >>> validate_path('/Downloads/script.log ') + False + >>> validate_path('/Downloads/folder/') + False + >>> validate_path('Downloads/script.log') + False + """ + + def _is_valid(single_path: str) -> bool: + """ + Validate a single Synology FileStation path. + + Parameters + ---------- + single_path : str + The path to validate. + + Returns + ------- + bool + True if the given path is a valid Synology FileStation path. + """ + path_pattern = re.compile(r'^/[^*?"<>|]+$') + if not isinstance(single_path, str): + return False + + if not path_pattern.match(single_path): + return False + + if path[-1] in (' ', '\t', '/'): + return False + + parts = single_path.rsplit('.', 1) + if len(parts) == 2 and ' ' in parts[1]: + return False + + return True + + if isinstance(path, str): + return _is_valid(path) + + if isinstance(path, list): + return all(isinstance(p, str) and _is_valid(p) for p in path) + + return False From 970afb040357b4ab16b280a888c240bc18a5a5bf Mon Sep 17 00:00:00 2001 From: Steve707-AE Date: Sat, 18 Oct 2025 20:58:25 +0200 Subject: [PATCH 107/126] #feat: code improvements on `downloadstation.py`, `utils.py` and `filestation.py` --- synology_api/auth.py | 4 +- synology_api/downloadstation.py | 34 +++++----- synology_api/filestation.py | 109 +++++++++++++------------------- synology_api/utils.py | 54 ++++++++++++---- 4 files changed, 107 insertions(+), 94 deletions(-) diff --git a/synology_api/auth.py b/synology_api/auth.py index d7f95d4a..f6e52221 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -5,7 +5,7 @@ import requests import json -from requests_toolbelt import MultipartEncoder +from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor from .error_codes import error_codes, CODE_SUCCESS, download_station_error_codes, file_station_error_codes from .error_codes import auth_error_codes, virtualization_error_codes @@ -626,7 +626,7 @@ def request_data(self, api_path: str, req_param: dict[str, object], method: Optional[str] = None, - data: Optional[Union[MultipartEncoder, str]] = None, + data: MultiPartEncoderMonitor | MultipartEncoder | str | None = None, response_json: bool = True ) -> dict[str, object] | str | list | requests.Response: # 'post' or 'get' """ diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index a3ef9586..89b00597 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -8,11 +8,8 @@ from __future__ import annotations import json -import secrets from typing import Optional, Any -from requests_toolbelt import MultipartEncoder - from . import base_api from .utils import get_data_for_request_from_file @@ -360,9 +357,15 @@ def tasks_info(self, task_id, additional_param: Optional[str | list[str]] = None if additional_param is None: additional_param = ['detail', 'transfer', 'file', 'tracker', 'peer'] + elif isinstance(additional_param, str): + additional_param = [additional_param] + elif isinstance(additional_param, list): + if not all(isinstance(a, str) for a in additional_param): + return "additional_param must be a string or a list of strings." + else: + return "additional_param must be a string or a list of strings." - req_param['additional'] = json.dumps(additional_param if isinstance( - additional_param, list) else [additional_param]) + req_param['additional'] = json.dumps(additional_param) req_param['id'] = json.dumps( task_id if isinstance(task_id, list) else [task_id]) @@ -477,16 +480,17 @@ def create_task(self, api_path = info['path'] if file_path: - fields = [ - ("api", api_name), - ("method", "create"), - ("version", str(info["maxVersion"])), - ("type", '"file"'), - ("file", '["torrent"]'), - ("destination", f'"{destination}"'), - ("create_list", "true") - ] - data = get_data_for_request_from_file(file_path, fields) + fields = { + "api": api_name, + "method": "create", + "version": str(info["maxVersion"]), + "type": '"file"', + "file": '["torrent"]', + "destination": f'"{destination}"', + "create_list": "true" + } + data = get_data_for_request_from_file( + file_path='file_path', fields=fields, called_from='DownloadStation') return self.request_data(api_name, api_path, method='post', data=data, req_param={}) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index c60d0703..840b2bd7 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -13,6 +13,7 @@ import io import time from datetime import datetime +from urllib.parse import urljoin, urlencode import requests import tqdm @@ -22,7 +23,7 @@ from urllib import parse from treelib import Tree from . import base_api -from .utils import validate_path +from .utils import validate_path, get_data_for_request_from_file class FileStation(base_api.BaseApi): @@ -269,18 +270,18 @@ def get_file_list(self, return self.request_data(api_name, api_path, req_param) def get_file_info(self, - path: Optional[str] = None, - additional: Optional[str | list[str]] = None + path: str | list[str], + additional_param: Optional[str | list[str]] = None ) -> dict[str, object] | str: """ Get information about a file or files. Parameters ---------- - path : str or list of str, optional + path : str or list of str Path(s) to the file(s). - additional : str or list of str, optional - Additional attributes to include. + additional_param : str or list of str, optional + Additional attributes to retrieve. Returns ------- @@ -290,24 +291,22 @@ def get_file_info(self, api_name = 'SYNO.FileStation.List' info = self.file_station_list[api_name] api_path = info['path'] - req_param = {'version': info['maxVersion'], 'method': 'getinfo'} - - if type(path) is list: - new_path = [] - [new_path.append('"' + x + '"') for x in path] - path = new_path - path = '[' + ','.join(path) + ']' - req_param['path'] = path - elif path is not None: - req_param['path'] = path - - if additional is None: - additional = ['real_path', 'size', 'owner', 'time'] - - if type(additional) is list: - additional = str(additional).replace("'", '"') + req_param = {'version': info['maxVersion'], + 'method': 'getinfo', + 'path': json.dumps(path)} + + if additional_param is None: + additional_param = ["real_path", "size", + "owner", "time", "perm", "type"] + elif isinstance(additional_param, str): + additional_param = [additional_param] + elif isinstance(additional_param, list): + if not all(isinstance(a, str) for a in additional_param): + return "additional_param must be a string or a list of strings." + else: + return "additional_param must be a string or a list of strings." - req_param['additional'] = additional + req_param['additional'] = json.dumps(additional_param) return self.request_data(api_name, api_path, req_param) @@ -1063,50 +1062,32 @@ def upload_file(self, api_name = 'SYNO.FileStation.Upload' info = self.file_station_list[api_name] api_path = info['path'] - filename = os.path.basename(file_path) session = requests.session() - with open(file_path, 'rb') as payload: - url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=upload&_sid=%s' % ( - api_name, info['minVersion'], self._sid) - - encoder = MultipartEncoder({ - 'path': dest_path, - 'create_parents': str(create_parents).lower(), - 'overwrite': str(overwrite).lower(), - 'files': (filename, payload, 'application/octet-stream') - }) - - if progress_bar: - bar = tqdm.tqdm(desc='Upload Progress', - total=encoder.len, - dynamic_ncols=True, - unit='B', - unit_scale=True, - unit_divisor=1024 - ) - - monitor = MultipartEncoderMonitor( - encoder, lambda monitor: bar.update(monitor.bytes_read - bar.n)) - - r = session.post( - url, - data=monitor, - verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, - 'Content-Type': monitor.content_type} - ) - - else: - r = session.post( - url, - data=encoder, - verify=verify, - headers={"X-SYNO-TOKEN": self.session._syno_token, - 'Content-Type': encoder.content_type} - ) - + base = urljoin(self.base_url, api_path) + url_params = { + "api": api_name, + "version": info["minVersion"], + "method": "upload", + "_sid": self._sid + } + + url = f"{base}?{urlencode(url_params)}" + encoder_params = { + 'path': dest_path, + 'create_parents': str(create_parents).lower(), + 'overwrite': str(overwrite).lower(), + } + data = get_data_for_request_from_file( + file_path=file_path, fields=encoder_params, called_from='FileStation', progress_bar=True) + r = session.post( + url, + data=data, + verify=verify, + headers={"X-SYNO-TOKEN": self.session._syno_token, + 'Content-Type': data.content_type} + ) session.close() if r.status_code != 200 or not r.json()['success']: return r.status_code, r.json() diff --git a/synology_api/utils.py b/synology_api/utils.py index bf0d78f9..ffa27e26 100644 --- a/synology_api/utils.py +++ b/synology_api/utils.py @@ -1,5 +1,6 @@ """Utility functions for Synology API operations.""" import json +import mimetypes import re import secrets import sys @@ -9,7 +10,8 @@ from pathlib import Path -from requests_toolbelt import MultipartEncoder +from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor +from tqdm import tqdm def merge_dicts(x, y): @@ -65,21 +67,34 @@ def make_folder_meta_list_from_path(path): return folder_list -def get_data_for_request_from_file(file_path: str, fields: list[tuple]): +def get_data_for_request_from_file(file_path: str, + fields: dict[str, str | tuple], + progress_bar: bool = True, + called_from: str = 'DownloadStation'): """ - Receive a file path and return a MultiPartEncoder for uploading it inside a request_data. + Build and return a ``MultipartEncoder`` or a ``MultipartEncoderMonitor`` to upload a file via ``request_data`` (POST multipart/form-data). Parameters ---------- file_path : str The file path to be parsed. - fields : list of tuple[str, str] - Fields to create the MultiPartEncoder. + fields : dict[str, str | tuple] + Dictionary of form fields used to build the multipart payload. + Each key represents a form field name. + The value can be: + - a string (for standard text fields) + - a tuple ``(filename, fileobj, mimetype)`` for file fields. + progress_bar : bool + Whether to show a progress bar when uploading file or not. + called_from : str + The name of the calling class. (ex 'FileStation') Returns ------- - MultiPartEncoder - MultiPartEncoder Object to send to the post request. + MultipartEncoder | MultipartEncoderMonitor + The multipart payload object to pass to your HTTP client. When a monitor is returned, + access its underlying encoder via ``monitor.encoder`` and supply + ``headers = {"Content-Type": monitor.content_type}`` (or ``encoder.content_type``). """ p = Path(file_path).expanduser().resolve() @@ -88,12 +103,25 @@ def get_data_for_request_from_file(file_path: str, fields: list[tuple]): size_value = p.stat().st_size boundary = generate_gecko_boundary() - fields.append(("size", str(size_value))) - fields.append( - ("torrent", (p.name, p.open("rb"), "application/x-bittorrent"))) - - enc = MultipartEncoder(fields=fields, boundary=boundary) - return enc + fields["size"] = str(size_value) + mime_type, _ = mimetypes.guess_type(p.name) + mime_type = mime_type or "application/octet-stream" + + if called_from == 'DownloadStation': + fields["torrent"] = (p.name, p.open("rb"), mime_type) + elif called_from == 'FileStation': + fields["files"] = (p.name, p.open("rb"), mime_type) + + encoder = MultipartEncoder(fields=fields, boundary=boundary) + print(encoder) + if progress_bar: + pbar = tqdm(total=encoder.len, unit="B", unit_scale=True, + unit_divisor=1024, desc="Upload Progress") + monitor = MultipartEncoderMonitor( + encoder, lambda m: pbar.update(m.bytes_read - pbar.n) + ) + return monitor + return encoder def generate_gecko_boundary(): From 5a52b48594935982afc1b2d84e398d5cc935360e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 13:20:24 +0000 Subject: [PATCH 108/126] chore(deps): bump psutil in the python-packages group Bumps the python-packages group with 1 update: [psutil](https://github.com/giampaolo/psutil). Updates `psutil` from 7.1.0 to 7.1.1 - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-7.1.0...release-7.1.1) --- updated-dependencies: - dependency-name: psutil dependency-version: 7.1.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 29cf0066..917e7772 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ requests==2.32.5 urllib3==2.5.0 requests-toolbelt==1.0.0 tqdm==4.67.1 -psutil==7.1.0 +psutil==7.1.1 docstring-extractor==0.4.0 treelib==1.8.0 PyYAML==6.0.3 From ad2efedeb49878a22867ca35410034fdbd508d5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Oct 2025 13:29:36 +0000 Subject: [PATCH 109/126] chore(deps): bump psutil in the python-packages group Bumps the python-packages group with 1 update: [psutil](https://github.com/giampaolo/psutil). Updates `psutil` from 7.1.1 to 7.1.2 - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-7.1.1...release-7.1.2) --- updated-dependencies: - dependency-name: psutil dependency-version: 7.1.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 917e7772..0feba572 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ requests==2.32.5 urllib3==2.5.0 requests-toolbelt==1.0.0 tqdm==4.67.1 -psutil==7.1.1 +psutil==7.1.2 docstring-extractor==0.4.0 treelib==1.8.0 PyYAML==6.0.3 From 9c61cf1698da11140b3b6316c680d8e500f77564 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Nov 2025 13:11:44 +0000 Subject: [PATCH 110/126] chore(deps): bump psutil in the python-packages group Bumps the python-packages group with 1 update: [psutil](https://github.com/giampaolo/psutil). Updates `psutil` from 7.1.2 to 7.1.3 - [Changelog](https://github.com/giampaolo/psutil/blob/master/HISTORY.rst) - [Commits](https://github.com/giampaolo/psutil/compare/release-7.1.2...release-7.1.3) --- updated-dependencies: - dependency-name: psutil dependency-version: 7.1.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 0feba572..177ee803 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ requests==2.32.5 urllib3==2.5.0 requests-toolbelt==1.0.0 tqdm==4.67.1 -psutil==7.1.2 +psutil==7.1.3 docstring-extractor==0.4.0 treelib==1.8.0 PyYAML==6.0.3 From 0ec2a0d3bde082eb6c6dc6dcebfc4561e86f757b Mon Sep 17 00:00:00 2001 From: fboissadier Date: Sun, 9 Nov 2025 21:12:46 +0100 Subject: [PATCH 111/126] Udpate get_file from filestation docstring. Based on the recent discution on telegram --- synology_api/filestation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synology_api/filestation.py b/synology_api/filestation.py index 840b2bd7..010035c4 100644 --- a/synology_api/filestation.py +++ b/synology_api/filestation.py @@ -2102,7 +2102,7 @@ def get_file(self, Parameters ---------- path : str - Path to the file on the server. + The file path starting with a shared folder to be downloaded. mode : str Mode for downloading the file ('open' to open in browser, 'download' to download to disk). dest_path : str, optional From 76ecd747e0387c4418460c6b32a6988022189e6a Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Mon, 10 Nov 2025 10:12:32 -0700 Subject: [PATCH 112/126] Raise exception if Synology returns 400 or 500-level response --- synology_api/auth.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/synology_api/auth.py b/synology_api/auth.py index f6e52221..7a5c936d 100644 --- a/synology_api/auth.py +++ b/synology_api/auth.py @@ -690,6 +690,7 @@ def request_data(self, '/' + api_name response = requests.post(url, data=data, params=req_param, verify=self._verify, headers={ "Content-Type": data.content_type, "X-SYNO-TOKEN": self._syno_token}) + response.raise_for_status() except requests.exceptions.ConnectionError as e: raise SynoConnectionError(error_message=e.args[0]) except requests.exceptions.HTTPError as e: @@ -702,6 +703,7 @@ def request_data(self, elif method == 'post': response = requests.post(url, req_param, verify=self._verify, headers={ "X-SYNO-TOKEN": self._syno_token}) + response.raise_for_status() # Check for error response from dsm: error_code = 0 From f2f493239d05de53afbf6621d48b6237c4826007 Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 11 Nov 2025 09:31:37 -0700 Subject: [PATCH 113/126] Add missing deps to `setup.py` and reformat --- setup.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/setup.py b/setup.py index 3c2703c0..4631ba35 100644 --- a/setup.py +++ b/setup.py @@ -2,21 +2,34 @@ # read the contents of your README file from os import path + this_directory = path.abspath(path.dirname(__file__)) -with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f: +with open(path.join(this_directory, "README.md"), encoding="utf-8") as f: long_description = f.read() setup( - name='synology-api', - version='0.8.1', - packages=find_packages(exclude=['tests*']), - license='MIT', - description='Python Synology API Wrapper', + name="synology-api", + version="0.8.1", + packages=find_packages(exclude=["tests*"]), + license="MIT", + description="Python Synology API Wrapper", long_description=long_description, - long_description_content_type='text/markdown', - install_requires=['requests', 'urllib3', 'setuptools', - 'requests_toolbelt', 'tqdm', 'cryptography', 'treelib'], - url='https://github.com/N4S4/synology-api', - author='Renato Visaggio', - author_email='synology.python.api@gmail.com' + long_description_content_type="text/markdown", + install_requires=[ + "requests", + "urllib3", + "setuptools", + "requests_toolbelt", + "tqdm", + "cryptography", + "treelib", + "psutil", + "docstring-extractor", + "PyYAML", + "cryptography", + "noiseprotocol", + ], + url="https://github.com/N4S4/synology-api", + author="Renato Visaggio", + author_email="synology.python.api@gmail.com", ) From 1f0b4190585870b6d050d8addd4d3984297c161b Mon Sep 17 00:00:00 2001 From: Adam Brown Date: Tue, 11 Nov 2025 10:28:43 -0700 Subject: [PATCH 114/126] Add `noiseprotocol` package to `setup.py` --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3c2703c0..dec2fb4d 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,9 @@ long_description=long_description, long_description_content_type='text/markdown', install_requires=['requests', 'urllib3', 'setuptools', - 'requests_toolbelt', 'tqdm', 'cryptography', 'treelib'], + 'requests_toolbelt', 'tqdm', 'cryptography', 'treelib', + 'noiseprotocol', + ], url='https://github.com/N4S4/synology-api', author='Renato Visaggio', author_email='synology.python.api@gmail.com' From 88e5ce0b116600c29810de9fff3e6c027c850940 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Nov 2025 17:03:45 +0000 Subject: [PATCH 115/126] chore(deps): bump js-yaml from 3.14.1 to 3.14.2 in /documentation Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.14.1 to 3.14.2. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/3.14.1...3.14.2) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 3.14.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- documentation/package-lock.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index 27151381..9458114f 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -8967,9 +8967,9 @@ } }, "node_modules/gray-matter/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", "license": "MIT", "dependencies": { "argparse": "^1.0.7", @@ -10111,9 +10111,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "license": "MIT", "dependencies": { "argparse": "^2.0.1" From 0577852509483004b70c6a6150e385be3505b2b3 Mon Sep 17 00:00:00 2001 From: Renato <33936751+N4S4@users.noreply.github.com> Date: Fri, 21 Nov 2025 03:17:55 +0100 Subject: [PATCH 116/126] update version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index dec2fb4d..d3542965 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setup( name='synology-api', - version='0.8.1', + version='0.8.2', packages=find_packages(exclude=['tests*']), license='MIT', description='Python Synology API Wrapper', From f04a87adfe5dce542e2e085016b12e652e3f7a01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Nov 2025 22:17:05 +0000 Subject: [PATCH 117/126] chore(deps): bump node-forge from 1.3.1 to 1.3.2 in /documentation Bumps [node-forge](https://github.com/digitalbazaar/forge) from 1.3.1 to 1.3.2. - [Changelog](https://github.com/digitalbazaar/forge/blob/main/CHANGELOG.md) - [Commits](https://github.com/digitalbazaar/forge/compare/v1.3.1...v1.3.2) --- updated-dependencies: - dependency-name: node-forge dependency-version: 1.3.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- documentation/package-lock.json | 35 ++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index 9458114f..b8d9d6cc 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -167,6 +167,7 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.20.0.tgz", "integrity": "sha512-KL1zWTzrlN4MSiaK1ea560iCA/UewMbS4ZsLQRPoDTWyrbDKVbztkPwwv764LAqgXk0fvkNZvJ3IelcK7DqhjQ==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-common": "5.20.0", "@algolia/requester-browser-xhr": "5.20.0", @@ -305,6 +306,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.7.tgz", "integrity": "sha512-SRijHmF0PSPgLIBYlWnG0hyeJLwXE2CgpsXaMOrtt2yp9/86ALw6oUlj9KYuZ0JN07T4eBMVIW4li/9S1j2BGA==", "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.26.2", @@ -2070,6 +2072,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2092,6 +2095,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2172,6 +2176,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2506,6 +2511,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3335,6 +3341,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.7.0.tgz", "integrity": "sha512-GXg5V7kC9FZE4FkUZA8oo/NrlRb06UwuICzI6tcbzj0+TVgjq/mpUXXzSgKzMS82YByi4dY2Q808njcBCyy6tQ==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/core": "3.7.0", "@docusaurus/logger": "3.7.0", @@ -3951,6 +3958,7 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.0.tgz", "integrity": "sha512-QjHtSaoameoalGnKDT3FoIl4+9RwyTmo9ZJGBdLOks/YOiWHoRDI3PUwEzOE7kEmGcV3AFcp9K6dYu9rEuKLAQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -4109,6 +4117,7 @@ "resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.3.tgz", "integrity": "sha512-z+j7DixNnfpdToYsOutStDgeRzJSMnbj8T1C/oQjB6Aa+kRfNjs/Fn7W6c8bmlt6mfy3FkgeKBRnDjxQow5dow==", "license": "MIT", + "peer": true, "dependencies": { "@octokit/auth-token": "^5.0.0", "@octokit/graphql": "^8.1.2", @@ -4595,6 +4604,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5005,6 +5015,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -5338,6 +5349,7 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5393,6 +5405,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -5438,6 +5451,7 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.20.0.tgz", "integrity": "sha512-groO71Fvi5SWpxjI9Ia+chy0QBwT61mg6yxJV27f5YFf+Mw+STT75K6SHySpP8Co5LsCrtsbCH5dJZSRtkSKaQ==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-abtesting": "5.20.0", "@algolia/client-analytics": "5.20.0", @@ -5912,6 +5926,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001688", "electron-to-chromium": "^1.5.73", @@ -6858,6 +6873,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8276,6 +8292,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -8479,6 +8496,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -12890,9 +12908,9 @@ } }, "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", + "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "license": "(BSD-3-Clause OR GPL-2.0)", "engines": { "node": ">= 6.13.0" @@ -12989,6 +13007,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -13572,6 +13591,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -14475,6 +14495,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.0.0.tgz", "integrity": "sha512-9RbEr1Y7FFfptd/1eEdntyjMwLeghW1bHX9GWjXo19vx4ytPQhANltvVxDggzJl7mnWM+dX28kb6cyS/4iQjlQ==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -15268,6 +15289,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -15416,6 +15438,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.25.0" }, @@ -15474,6 +15497,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", "license": "MIT", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -15502,6 +15526,7 @@ "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -17340,6 +17365,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -17719,6 +17745,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -17917,6 +17944,7 @@ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -18154,6 +18182,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", From 5472f2ecf252f9d585b3da05439f1ff19e69365a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 04:03:23 +0000 Subject: [PATCH 118/126] chore(deps): bump mdast-util-to-hast in /documentation Bumps [mdast-util-to-hast](https://github.com/syntax-tree/mdast-util-to-hast) from 13.2.0 to 13.2.1. - [Release notes](https://github.com/syntax-tree/mdast-util-to-hast/releases) - [Commits](https://github.com/syntax-tree/mdast-util-to-hast/compare/13.2.0...13.2.1) --- updated-dependencies: - dependency-name: mdast-util-to-hast dependency-version: 13.2.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- documentation/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index b8d9d6cc..834f5600 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -10766,9 +10766,9 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", From e610839417033f6b33325fa1cf3c941b2cce7055 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:39:29 +0000 Subject: [PATCH 119/126] chore(deps): bump express from 4.21.2 to 4.22.1 in /documentation Bumps [express](https://github.com/expressjs/express) from 4.21.2 to 4.22.1. - [Release notes](https://github.com/expressjs/express/releases) - [Changelog](https://github.com/expressjs/express/blob/v4.22.1/History.md) - [Commits](https://github.com/expressjs/express/compare/4.21.2...v4.22.1) --- updated-dependencies: - dependency-name: express dependency-version: 4.22.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- documentation/package-lock.json | 47 ++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/documentation/package-lock.json b/documentation/package-lock.json index 834f5600..f1dc55c4 100644 --- a/documentation/package-lock.json +++ b/documentation/package-lock.json @@ -8032,39 +8032,39 @@ } }, "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", + "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", + "body-parser": "~1.20.3", + "content-disposition": "~0.5.4", "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", + "cookie": "~0.7.1", + "cookie-signature": "~1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", + "finalhandler": "~1.3.1", + "fresh": "~0.5.2", + "http-errors": "~2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "2.4.1", + "on-finished": "~2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", + "path-to-regexp": "~0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.13.0", + "qs": "~6.14.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", + "send": "~0.19.0", + "serve-static": "~1.16.2", "setprototypeof": "1.2.0", - "statuses": "2.0.1", + "statuses": "~2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -8110,6 +8110,21 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "node_modules/express/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/express/node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", From 67aa2baab6d4133d6078488e242667cc6c6ecbf9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 05:06:38 +0000 Subject: [PATCH 120/126] chore(deps): bump urllib3 from 2.5.0 to 2.6.0 Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.5.0 to 2.6.0. - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.0) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.6.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 177ee803..590e2648 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ setuptools==80.9.0 requests==2.32.5 -urllib3==2.5.0 +urllib3==2.6.0 requests-toolbelt==1.0.0 tqdm==4.67.1 psutil==7.1.3 From 71a5a1d492f69618619a685801903604f2a29718 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 13:06:48 +0000 Subject: [PATCH 121/126] chore(deps): bump urllib3 in the python-packages group Bumps the python-packages group with 1 update: [urllib3](https://github.com/urllib3/urllib3). Updates `urllib3` from 2.6.0 to 2.6.1 - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.6.0...2.6.1) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.6.1 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 590e2648..78009d0d 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ setuptools==80.9.0 requests==2.32.5 -urllib3==2.6.0 +urllib3==2.6.1 requests-toolbelt==1.0.0 tqdm==4.67.1 psutil==7.1.3 From 6980d65d549ef452541e58da05a9c6ee28acf468 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 13:06:29 +0000 Subject: [PATCH 122/126] chore(deps): bump urllib3 in the python-packages group Bumps the python-packages group with 1 update: [urllib3](https://github.com/urllib3/urllib3). Updates `urllib3` from 2.6.1 to 2.6.2 - [Release notes](https://github.com/urllib3/urllib3/releases) - [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst) - [Commits](https://github.com/urllib3/urllib3/compare/2.6.1...2.6.2) --- updated-dependencies: - dependency-name: urllib3 dependency-version: 2.6.2 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: python-packages ... Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 78009d0d..f93c7126 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ setuptools==80.9.0 requests==2.32.5 -urllib3==2.6.1 +urllib3==2.6.2 requests-toolbelt==1.0.0 tqdm==4.67.1 psutil==7.1.3 From 9c0e9c599925ac1a7fb75bbc9c38c41101f477ce Mon Sep 17 00:00:00 2001 From: EddieKuo723 <66857463+EddieKuo723@users.noreply.github.com> Date: Sun, 9 Feb 2025 22:20:24 -0800 Subject: [PATCH 123/126] Add some rss filter function --- synology_api/downloadstation.py | 89 ++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 2 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 89b00597..152ce48f 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -719,7 +719,7 @@ def refresh_rss_site(self, rss_id: Optional[str] = None) -> dict[str, object] | 'method': 'refresh', 'id': rss_id} if rss_id is None: - return 'Enter a valid ID check if you have any with get_rss_list()' + return 'Enter a valid ID check if you have any with get_rss_info_list()' elif type(rss_id) is list: rss_id = ','.join(rss_id) param['id'] = rss_id @@ -754,7 +754,7 @@ def rss_feed_list(self, param = {'version': info['maxVersion'], 'method': 'list', 'id': rss_id} if rss_id is None: - return 'Enter a valid ID check if you have any with get_rss_list()' + return 'Enter a valid ID check if you have any with get_rss_info_list()' elif type(rss_id) is list: rss_id = ','.join(rss_id) param['id'] = rss_id @@ -766,6 +766,91 @@ def rss_feed_list(self, return self.request_data(api_name, api_path, param) + def rss_feed_filter_list(self, + feed_id: Optional [int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None + ) -> dict[str, object] | str: + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' + info = self.download_list[api_name] + api_path = info['path'] + param = {'version': info['maxVersion'], 'method': 'list', 'feed_id': feed_id} + + if feed_id is None: + return 'Enter a valid ID check if you have any with get_rss_info_list()' + + if offset is not None: + param['offset'] = offset + if limit is not None: + param['limit'] = limit + + return self.request_data(api_name, api_path, param) + + def rss_feed_filter_add(self, + feed_id: int = None, + filter_name: str = None, + match: str = None, + not_match: str = None, + destination: str = None, + is_regex: bool = False + ) -> dict[str, object] | str: + + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' + info = self.download_list[api_name] + api_path = info['path'] + + param = {'version': info['maxVersion'], 'method': 'add', 'feed_id': feed_id, + 'name':f'"{filter_name}"', 'match':f'"{match}"','not_match':f'"{not_match}"', + 'destination':f'"{destination}"', 'is_regex':str(is_regex).lower()} + + if type(is_regex) is not bool: + return 'Please set is_regex to True or False' + + if feed_id is None: + return 'Enter a valid ID check if you have any with get_rss_info_list()' + + return self.request_data(api_name, api_path, param) + + def rss_feed_filter_set(self, + filter_id: int = None, + filter_name: str = None, + match: str = None, + not_match: str = None, + destination: str = None, + is_regex: bool = False + ) -> dict[str, object] | str: + + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' + info = self.download_list[api_name] + api_path = info['path'] + + param = {'version': info['maxVersion'], 'method': 'set', 'feed_id': 'null', 'id': filter_id, + 'name':f'"{filter_name}"', 'match':f'"{match}"','not_match':f'"{not_match}"', + 'destination':f'"{destination}"', 'is_regex':str(is_regex).lower()} + + if type(is_regex) is not bool: + return 'Please set is_regex to True or False' + + if filter_id is None: + return 'Enter a valid ID check if you have any with rss_feed_filter_list()' + + return self.request_data(api_name, api_path, param) + + def rss_feed_filter_delete(self, + filter_id: int = None, + ) -> dict[str, object] | str: + + api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' + info = self.download_list[api_name] + api_path = info['path'] + + param = {'version': info['maxVersion'], 'method': 'delete', 'id': filter_id} + + if filter_id is None: + return 'Enter a valid ID check if you have any with rss_feed_filter_list()' + + return self.request_data(api_name, api_path, param) + def start_bt_search(self, keyword: Optional[str] = None, module: str = 'all') -> dict[str, object] | str: """ Start a BT search. From 7bafaea6294ef83c74e97b4f4e49559ec9fcf8dd Mon Sep 17 00:00:00 2001 From: EddieKuo723 <66857463+EddieKuo723@users.noreply.github.com> Date: Sat, 13 Dec 2025 00:29:57 -0800 Subject: [PATCH 124/126] docs(downloadstation): add missing docstrings for RSS filter methods --- synology_api/downloadstation.py | 84 +++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 152ce48f..83b8061f 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -85,6 +85,14 @@ class DownloadStation(base_api.BaseApi): Refresh RSS site. rss_feed_list(...) Get RSS feed list. + rss_feed_filter_list(...) + Get RSS feed filter list. + rss_feed_filter_add(...) + Add RSS feed filter. + rss_feed_filter_set(...) + Set RSS feed filter. + rss_feed_filter_delete(...) + Delete RSS feed filter. start_bt_search(...) Start a BT search. get_bt_search_results(...) @@ -771,6 +779,23 @@ def rss_feed_filter_list(self, offset: Optional[int] = None, limit: Optional[int] = None ) -> dict[str, object] | str: + """ + Get RSS feed filter list. + + Parameters + ---------- + feed_id : int, optional + RSS feed ID. + offset : int, optional + Offset for pagination. + limit : int, optional + Maximum number of filters to retrieve. + + Returns + ------- + dict[str, object] or str + RSS feed filter list. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' info = self.download_list[api_name] api_path = info['path'] @@ -794,6 +819,29 @@ def rss_feed_filter_add(self, destination: str = None, is_regex: bool = False ) -> dict[str, object] | str: + """ + Add RSS feed filter. + + Parameters + ---------- + feed_id : int + RSS feed ID. + filter_name : str + Filter name. + match : str + Match pattern. + not_match : str + Not match pattern. + destination : str + Download destination. + is_regex : bool, optional + Use regex for matching (default is False). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' info = self.download_list[api_name] @@ -819,6 +867,29 @@ def rss_feed_filter_set(self, destination: str = None, is_regex: bool = False ) -> dict[str, object] | str: + """ + Set RSS feed filter. + + Parameters + ---------- + filter_id : int + Filter ID. + filter_name : str + Filter name. + match : str + Match pattern. + not_match : str + Not match pattern. + destination : str + Download destination. + is_regex : bool, optional + Use regex for matching (default is False). + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' info = self.download_list[api_name] @@ -839,6 +910,19 @@ def rss_feed_filter_set(self, def rss_feed_filter_delete(self, filter_id: int = None, ) -> dict[str, object] | str: + """ + Delete RSS feed filter. + + Parameters + ---------- + filter_id : int + Filter ID. + + Returns + ------- + dict[str, object] or str + API response. + """ api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' info = self.download_list[api_name] From f59e042bb159b7ca4973664a398ea41aa361f3ba Mon Sep 17 00:00:00 2001 From: EddieKuo723 <66857463+EddieKuo723@users.noreply.github.com> Date: Sat, 13 Dec 2025 22:56:43 -0800 Subject: [PATCH 125/126] fix pep8 format --- synology_api/downloadstation.py | 54 +++++++++++++++++---------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index 83b8061f..be3d41ba 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -775,10 +775,10 @@ def rss_feed_list(self, return self.request_data(api_name, api_path, param) def rss_feed_filter_list(self, - feed_id: Optional [int] = None, - offset: Optional[int] = None, - limit: Optional[int] = None - ) -> dict[str, object] | str: + feed_id: Optional[int] = None, + offset: Optional[int] = None, + limit: Optional[int] = None + ) -> dict[str, object] | str: """ Get RSS feed filter list. @@ -799,7 +799,8 @@ def rss_feed_filter_list(self, api_name = 'SYNO.DownloadStation' + self.download_st_version + '.RSS.Filter' info = self.download_list[api_name] api_path = info['path'] - param = {'version': info['maxVersion'], 'method': 'list', 'feed_id': feed_id} + param = {'version': info['maxVersion'], + 'method': 'list', 'feed_id': feed_id} if feed_id is None: return 'Enter a valid ID check if you have any with get_rss_info_list()' @@ -812,13 +813,13 @@ def rss_feed_filter_list(self, return self.request_data(api_name, api_path, param) def rss_feed_filter_add(self, - feed_id: int = None, - filter_name: str = None, - match: str = None, - not_match: str = None, - destination: str = None, - is_regex: bool = False - ) -> dict[str, object] | str: + feed_id: int = None, + filter_name: str = None, + match: str = None, + not_match: str = None, + destination: str = None, + is_regex: bool = False + ) -> dict[str, object] | str: """ Add RSS feed filter. @@ -848,8 +849,8 @@ def rss_feed_filter_add(self, api_path = info['path'] param = {'version': info['maxVersion'], 'method': 'add', 'feed_id': feed_id, - 'name':f'"{filter_name}"', 'match':f'"{match}"','not_match':f'"{not_match}"', - 'destination':f'"{destination}"', 'is_regex':str(is_regex).lower()} + 'name': f'"{filter_name}"', 'match': f'"{match}"', 'not_match': f'"{not_match}"', + 'destination': f'"{destination}"', 'is_regex': str(is_regex).lower()} if type(is_regex) is not bool: return 'Please set is_regex to True or False' @@ -860,13 +861,13 @@ def rss_feed_filter_add(self, return self.request_data(api_name, api_path, param) def rss_feed_filter_set(self, - filter_id: int = None, - filter_name: str = None, - match: str = None, - not_match: str = None, - destination: str = None, - is_regex: bool = False - ) -> dict[str, object] | str: + filter_id: int = None, + filter_name: str = None, + match: str = None, + not_match: str = None, + destination: str = None, + is_regex: bool = False + ) -> dict[str, object] | str: """ Set RSS feed filter. @@ -896,8 +897,8 @@ def rss_feed_filter_set(self, api_path = info['path'] param = {'version': info['maxVersion'], 'method': 'set', 'feed_id': 'null', 'id': filter_id, - 'name':f'"{filter_name}"', 'match':f'"{match}"','not_match':f'"{not_match}"', - 'destination':f'"{destination}"', 'is_regex':str(is_regex).lower()} + 'name': f'"{filter_name}"', 'match': f'"{match}"', 'not_match': f'"{not_match}"', + 'destination': f'"{destination}"', 'is_regex': str(is_regex).lower()} if type(is_regex) is not bool: return 'Please set is_regex to True or False' @@ -908,8 +909,8 @@ def rss_feed_filter_set(self, return self.request_data(api_name, api_path, param) def rss_feed_filter_delete(self, - filter_id: int = None, - ) -> dict[str, object] | str: + filter_id: int = None, + ) -> dict[str, object] | str: """ Delete RSS feed filter. @@ -928,7 +929,8 @@ def rss_feed_filter_delete(self, info = self.download_list[api_name] api_path = info['path'] - param = {'version': info['maxVersion'], 'method': 'delete', 'id': filter_id} + param = {'version': info['maxVersion'], + 'method': 'delete', 'id': filter_id} if filter_id is None: return 'Enter a valid ID check if you have any with rss_feed_filter_list()' From 3fdb96155e733352d734ecfd4cba6bad3b12d5a3 Mon Sep 17 00:00:00 2001 From: Sanich137 Date: Tue, 16 Dec 2025 12:37:59 +0300 Subject: [PATCH 126/126] fix error 'file not found error' on ds.create_task(file_path) --- synology_api/downloadstation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/synology_api/downloadstation.py b/synology_api/downloadstation.py index be3d41ba..60ea7069 100644 --- a/synology_api/downloadstation.py +++ b/synology_api/downloadstation.py @@ -498,7 +498,7 @@ def create_task(self, "create_list": "true" } data = get_data_for_request_from_file( - file_path='file_path', fields=fields, called_from='DownloadStation') + file_path=file_path, fields=fields, called_from='DownloadStation') return self.request_data(api_name, api_path, method='post', data=data, req_param={})