diff --git a/examples/env/delete_env/with_app.py b/examples/env/delete_env/with_app.py new file mode 100644 index 0000000..a5b486e --- /dev/null +++ b/examples/env/delete_env/with_app.py @@ -0,0 +1,13 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + +async def main(): + app = await client.app("your_app_id") + keys = [] # The keys you want to delete + result = await app.delete_envs(keys) # Deletes the specified environment variables + print("Remaining env variables: ", result) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/delete_env/with_client.py b/examples/env/delete_env/with_client.py new file mode 100644 index 0000000..8c7e53d --- /dev/null +++ b/examples/env/delete_env/with_client.py @@ -0,0 +1,13 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + keys = [] # The keys you want to delete + result = await client.delete_app_envs("app_id", keys) # Deletes the specified environment variables + print("Remaining env variables: ", result) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/get_env/with_app.py b/examples/env/get_env/with_app.py new file mode 100644 index 0000000..7c9b9b5 --- /dev/null +++ b/examples/env/get_env/with_app.py @@ -0,0 +1,13 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + app = await client.app("your_app_id") + envs = await app.get_envs() + print("App envs: ", envs) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/get_env/with_client.py b/examples/env/get_env/with_client.py new file mode 100644 index 0000000..c2e9062 --- /dev/null +++ b/examples/env/get_env/with_client.py @@ -0,0 +1,12 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + envs = await client.get_app_envs("app_id") + print("App envs: ", envs) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/overwrite_env/with_app.py b/examples/env/overwrite_env/with_app.py new file mode 100644 index 0000000..1d8fb0f --- /dev/null +++ b/examples/env/overwrite_env/with_app.py @@ -0,0 +1,14 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + app = await client.app("your_app_id") + envs = {"KEY": "VALUE"} # The new environment variables + result = await app.overwrite_env(envs) # Overwrites all environment variables and sets only the new ones + print("Overwrite envs result: ", result) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/overwrite_env/with_client.py b/examples/env/overwrite_env/with_client.py new file mode 100644 index 0000000..33f4b03 --- /dev/null +++ b/examples/env/overwrite_env/with_client.py @@ -0,0 +1,13 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + envs = {"ONLY_THIS": "present"} # The new environment variables + result = await client.overwrite_app_envs("app_id", envs) # Overwrites all environment variables and sets only the new ones + print("Overwrite envs result:", result) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/set_env/with_app.py b/examples/env/set_env/with_app.py new file mode 100644 index 0000000..ad2cdd7 --- /dev/null +++ b/examples/env/set_env/with_app.py @@ -0,0 +1,14 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + envs = {"KEY": "VALUE"} # The environment variables you want to set + app = await client.app("your_app_id") + result = await app.set_envs(envs) # Sets or updates the specified environment variables + print("Set envs result:", result) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/env/set_env/with_client.py b/examples/env/set_env/with_client.py new file mode 100644 index 0000000..40f1676 --- /dev/null +++ b/examples/env/set_env/with_client.py @@ -0,0 +1,13 @@ +import asyncio + +from squarecloud import Client + +client = Client(api_key="your_api_key") + + +async def main(): + envs = {"KEY": "VALUE"} # The environment variables you want to set + result = await client.set_app_envs("app_id", envs) # Sets or updates the specified environment variables + print("Set envs result:", result) + +asyncio.run(main()) \ No newline at end of file diff --git a/examples/backup/with_application.py b/examples/snapshots/with_application.py similarity index 63% rename from examples/backup/with_application.py rename to examples/snapshots/with_application.py index 3b51966..f2e4698 100644 --- a/examples/backup/with_application.py +++ b/examples/snapshots/with_application.py @@ -7,8 +7,7 @@ async def example() -> None: app = await client.app('application_id') - backup = await app.backup() - print(backup.url) # https://squarecloud.app/dashboard/backup/f.zip - + snapshot = await app.snapshot() + print(snapshot.url) # https://squarecloud.app/dashboard/backup/f.zip asyncio.run(example()) diff --git a/examples/backup/with_client.py b/examples/snapshots/with_client.py similarity index 52% rename from examples/backup/with_client.py rename to examples/snapshots/with_client.py index a59e1a3..b32f9a8 100644 --- a/examples/backup/with_client.py +++ b/examples/snapshots/with_client.py @@ -6,8 +6,8 @@ async def example() -> None: - backup = await client.backup('application_id') - print(backup.url) # https://squarecloud.app/dashboard/backup/f.zip + snapshot = await client.snapshot('application_id') + print(snapshot.url) # https://squarecloud.app/dashboard/backup/f.zip asyncio.run(example()) diff --git a/pyproject.toml b/pyproject.toml index 56a68ca..8f39674 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = 'squarecloud-api' -version = '3.7.5' +version = '3.8.0' description = 'SquareCloud API wrapper' authors = ['Robert Nogueira '] repository = 'https://github.com/squarecloudofc/wrapper-api-py' diff --git a/squarecloud/__init__.py b/squarecloud/__init__.py index cbd6ec3..651590c 100644 --- a/squarecloud/__init__.py +++ b/squarecloud/__init__.py @@ -5,8 +5,8 @@ from .client import Client from .data import ( AppData, - Backup, - BackupInfo, + Snapshot, + SnapshotInfo, DeployData, DNSRecord, DomainAnalytics, @@ -29,8 +29,8 @@ 'Endpoint', 'Response', 'AppData', - 'Backup', - 'BackupInfo', + 'Snapshot', + 'SnapshotInfo', 'DeployData', 'DNSRecord', 'DomainAnalytics', diff --git a/squarecloud/app.py b/squarecloud/app.py index 8670583..aae0d59 100644 --- a/squarecloud/app.py +++ b/squarecloud/app.py @@ -4,13 +4,15 @@ from io import BytesIO from typing import TYPE_CHECKING, Any, Callable, Coroutine, TypeVar +from typing_extensions import deprecated + from squarecloud import errors from ._internal.decorators import validate from .data import ( AppData, - Backup, - BackupInfo, + Snapshot, + SnapshotInfo, DeployData, DNSRecord, DomainAnalytics, @@ -53,7 +55,7 @@ def __init__(self) -> None: """ self._status: StatusData | None = None self._logs: LogsData | None = None - self._backup: Backup | None = None + self._backup: Snapshot | None = None self._app_data: AppData | None = None @property @@ -79,7 +81,8 @@ def logs(self) -> LogsData: return self._logs @property - def backup(self) -> Backup: + @deprecated("this property will be removed in future versions, use the 'snapshot' property instead") + def backup(self) -> Snapshot: """ The backup method is a property that returns the cached Backup of the application. @@ -130,7 +133,7 @@ def update(self, *args) -> None: self._status = arg elif isinstance(arg, LogsData): self._logs = arg - elif isinstance(arg, Backup): + elif isinstance(arg, Snapshot): self._backup = arg elif isinstance(arg, AppData): self._app_data = arg @@ -140,7 +143,7 @@ def update(self, *args) -> None: for i in [ StatusData, LogsData, - Backup, + Snapshot, AppData, ] ] @@ -458,8 +461,9 @@ async def status(self, *_args, **_kwargs) -> StatusData: return status @_update_cache - @_notify_listener(Endpoint.backup()) - async def backup(self, *_args, **_kwargs) -> Backup: + @_notify_listener(Endpoint.snapshot()) + @deprecated("this method will be removed in future versions, use the 'snapshot' method instead") + async def backup(self, *_args, **_kwargs) -> Snapshot: """ The backup function is used to create a backup of the application. @@ -467,8 +471,21 @@ async def backup(self, *_args, **_kwargs) -> Backup: :return: A Backup object :rtype: Backup """ - backup: Backup = await self.client.backup(self.id) + backup: Snapshot = await self.client.snapshot(self.id) return backup + + @_update_cache + @_notify_listener(Endpoint.snapshot()) + async def snapshot(self, *_args, **_kwargs) -> Snapshot: + """ + The Snapshot function is used to create a snapshot of the application. + + :param self: Refer to the class instance + :return: A Snapshot object + :rtype: Snapshot + """ + snapshot: Snapshot = await self.client.snapshot(self.id) + return snapshot async def start(self) -> Response: """ @@ -638,23 +655,61 @@ async def github_integration(self, access_token: str) -> str: return webhook async def domain_analytics(self) -> DomainAnalytics: + """ + Retrieve analytics data for the application's domain. + + :param self: Refer to the instance of the class. + :returns: An instance of :class:`DomainAnalytics` containing analytics data for the domain. + :rtype: DomainAnalytics + :raises Exception: If the analytics data could not be retrieved. + """ analytics: DomainAnalytics = await self.client.domain_analytics( self.id, avoid_listener=True ) - return analytics # TODO: + return analytics async def set_custom_domain(self, custom_domain: str) -> Response: + """ + Sets a custom domain for the application. + + :param custom_domain: The custom domain to be assigned to the application. + :type custom_domain: str + :return: The response from the domain assignment operation. + :rtype: Response + """ response: Response = await self.client.set_custom_domain( self.id, custom_domain, avoid_listener=True ) return response - async def all_backups(self) -> Response: - backups: list[BackupInfo] = await self.client.all_app_backups(self.id) + @deprecated("this method will be removed in future versions, use the 'all_snapshots' method instead") + async def all_backups(self) -> list[SnapshotInfo]: + backups: list[SnapshotInfo] = await self.client.all_app_snapshots(self.id) return backups + + async def all_snapshots(self) -> list[SnapshotInfo]: + """ + Retrieve all snapshots of the application. + + :return: A list of SnapshotInfo objects representing all snapshots of the application. + :rtype: list[SnapshotInfo] + """ + snapshots: list[SnapshotInfo] = await self.client.all_app_snapshots(self.id) + return snapshots @validate async def move_file(self, origin: str, dest: str) -> Response: + """ + Moves a file from the origin path to the destination path within the application. + + :param origin: The source path of the file to be moved. + :type origin: str + :param dest: The destination path where the file should be moved. + :type dest: str + :return: A Response object containing the result of the file move operation. + :rtype: Response + """ + return await self.client.move_app_file(self.id, origin, dest) async def current_integration(self) -> Response: @@ -662,4 +717,53 @@ async def current_integration(self) -> Response: @_notify_listener(Endpoint.dns_records()) async def dns_records(self) -> list[DNSRecord]: + """ + Retrieve the DNS records associated with the application. + + :returns: A list of DNSRecord objects representing the DNS records. + :rtype: list[DNSRecord] + """ + return await self.client.dns_records(self.id) + + async def get_envs(self) -> dict[str, str]: + """ + Get environment variables of the application. + + :return: A dictionary of the environment variables that were set. + :rtype: dict[str, str] + """ + return await self.client.get_app_envs(self.id) + + async def set_envs(self, envs: dict[str, str]) -> dict[str,str]: + """ + Set environment variables or edits for the application. + + :param envs: A dictionary containing environment variable names and their corresponding values. + :type envs: dict[str, str] + :return: A dictionary of the environment variables that were set. + :rtype: dict[str, str] + """ + return await self.client.set_app_envs(self.id, envs) + + async def delete_envs(self, keys: list[str]) -> dict[str,str]: + """ + Deletes environment variables from the application. + + :param keys: A list of environment variable keys to be deleted. + :type keys: list[str] + :returns: A dictionary containing the remaining variables. + :rtype: dict[str, str] + """ + return await self.client.delete_app_envs(self.id, keys) + + async def overwrite_env(self, envs: dict[str, str]) -> dict[str,str]: + """ + Overwrites the environment variables for the application. + + :param envs: A dictionary containing the environment variables to set, where keys are variable names and values are their corresponding values. + :type envs: dict[str, str] + :return: A dictionary of the environment variables. + :rtype: dict[str, str] + """ + return await self.client.overwrite_app_envs(self.id, envs) \ No newline at end of file diff --git a/squarecloud/client.py b/squarecloud/client.py index 067a7dd..9e8e077 100644 --- a/squarecloud/client.py +++ b/squarecloud/client.py @@ -4,7 +4,7 @@ from functools import wraps from io import BytesIO -from typing import Any, Callable, Literal, ParamSpec, TextIO, TypeVar +from typing import Any, Callable, Literal, ParamSpec, TypeVar from typing_extensions import deprecated @@ -12,8 +12,8 @@ from .app import Application from .data import ( AppData, - Backup, - BackupInfo, + Snapshot, + SnapshotInfo, DeployData, DNSRecord, DomainAnalytics, @@ -36,66 +36,6 @@ R = TypeVar("R") -@deprecated( - "create_config_file is deprecated, " - "use squarecloud.utils.ConfigFile instead." -) -def create_config_file( - path: str, - display_name: str, - main: str, - memory: int, - version: Literal["recommended", "latest"] = "recommended", - description: str | None = None, - subdomain: str | None = None, - start: str | None = None, - auto_restart: bool = False, - **kwargs, -) -> TextIO | str: - """ - The create_config_file function creates a squarecloud.app file in the - specified path, with the given parameters. - The function takes in 8 arguments: - - :param path: str: Specify the path to the folder where you want to create - your config file - :param display_name: str: Set the display name of your app - :param main: str: Specify the file that will be executed when the app - is started - :param memory: int: Set the memory of the app - :param version: Literal['recommended', 'latest']: Ensure that the version - is either 'recommended' or 'latest'. - :param description: str | None: Specify a description for the app - :param subdomain: str | None: Specify the subdomain of your app - :param start: str | None: Specify the command that should be run when the - application starts - :param auto_restart: bool | None: Determine if the app should restart - automatically after a crash - :return: File content - :rtype: str - """ - content: str = "" - optionals: dict[str, Any] = { - "DISPLAY_NAME": display_name, - "MAIN": main, - "MEMORY": memory, - "VERSION": version, - "DESCRIPTION": description, - "SUBDOMAIN": subdomain, - "START": start, - "AUTORESTART": auto_restart, - } - for key, value in optionals.items(): - if value: - string: str = f"{key}={value}\n" - content += string - if kwargs.get("save", True): - with open(f"./{path}/squarecloud.app", "w", encoding="utf-8") as file: - file.write(content) - return file - return content - - class Client(RequestListenerManager): """A client for interacting with the SquareCloud API.""" @@ -338,15 +278,38 @@ async def restart_app(self, app_id: str, **_kwargs) -> Response: return await self._http.restart_application(app_id) @validate - @_notify_listener(Endpoint.backup()) - async def backup(self, app_id: str, **_kwargs) -> Backup: + @_notify_listener(Endpoint.snapshot()) + @deprecated("this method will be removed in future versions, use the 'snapshot' method instead") + async def backup(self, app_id: str, **_kwargs) -> Snapshot: """ The backup method is used to backup an application. :param app_id: Specify the application id :param _kwargs: Keyword arguments - :return: A Backup object - :rtype: Backup + :return: A Snapshot object + :rtype: Snapshot + + :raises NotFoundError: Raised when the request status code is 404 + :raises BadRequestError: Raised when the request status code is 400 + :raises AuthenticationFailure: Raised when the request status + code is 401 + :raises TooManyRequestsError: Raised when the request status + code is 429 + """ + response: Response = await self._http.snapshot(app_id) + payload: dict[str, Any] = response.response + return Snapshot(**payload) + + @validate + @_notify_listener(Endpoint.snapshot()) + async def snapshot(self, app_id: str, **_kwargs) -> Snapshot: + """ + The snapshot method is used to save a snapshot of an application. + + :param app_id: Specify the application id + :param _kwargs: Keyword arguments + :return: A Snapshot object + :rtype: Snapshot :raises NotFoundError: Raised when the request status code is 404 :raises BadRequestError: Raised when the request status code is 400 @@ -355,9 +318,9 @@ async def backup(self, app_id: str, **_kwargs) -> Backup: :raises TooManyRequestsError: Raised when the request status code is 429 """ - response: Response = await self._http.backup(app_id) + response: Response = await self._http.snapshot(app_id) payload: dict[str, Any] = response.response - return Backup(**payload) + return Snapshot(**payload) @validate @_notify_listener(Endpoint.delete_app()) @@ -540,7 +503,7 @@ async def app_files_list( if not response.response: return [] return [ - FileInfo(**data, app_id=app_id, path=path + f"/{data.get('name')}") + FileInfo(**data, app_id=app_id, path=path + f"{data.get('name')}") for data in response.response ] @@ -733,21 +696,54 @@ async def domain_analytics( response: Response = await self._http.domain_analytics( app_id=app_id, ) - return DomainAnalytics(**response.response) @validate - @_notify_listener(Endpoint.all_backups()) + @_notify_listener(Endpoint.all_snapshots()) + @deprecated("this method will be removed in future versions, use the 'all_app_snapshots' method instead") async def all_app_backups( self, app_id: str, **_kwargs - ) -> list[BackupInfo]: - response: Response = await self._http.get_all_app_backups( + ) -> list[SnapshotInfo]: + response: Response = await self._http.get_all_app_snapshots( + app_id=app_id + ) + return [SnapshotInfo(**backup_data) for backup_data in response.response] + + @validate + @_notify_listener(Endpoint.all_snapshots()) + async def all_app_snapshots( + self, app_id: str, **_kwargs + ) -> list[SnapshotInfo]: + """ + Retrieve all snapshots for a specific application. + This method fetches a list of snapshots associated with the + given application ID and returns them as a list of `SnapshotInfo` objects. + :param app_id: Specify the application by id. + :type app_id: str + :param _kwargs: Additional keyword arguments. + :type _kwargs: dict + :return: A list of `SnapshotInfo` objects representing the snapshots of + the specified application. + :rtype: list[SnapshotInfo] + """ + response: Response = await self._http.get_all_app_snapshots( app_id=app_id ) - return [BackupInfo(**backup_data) for backup_data in response.response] + return [SnapshotInfo(**snapshot_data) for snapshot_data in response.response] @_notify_listener(Endpoint.all_apps_status()) async def all_apps_status(self, **_kwargs) -> list[ResumedStatus]: + """ + Retrieve the status of all applications. + This method fetches the status of all applications + and returns a list of `ResumedStatus` objects for applications + that are currently running. + :param _kwargs: Additional keyword arguments. + :type _kwargs: dict + :return: A list of `ResumedStatus` objects representing the status + of running applications. + :rtype: list[ResumedStatus] + """ response: Response = await self._http.all_apps_status() all_status = [] for status in response.response: @@ -760,6 +756,19 @@ async def all_apps_status(self, **_kwargs) -> list[ResumedStatus]: async def move_app_file( self, app_id: str, origin: str, dest: str, **_kwargs ) -> Response: + """ + Moves a file within an application from the origin path to the destination path. + :param app_id: Specify the application by id. + :type app_id: str + :param origin: The current path of the file to be moved. + :type origin: str + :param dest: The target path where the file should be moved. + :type dest: str + :param _kwargs: Additional keyword arguments. + :type _kwargs: dict + :return: The response object containing the result of the move operation. + :rtype: Response + """ response: Response = await self._http.move_app_file( app_id=app_id, origin=origin, dest=dest ) @@ -768,6 +777,14 @@ async def move_app_file( @validate @_notify_listener(Endpoint.dns_records()) async def dns_records(self, app_id: str) -> list[DNSRecord]: + """ + Retrieve DNS records for a specific application. + :param app_id: Specify the application by id. + :type app_id: str + :return: A list of DNSRecord objects representing the DNS records of the application. + :rtype: list[DNSRecord] + """ + response: Response = await self._http.dns_records(app_id) return [DNSRecord(**data) for data in response.response] @@ -778,3 +795,76 @@ async def current_app_integration(self, app_id: str) -> str | None: app_id ) return response.response["webhook"] + + async def get_app_envs(self, app_id: str) -> dict[str, str]: + """ + Retrieve the environment variables of a specific application. + :param app_id: Specify the application by id. + :type app_id: str + :return: A dictionary containing the environment variables as key-value pairs. + :rtype: dict[str, str] + """ + response: Response = await self._http.get_environment_variables(app_id) + return response.response + + async def set_app_envs(self, app_id: str, envs: dict[str, str]) -> dict[str, str]: + """ + Sets or edits environment variables for a specific application. + This method sends a request to update the environment variables of the + specified application with the provided key-value pairs. + :param app_id: Specify the application by id. + :type app_id: str + :param envs: A dictionary containing the environment variables to set, + where the keys are variable names and the values are their + corresponding values. + :type envs: dict[str, str] + :return: A dictionary containing the updated environment with all variables. + :rtype: dict[str, str] + :raises HTTPException: If the HTTP request fails or returns an error response. + """ + + response: Response = await self._http.set_environment_variable(app_id, envs) + return response.response + + async def delete_app_envs(self, app_id: str, keys: list[str]) -> dict[str, str]: + """ + Deletes specified environment variables for a given application. + :param app_id: Specify the application by id. + :type app_id: str + :param keys: A list of keys representing the environment variables to be deleted. + :type keys: list[str] + :return: A dictionary containing the remaining variables. + :rtype: dict[str, str] + """ + response: Response = await self._http.delete_environment_variable(app_id, keys) + return response.response + + async def overwrite_app_envs(self, app_id: str, envs: dict[str, str]) -> dict[str, str]: + """ + Overwrite the environment variables of a specific application. + This method sets the dictionary provided as the new environment for the application. + :param app_id: Specify the application by id. + :type app_id: str + :param envs: A dictionary containing the new environment variables to set + for the application. Keys and values must both be strings. + :type envs: dict[str, str] + :return: A dictionary containing the new environment after overwriting the + environment variables. + :rtype: dict[str, str] + """ + response: Response = await self._http.overwrite_environment_variables(app_id, envs) + return response.response + + async def clear_app_envs(self, app_id: str) -> dict[str, str]: + """ + Clears all environment variables for the specified application. + This method overwrites the application's environment variables with an empty dictionary, + effectively removing all existing environment variables. + + :param app_id: Specify the application by id. + :type app_id: str + :return: A dictionary containing the response from the server. + :rtype: dict[str, str] + """ + response: Response = await self._http.overwrite_environment_variables(app_id, {}) + return response.response \ No newline at end of file diff --git a/squarecloud/data.py b/squarecloud/data.py index e13a92a..e698b8d 100644 --- a/squarecloud/data.py +++ b/squarecloud/data.py @@ -195,19 +195,19 @@ async def example(): return isinstance(other, LogsData) and self.logs == other.logs -class BackupInfo(BaseDataClass): +class SnapshotInfo(BaseDataClass): name: str size: int modified: datetime key: str -class Backup: +class Snapshot: """ - Backup data class + Snapshot data class - :ivar url: Url for download your backup - :ivar key: The backup's key + :ivar url: Url for download your Snapshot + :ivar key: The Snapshot's key :type url: str :type key: str @@ -219,12 +219,12 @@ def __init__(self, url: str, key: str) -> None: self.url = url self.key = key - def to_dict(self) -> None: + def to_dict(self) -> dict[str, str]: return {'url': self.url, 'key': self.key} async def download(self, path: str = './') -> zipfile.ZipFile: file_name = os.path.basename(self.url.split('?')[0]) - content = await HTTPClient.fetch_backup_content(self.url) + content = await HTTPClient.fetch_snapshot_content(self.url) with zipfile.ZipFile(f'{path}/{file_name}', 'w') as zip_file: zip_file.writestr(f'{path}/{file_name}', content) return zip_file @@ -283,9 +283,9 @@ class FileInfo(BaseDataClass): app_id: str type: Literal['file', 'directory'] name: str - lastModified: int | float | None # noqa: N815: Ignore mixedCase naming convention path: str size: int = 0 + lastModified: int | float | None = None # noqa: N815: Ignore mixedCase naming convention class DeployData(BaseDataClass): @@ -294,38 +294,48 @@ class DeployData(BaseDataClass): date: datetime -class AnalyticsTotal(BaseDataClass): - visits: int - megabytes: float - bytes: int - - class DomainAnalytics(BaseDataClass): - class Analytics(BaseDataClass): - total: list[AnalyticsTotal] - countries: list[Any] - methods: list[Any] - referers: list[Any] - browsers: list[Any] - deviceTypes: list[ - Any - ] # noqa: N815: Ignore mixedCase naming convention - operatingSystems: list[ - Any - ] # noqa: N815: Ignore mixedCase naming convention - agents: list[Any] - hosts: list[Any] - paths: list[Any] - - class Domain(BaseDataClass): - hostname: str - analytics: DomainAnalytics.Analytics | None - - class Custom(BaseDataClass): - analytics: DomainAnalytics.Analytics | None - - domain: Domain - custom: Custom + class BaseAnalytics(BaseDataClass): + visits: int + requests: int + bytes: int + date: str + @property + def date_time(self) -> datetime: + "retrieves the date as a datetime object" + return datetime.fromisoformat(self.date) + class ExtraBaseAnalytics(BaseAnalytics): + type: str + class Visits(BaseAnalytics): + pass + class Countries(ExtraBaseAnalytics): + pass + class Devices(ExtraBaseAnalytics): + pass + class Os(ExtraBaseAnalytics): + pass + class Browsers(ExtraBaseAnalytics): + pass + class Protocols(ExtraBaseAnalytics): + pass + class Methods(ExtraBaseAnalytics): + pass + class Paths(ExtraBaseAnalytics): + pass + class Referers(ExtraBaseAnalytics): + pass + class Providers(ExtraBaseAnalytics): + pass + visits: list[Visits] + countries: list[Countries] + devices: list[Devices] + os: list[Os] + browsers: list[Browsers] + protocols: list[Protocols] + methods: list[Methods] + paths: list[Paths] + referers: list[Referers] + providers: list[Providers] class DNSRecord(BaseDataClass): diff --git a/squarecloud/http/endpoints.py b/squarecloud/http/endpoints.py index 7c73d1e..5c5b891 100644 --- a/squarecloud/http/endpoints.py +++ b/squarecloud/http/endpoints.py @@ -9,12 +9,12 @@ class Endpoint: 'APP_DATA': {'METHOD': 'GET', 'PATH': '/apps/{app_id}'}, 'APP_STATUS': {'METHOD': 'GET', 'PATH': '/apps/{app_id}/status'}, 'ALL_APPS_STATUS': {'METHOD': 'GET', 'PATH': '/apps/status'}, - 'ALL_BACKUPS': {'METHOD': 'GET', 'PATH': '/apps/{app_id}/snapshots'}, + 'ALL_SNAPSHOTS': {'METHOD': 'GET', 'PATH': '/apps/{app_id}/snapshots'}, 'LOGS': {'METHOD': 'GET', 'PATH': '/apps/{app_id}/logs'}, 'START': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/start'}, 'STOP': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/stop'}, 'RESTART': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/restart'}, - 'BACKUP': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/snapshots'}, + 'SNAPSHOT': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/snapshots'}, 'COMMIT': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/commit'}, 'DELETE_APP': {'METHOD': 'DELETE', 'PATH': '/apps/{app_id}'}, 'UPLOAD_APP': {'METHOD': 'POST', 'PATH': '/apps'}, @@ -56,6 +56,10 @@ class Endpoint: 'PATH': '/apps/{app_id}/network/analytics', }, 'DNSRECORDS': {'METHOD': 'GET', 'PATH': '/apps/{app_id}/network/dns'}, + 'ENVS_GET': {'METHOD': 'GET', 'PATH': '/apps/{app_id}/envs'}, + 'ENVS_PUT': {'METHOD': 'PUT', 'PATH': '/apps/{app_id}/envs'}, + 'ENVS_POST': {'METHOD': 'POST', 'PATH': '/apps/{app_id}/envs'}, + 'ENVS_DELETE': {'METHOD': 'DELETE', 'PATH': '/apps/{app_id}/envs'}, } def __init__(self, name: str) -> None: @@ -145,12 +149,12 @@ def restart(cls) -> Endpoint: return cls('RESTART') @classmethod - def backup(cls) -> Endpoint: + def snapshot(cls) -> Endpoint: """ Returns an Endpoint object that represents the /apps/{app_id}/snapshots endpoint. """ - return cls('BACKUP') + return cls('SNAPSHOT') @classmethod def commit(cls) -> Endpoint: @@ -241,12 +245,12 @@ def custom_domain(cls) -> Endpoint: return cls('CUSTOM_DOMAIN') @classmethod - def all_backups(cls) -> Endpoint: + def all_snapshots(cls) -> Endpoint: """ Returns an Endpoint object that represents the /apps/{app_id}/snapshots endpoint. """ - return cls('ALL_BACKUPS') + return cls('ALL_SNAPSHOTS') @classmethod def all_apps_status(cls) -> Endpoint: @@ -279,6 +283,38 @@ def dns_records(cls) -> Endpoint: /apps/{app_id}/network/dns """ return cls('DNSRECORDS') + + @classmethod + def envs_get(cls) -> Endpoint: + """ + Returns an Endpoint object that represents the + /apps/{app_id}/envs GET endpoint. + """ + return cls('ENVS_GET') + + @classmethod + def envs_put(cls) -> Endpoint: + """ + Returns an Endpoint object that represents the + /apps/{app_id}/envs PUT endpoint. + """ + return cls('ENVS_PUT') + + @classmethod + def envs_post(cls) -> Endpoint: + """ + Returns an Endpoint object that represents the + /apps/{app_id}/envs POST endpoint. + """ + return cls('ENVS_POST') + + @classmethod + def envs_delete(cls) -> Endpoint: + """ + Returns an Endpoint object that represents the + /apps/{app_id}/envs DELETE endpoint. + """ + return cls('ENVS_DELETE') # pylint: disable=too-few-public-methods diff --git a/squarecloud/http/http_client.py b/squarecloud/http/http_client.py index a27da76..839f516 100644 --- a/squarecloud/http/http_client.py +++ b/squarecloud/http/http_client.py @@ -231,7 +231,7 @@ async def request(self, route: Router, **kwargs: Any) -> Response: return response @classmethod - async def fetch_backup_content(cls, url: str) -> bytes: + async def fetch_snapshot_content(cls, url: str) -> bytes: async with aiohttp.ClientSession() as session: async with session.get(url) as response: return await response.read() @@ -348,7 +348,7 @@ async def restart_application(self, app_id: str) -> Response: response: Response = await self.request(route) return response - async def backup(self, app_id: str) -> Response: + async def snapshot(self, app_id: str) -> Response: """ Backup a hosted application @@ -363,7 +363,7 @@ async def backup(self, app_id: str) -> Response: :raises TooManyRequestsError: Raised when the request status code is 429 """ - route: Router = Router(Endpoint.backup(), app_id=app_id) + route: Router = Router(Endpoint.snapshot(), app_id=app_id) response: Response = await self.request(route) return response @@ -512,7 +512,7 @@ async def create_app_file( """ route: Router = Router(Endpoint.files_create(), app_id=app_id) response: Response = await self.request( - route, json={'buffer': file, 'path': '/' + path} + route, json={'content': file, 'path': '/' + path} ) return response @@ -655,7 +655,7 @@ async def domain_analytics(self, app_id: str) -> Response: response: Response = await self.request(route) return response - async def get_all_app_backups(self, app_id: str) -> Response: + async def get_all_app_snapshots(self, app_id: str) -> Response: """ Returns a list of all backups of the specified application @@ -669,7 +669,7 @@ async def get_all_app_backups(self, app_id: str) -> Response: :raises TooManyRequestsError: Raised when the request status code is 429 """ - route: Router = Router(Endpoint.all_backups(), app_id=app_id) + route: Router = Router(Endpoint.all_snapshots(), app_id=app_id) response: Response = await self.request(route) return response @@ -757,3 +757,68 @@ def last_response(self) -> Response | None: :rtype: Response | None """ return self._last_response + + async def get_environment_variables(self, app_id: str) -> Response: + """ + Retrieve the environment variables for a specific application. + + :param app_id: The unique identifier of the application. + :type app_id: str + :return: The response containing the environment variables. + :rtype: Response + """ + route: Router = Router(Endpoint.envs_get(), app_id=app_id) + response: Response = await self.request(route) + return response + + async def set_environment_variable(self, app_id: str, keys: dict[str, str]) -> Response: + """ + Sets environment variables for a specific application. + This method sends a request to set the specified environment variables + for the application identified by the given `app_id`. + :param app_id: The ID of the application for which the environment + variables will be set. + :type app_id: str + :param keys: A dictionary containing the environment variable names + as keys and their corresponding values. + :type keys: dict[str, str] + :return: The response object containing the result of the operation. + :rtype: Response + """ + + route: Router = Router(Endpoint.envs_post(), app_id=app_id) + response: Response = await self.request(route, json={"envs": keys}) + return response + + async def delete_environment_variable(self, app_id: str, keys: list[str]) -> Response: + """ + Deletes one or more environment variables for a specific application. + :param app_id: The ID of the application whose environment variables are to be deleted. + :type app_id: str + :param keys: A list of environment variable keys to be deleted. + :type keys: list[str] + :return: The response object containing the result of the deletion operation. + :rtype: Response + """ + route: Router = Router(Endpoint.envs_delete(), app_id=app_id) + response: Response = await self.request(route, json={"envs": keys}) + return response + + async def overwrite_environment_variables(self, app_id: str, keys: dict[str, str]) -> Response: + """ + Overwrites the environment variables for a specific application. + This method sends a request to update the environment variables of the + specified application with the provided key-value pairs. + :param app_id: The ID of the application whose environment variables + are to be overwritten. + :type app_id: str + :param keys: A dictionary containing the environment variable keys and + their corresponding values to be set. + :type keys: dict[str, str] + :return: The response object containing the result of the operation. + :rtype: Response + """ + + route: Router = Router(Endpoint.envs_put(), app_id=app_id) + response: Response = await self.request(route, json={"envs": keys}) + return response \ No newline at end of file diff --git a/squarecloud/listeners/__init__.py b/squarecloud/listeners/__init__.py index a67398f..c758251 100644 --- a/squarecloud/listeners/__init__.py +++ b/squarecloud/listeners/__init__.py @@ -167,5 +167,5 @@ def cast_to_pydantic_model( data.AppData, data.StatusData, data.LogsData, - data.Backup, + data.Snapshot, ] diff --git a/squarecloud/listeners/capture_listener.py b/squarecloud/listeners/capture_listener.py index 2038664..69172af 100644 --- a/squarecloud/listeners/capture_listener.py +++ b/squarecloud/listeners/capture_listener.py @@ -15,7 +15,7 @@ data.AppData, data.StatusData, data.LogsData, - data.Backup, + data.Snapshot, ] @@ -38,7 +38,7 @@ def include_listener(self, listener: Listener) -> Listener: allowed_endpoints: tuple[Endpoint, Endpoint, Endpoint, Endpoint] = ( Endpoint.logs(), Endpoint.app_status(), - Endpoint.backup(), + Endpoint.snapshot(), Endpoint.app_data(), )