Skip to content

Commit e8f4892

Browse files
✨ feat: added support to new endpoints in cli and wrapper
1 parent aa45922 commit e8f4892

File tree

8 files changed

+291
-20
lines changed

8 files changed

+291
-20
lines changed

squarecloud/app.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
AppData,
1111
BackupData,
1212
DeployData,
13+
DomainAnalytics,
1314
FileInfo,
1415
LogsData,
1516
StatusData,
@@ -619,3 +620,15 @@ async def github_integration(self, access_token: str) -> str:
619620
avoid_listener=True,
620621
)
621622
return webhook
623+
624+
async def domain_analytics(self) -> DomainAnalytics:
625+
analytics: DomainAnalytics = await self.client.domain_analytics(
626+
self.id, avoid_listener=True
627+
)
628+
return analytics
629+
630+
async def set_custom_domain(self, custom_domain: str):
631+
response: Response = await self.client.set_custom_domain(
632+
self.id, custom_domain, avoid_listener=True
633+
)
634+
return response

squarecloud/cli/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import click
55

6-
__version__ = '3.1.5'
6+
__version__ = '3.2.1'
77

88

99
def run_async(func):

squarecloud/cli/app.py

Lines changed: 99 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
from squarecloud.data import (
1515
AppData,
1616
BackupData,
17+
DeployData,
18+
DomainAnalytics,
1719
LogsData,
1820
StatusData,
1921
UploadData,
@@ -88,7 +90,7 @@ async def get_app_status(ctx: Context):
8890

8991
table = Table(title='Status', header_style='purple')
9092

91-
status_list = status.__slots__
93+
status_list = status.to_dict()
9294
for s in status_list:
9395
table.add_column(s.capitalize(), justify='center')
9496
table.add_row(
@@ -158,7 +160,7 @@ async def app_data(ctx: Context):
158160
data: AppData = await client.app_data(app_id)
159161
table = Table(title='Status', header_style='purple')
160162

161-
status_list = data.__slots__
163+
status_list = data.to_dict()
162164
for s in status_list:
163165
table.add_column(s.capitalize(), justify='center')
164166
table.add_row(
@@ -329,3 +331,98 @@ async def commit(ctx: Context, file: BufferedReader):
329331
style='green',
330332
)
331333
)
334+
335+
336+
@app_group.command(name='last-deploys')
337+
@click.pass_context
338+
@run_async
339+
async def last_deploys(ctx: Context):
340+
with Console().status('loading'):
341+
client: Client = ctx.obj['client']
342+
app_id = ctx.obj['app_id']
343+
deploys: list[list[DeployData]] = await client.last_deploys(app_id)
344+
if not deploys:
345+
print(
346+
Panel(
347+
'You do not have any recent deploys for this application',
348+
title='No deploys',
349+
title_align='left',
350+
style='red',
351+
),
352+
)
353+
return
354+
for deploy in deploys:
355+
table = Table(header_style='purple')
356+
357+
attr_list = deploy[0].__dict__
358+
for s in attr_list:
359+
table.add_column(s.capitalize(), justify='center')
360+
361+
for d in deploy:
362+
table.add_row(
363+
*[str(getattr(d, attr)) for attr in attr_list],
364+
style='green',
365+
)
366+
367+
print(table)
368+
369+
370+
@app_group.command(name='github-integration')
371+
@click.argument('access_token', type=click.STRING)
372+
@click.pass_context
373+
@run_async
374+
async def github_integration(ctx: Context, access_token: str):
375+
with Console().status('loading'):
376+
client: Client = ctx.obj['client']
377+
app_id = ctx.obj['app_id']
378+
webhook_url: str = await client.github_integration(
379+
app_id, access_token
380+
)
381+
print(
382+
Panel(
383+
webhook_url,
384+
title='Webhook url',
385+
border_style='purple',
386+
style='green',
387+
)
388+
)
389+
390+
391+
@app_group.command(name='custom-domain')
392+
@click.argument('domain', type=click.STRING)
393+
@click.pass_context
394+
@run_async
395+
async def custom_domain(ctx: Context, domain: str):
396+
with Console().status('loading'):
397+
client: Client = ctx.obj['client']
398+
app_id = ctx.obj['app_id']
399+
await client.set_custom_domain(app_id, domain)
400+
print(
401+
Panel(
402+
f'Domain defined to "{domain}"',
403+
title='Success',
404+
border_style='purple',
405+
style='green',
406+
)
407+
)
408+
409+
410+
@app_group.command(name='domain-analytics')
411+
@click.pass_context
412+
@run_async
413+
async def domain_analytics(ctx: Context):
414+
with Console().status('loading'):
415+
client: Client = ctx.obj['client']
416+
app_id = ctx.obj['app_id']
417+
analytics: DomainAnalytics = await client.domain_analytics(app_id)
418+
table = Table(title='Status', header_style='purple')
419+
420+
attr_list = analytics.to_dict()
421+
for s in attr_list:
422+
table.add_column(s.capitalize(), justify='center')
423+
table.add_row(
424+
*[str(getattr(analytics, attr)) for attr in attr_list],
425+
style='green',
426+
)
427+
428+
print(table)

squarecloud/client.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
AppData,
1212
BackupData,
1313
DeployData,
14+
DomainAnalytics,
1415
FileInfo,
1516
LogsData,
1617
StatisticsData,
@@ -92,17 +93,9 @@ def create_config_file(
9293

9394

9495
class Client(AbstractClient):
95-
"""A client for interacting with the SquareCloud API.
96-
97-
:ivar api_key: the api key for the client
98-
:ivar debug: weather the debug messages is enabled
99-
100-
:type api_key: str
101-
:type debug: bool
102-
"""
96+
"""A client for interacting with the SquareCloud API."""
10397

10498
def __init__(self, api_key: str, debug: bool = True) -> None:
105-
10699
"""
107100
The __init__ function is called when the class is instantiated.
108101
It sets up the instance of the class, and defines all of its
@@ -619,3 +612,28 @@ async def github_integration(
619612
)
620613
data = response.response
621614
return data.get('webhook')
615+
616+
async def set_custom_domain(
617+
self, app_id: str, custom_domain: str, **kwargs
618+
) -> Response:
619+
response: Response = await self._http.update_custom_domain(
620+
app_id=app_id, custom_domain=custom_domain
621+
)
622+
if not kwargs.get('avoid_listener'):
623+
endpoint: Endpoint = response.route.endpoint
624+
await self._listener.on_request(
625+
endpoint=endpoint, response=response
626+
)
627+
return response
628+
629+
async def domain_analytics(self, app_id: str, **kwargs) -> DomainAnalytics:
630+
response: Response = await self._http.domain_analytics(
631+
app_id=app_id,
632+
)
633+
if not kwargs.get('avoid_listener'):
634+
endpoint: Endpoint = response.route.endpoint
635+
await self._listener.on_request(
636+
endpoint=endpoint, response=response
637+
)
638+
analytics: DomainAnalytics = DomainAnalytics(**response.response)
639+
return analytics

squarecloud/data.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ class PlanData:
2929
memory: Dict[str, Any]
3030
duration: Dict[str, Any] | None
3131

32+
def to_dict(self):
33+
return self.__dict__
34+
3235

3336
# @dataclass(frozen=True)
3437
class Language(TypedDict):
@@ -72,8 +75,11 @@ class StatusData:
7275
uptime: conint(ge=0) | None = None
7376
time: conint(ge=0) | None = None
7477

78+
def to_dict(self):
79+
return self.__dict__
80+
7581

76-
@dataclass(frozen=True, slots=True)
82+
@dataclass(frozen=True)
7783
class AppData:
7884
"""
7985
Application data class
@@ -112,6 +118,9 @@ class AppData:
112118
custom: str | None = None
113119
desc: str | None = None
114120

121+
def to_dict(self):
122+
return self.__dict__
123+
115124

116125
@dataclass(frozen=True)
117126
class UserData:
@@ -134,6 +143,9 @@ class UserData:
134143
plan: PlanData
135144
email: str | None = None
136145

146+
def to_dict(self):
147+
return self.__dict__
148+
137149

138150
@dataclass(frozen=True)
139151
class LogsData:
@@ -189,6 +201,9 @@ async def example():
189201
"""
190202
return isinstance(other, LogsData) and self.logs == other.logs
191203

204+
def to_dict(self):
205+
return self.__dict__
206+
192207

193208
@dataclass(frozen=True)
194209
class BackupData:
@@ -202,6 +217,9 @@ class BackupData:
202217

203218
downloadURL: str
204219

220+
def to_dict(self):
221+
return self.__dict__
222+
205223

206224
@dataclass(frozen=True)
207225
class UploadData:
@@ -233,6 +251,9 @@ class UploadData:
233251
subdomain: str | None = None
234252
description: str | None = None
235253

254+
def to_dict(self):
255+
return self.__dict__
256+
236257

237258
@dataclass(frozen=True)
238259
class FileInfo:
@@ -258,6 +279,9 @@ class FileInfo:
258279
lastModified: conint(ge=0) | float
259280
path: str
260281

282+
def to_dict(self):
283+
return self.__dict__
284+
261285

262286
@dataclass(frozen=True)
263287
class StatisticsData:
@@ -280,9 +304,33 @@ class StatisticsData:
280304
websites: conint(ge=0)
281305
ping: conint(ge=0)
282306

307+
def to_dict(self):
308+
return self.__dict__
309+
283310

284311
@dataclass(frozen=True)
285312
class DeployData:
286313
id: str
287314
state: str
288315
date: datetime
316+
317+
def to_dict(self):
318+
return self.__dict__
319+
320+
321+
@dataclass(frozen=True)
322+
class DomainAnalytics:
323+
hostname: str
324+
total: list[Any]
325+
countries: list[Any]
326+
methods: list[Any]
327+
referers: list[Any]
328+
browsers: list[Any]
329+
deviceTypes: list[Any]
330+
operatingSystems: list[Any]
331+
agents: list[Any]
332+
hosts: list[Any]
333+
paths: list[Any]
334+
335+
def to_dict(self):
336+
return self.__dict__

squarecloud/errors.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ class RequestError(SquareException):
1515
"""raised when a request fails"""
1616

1717
def __init__(
18-
self, route: str, status_code: int, code: str, *args, **kwargs
18+
self, route: str, status_code: int, code: str, *args, **kwargs
1919
):
2020
self.route = route
2121
self.status = status_code
@@ -29,7 +29,9 @@ class AuthenticationFailure(RequestError):
2929

3030
def __init__(self, *args, **kwargs):
3131
super().__init__(*args, **kwargs)
32-
self.message = 'Authentication failed: Invalid API token'
32+
self.message = (
33+
'Authentication failed: ' 'Invalid API token or access denied'
34+
)
3335

3436

3537
class NotFoundError(RequestError):
@@ -199,5 +201,20 @@ def __init__(self, *args, **kwargs):
199201

200202

201203
class InvalidAccessToken(RequestError):
202-
def __init__(self, *args, **kwargs):
204+
"""
205+
raised when the GitHub access token provided by the user is invalid.
206+
"""
207+
208+
209+
def __init__(self, *args, **kwargs):
210+
super().__init__(*args, **kwargs)
211+
212+
213+
class InvalidDomain(RequestError):
214+
"""
215+
raised when an invalid domain is provided
216+
"""
217+
218+
def __init__(self, domain: str, *args, **kwargs):
203219
super().__init__(*args, **kwargs)
220+
self.message = f'{domain} is a invalid custom domain'

0 commit comments

Comments
 (0)