From 6e2d6cb1c8e59f37aa1cdbcacd0cefbe1e3830df Mon Sep 17 00:00:00 2001 From: Yuli Stremovsky Date: Mon, 10 Aug 2026 18:30:54 +0300 Subject: [PATCH 1/2] Add File API methods and drop internal portal endpoints Co-Authored-By: Claude Opus 5 (1M context) --- databunkerpro/api.py | 183 +++++++++++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 48 deletions(-) diff --git a/databunkerpro/api.py b/databunkerpro/api.py index 773b826..62883c6 100644 --- a/databunkerpro/api.py +++ b/databunkerpro/api.py @@ -121,6 +121,15 @@ class BasicOptions(TypedDict, total=False): slidingtime: Optional[str] +class FileOptions(TypedDict, total=False): + """Options for storing a file.""" + + mimetype: Optional[str] + tags: Optional[Union[List[str], str]] + finaltime: Optional[str] + slidingtime: Optional[str] + + class TokenOptions(TypedDict, total=False): """Options for token operations.""" @@ -493,45 +502,6 @@ def list_user_versions( } return self._make_request("UserListVersions", data, request_metadata) - # User Authentication - def prelogin_user( - self, - mode: str, - identity: str, - code: str, - captchacode: str, - request_metadata: Optional[Dict[str, Any]] = None, - ) -> Dict[str, Any]: - """Perform pre-login operations for a user.""" - data = { - "mode": mode, - "identity": identity, - "code": code, - "captchacode": captchacode, - } - return self._make_request("UserPrelogin", data, request_metadata) - - def login_user( - self, - mode: str, - identity: str, - smscode: str, - request_metadata: Optional[Dict[str, Any]] = None, - ) -> Dict[str, Any]: - """Log in a user with SMS verification.""" - data = { - "mode": mode, - "identity": identity, - "smscode": smscode, - } - return self._make_request("UserLogin", data, request_metadata) - - def create_captcha( - self, request_metadata: Optional[Dict[str, Any]] = None - ) -> Dict[str, Any]: - """Create a captcha for user verification.""" - return self._make_request("CaptchaCreate", None, request_metadata) - def create_user_x_token( self, mode: str, @@ -713,6 +683,132 @@ def list_app_data_versions( } return self._make_request("AppdataListVersions", data, request_metadata) + def delete_app_data( + self, + mode: str, + identity: str, + appname: str, + request_metadata: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """Delete application data for a user.""" + data = { + "mode": mode, + "identity": identity, + "appname": appname, + } + return self._make_request("AppdataDelete", data, request_metadata) + + # File Storage + def create_file( + self, + mode: str, + identity: str, + filename: str, + filedata: str, + options: Optional[FileOptions] = None, + request_metadata: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """Store an encrypted file for a user. + + Args: + mode: User identification mode (login, token, email, phone, custom) + identity: User identifier corresponding to the mode + filename: Name of the file + filedata: File content, base64-encoded + options: Optional mimetype, tags, slidingtime, finaltime + request_metadata: Additional metadata to include with the request + + Returns: + The stored file information, including its fileuuid + """ + data: Dict[str, Any] = { + "mode": mode, + "identity": identity, + "filename": filename, + "filedata": filedata, + } + if options: + for key in ("mimetype", "tags", "slidingtime", "finaltime"): + if key in options: + data[key] = options[key] + return self._make_request("FileCreate", data, request_metadata) + + def get_file( + self, + mode: str, + identity: str, + fileuuid: Optional[str] = None, + filename: Optional[str] = None, + raw: Optional[bool] = None, + request_metadata: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """Get a user file, selected by fileuuid or filename. + + At least one of fileuuid or filename is required. When selecting by + filename, the most recently created file with that name is returned. + """ + data: Dict[str, Any] = { + "mode": mode, + "identity": identity, + } + if fileuuid is not None: + data["fileuuid"] = fileuuid + if filename is not None: + data["filename"] = filename + if raw is not None: + data["raw"] = raw + return self._make_request("FileGet", data, request_metadata) + + def list_user_files( + self, + mode: str, + identity: str, + request_metadata: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """List the metadata of all files owned by a user.""" + data = { + "mode": mode, + "identity": identity, + } + return self._make_request("FileListUserFiles", data, request_metadata) + + def replace_file_tags( + self, + mode: str, + identity: str, + fileuuid: str, + tags: Union[List[str], str], + request_metadata: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """Replace the complete tag set on a file. + + The supplied list is authoritative — tags not included are removed. + Tags are lowercased and de-duplicated, must match + ^[a-z0-9][a-z0-9._-]{0,49}$, and at most 16 are kept. + """ + data: Dict[str, Any] = { + "mode": mode, + "identity": identity, + "fileuuid": fileuuid, + "tags": tags, + } + return self._make_request("FileReplaceTags", data, request_metadata) + + def delete_file( + self, + mode: str, + identity: str, + fileuuid: str, + request_metadata: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + """Delete a user file.""" + data = { + "mode": mode, + "identity": identity, + "fileuuid": fileuuid, + } + return self._make_request("FileDelete", data, request_metadata) + # Legal Basis Management def create_legal_basis( self, @@ -1377,15 +1473,6 @@ def bulk_delete_tokens( } return self._make_request("BulkDeleteTokens", data, request_metadata) - # System Configuration - def get_ui_conf(self) -> Dict[str, Any]: - """Get UI configuration.""" - return self._make_request("TenantGetUIConf") - - def get_tenant_conf(self) -> Dict[str, Any]: - """Get tenant configuration.""" - return self._make_request("TenantGetUIConf") - def get_user_html_report( self, mode: str, From 914950945c2a20cd8f02078bba545adc757ca4f2 Mon Sep 17 00:00:00 2001 From: Yuli Stremovsky Date: Mon, 10 Aug 2026 18:31:37 +0300 Subject: [PATCH 2/2] Bump version to 0.1.5 Co-Authored-By: Claude Opus 5 (1M context) --- databunkerpro/__init__.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/databunkerpro/__init__.py b/databunkerpro/__init__.py index f8335ac..488b9f8 100644 --- a/databunkerpro/__init__.py +++ b/databunkerpro/__init__.py @@ -5,5 +5,5 @@ from .api import DatabunkerproAPI -__version__ = "0.1.1" +__version__ = "0.1.5" __all__ = ["DatabunkerproAPI"] diff --git a/setup.py b/setup.py index 795ed36..4c94fc1 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="databunkerpro", - version="0.1.4", + version="0.1.5", author="Databunker team", author_email="hello@databunker.org", description="Python client library for DatabunkerPro API",