ddapi 0.1.1__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
ddapi-0.5.1/PKG-INFO ADDED
@@ -0,0 +1,49 @@
1
+ Metadata-Version: 2.1
2
+ Name: ddapi
3
+ Version: 0.5.1
4
+ Summary: DDnet api
5
+ Home-page: https://github.com/ByFox213/ddapi
6
+ Author: ByFox
7
+ Project-URL: Github, https://github.com/ByFox213/ddapi
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.8
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+
15
+ ddapi is an api from the ddnet and qwik website
16
+ ## Installation
17
+
18
+ ```bash
19
+ pip install ddapi
20
+ ```
21
+ or
22
+ ```bash
23
+ pip install git+https://github.com/ByFox213/ddapi
24
+ ```
25
+
26
+ ## Usage/Examples
27
+
28
+ DDnet
29
+ ```python
30
+ import asyncio
31
+ from ddapi import DDnetApi, DDPlayer
32
+
33
+
34
+ async def main():
35
+ obj = DDnetApi()
36
+ nickname = "Cor"
37
+ user: DDPlayer = await obj.player(nickname)
38
+ if user is None:
39
+ return "Player not found"
40
+ print(f"{user.player}: {user.points.points}")
41
+ # Cor: 31473
42
+ await obj.close() # Closing client Not necessary
43
+ assert isinstance(user, DDPlayer)
44
+
45
+
46
+ asyncio.run(main())
47
+ ```
48
+
49
+ [other examples](https://github.com/ByFox213/ddapi/tree/main/example)
@@ -4,6 +4,10 @@ ddapi is an api from the ddnet and qwik website
4
4
  ```bash
5
5
  pip install ddapi
6
6
  ```
7
+ or
8
+ ```bash
9
+ pip install git+https://github.com/ByFox213/ddapi
10
+ ```
7
11
 
8
12
  ## Usage/Examples
9
13
 
@@ -28,24 +32,4 @@ async def main():
28
32
  asyncio.run(main())
29
33
  ```
30
34
 
31
- qwik
32
-
33
- ```python
34
- import asyncio
35
- from ddapi import Player, QwikAPI
36
-
37
-
38
- async def main():
39
- obj = QwikAPI()
40
- nickname = "ByFox"
41
- user = await obj.player(nickname)
42
- if user is None:
43
- return "Player not found"
44
- print(f"{user.player}: {user.points.points}")
45
- # Cor: 31473
46
- await obj.close() # Closing client Not necessary
47
- assert isinstance(user, Player)
48
-
49
-
50
- asyncio.run(main())
51
- ```
35
+ [other examples](https://github.com/ByFox213/ddapi/tree/main/example)
@@ -0,0 +1,7 @@
1
+ """the module is made for the convenience of users to download and use"""
2
+ from .main import DDnetApi, DDstats, StatusAPI, utc_times, DDStatsDB
3
+ from .dataclass import *
4
+
5
+ __version__ = "0.5.1"
6
+ __author__ = 'ByFox'
7
+ __LICENSE__ = "MIT"
@@ -0,0 +1,468 @@
1
+ # pylint: disable-all
2
+ from collections import Counter
3
+ from datetime import datetime
4
+ from typing import Optional, Union, Any, AsyncGenerator
5
+ from pydantic import BaseModel, Field
6
+
7
+ rm_list = ["DD-Persian", "/vDQMHSss8W"]
8
+
9
+ # DDStats
10
+
11
+
12
+ class QE(BaseModel):
13
+ sql: str
14
+ params: dict
15
+
16
+
17
+ class DDStatsSql(BaseModel):
18
+ ok: bool = Field(default=None)
19
+ database: str = Field(default=None)
20
+ table: str = Field(default=None)
21
+ is_view: bool = Field(default=None)
22
+ human_description_en: str = Field(default=None)
23
+ rows: list[list] = Field(default=None)
24
+ truncated: bool = Field(default=None)
25
+ filtered_table_rows_count: int = Field(default=None)
26
+ expanded_columns: list = Field(default=None)
27
+ expandable_columns: list = Field(default=None)
28
+ columns: list = Field(default=None)
29
+ primary_keys: list = Field(default=None)
30
+ units: dict = Field(default=None)
31
+ query: QE = Field(default=None)
32
+ facet_results: dict = Field(default=None)
33
+ suggested_facets: list = Field(default=None)
34
+ next: int | None = Field(default=None)
35
+ next_url: str | None = Field(default=None)
36
+ error: str = Field(default='')
37
+ private: bool = Field(default=None)
38
+ allow_execute_sql: bool = Field(default=None)
39
+ query_ms: float = Field(default=None)
40
+
41
+
42
+ # ddnet
43
+ class DPoints(BaseModel):
44
+ total: Optional[int] = Field(default=None)
45
+ points: Optional[int] = Field(default=None)
46
+ rank: Optional[int] = Field(default=None)
47
+
48
+
49
+ class MaxFinishes(BaseModel):
50
+ rank: Optional[int] = Field(default=None)
51
+ player: Optional[str] = Field(default=None)
52
+ num: Optional[int] = Field(default=None)
53
+ time: Optional[float] = Field(default=None)
54
+ min_timestamp: Optional[int] = Field(default=None)
55
+ max_timestamp: Optional[int] = Field(default=None)
56
+
57
+
58
+ class DDRanks(BaseModel):
59
+ rank: Optional[int] = Field(default=None)
60
+ player: Union[str, list[str]] = Field(default=None)
61
+ time: Optional[float] = Field(default=None)
62
+ timestamp: Optional[int] = Field(default=None)
63
+ country: Optional[str] = Field(default=None)
64
+
65
+
66
+ class DDTMRanks(BaseModel):
67
+ rank: Optional[int] = Field(default=None)
68
+ players: Union[str, list[str]] = Field(default=None)
69
+ time: Optional[float] = Field(default=None)
70
+ timestamp: Optional[int] = Field(default=None)
71
+ country: Optional[str] = Field(default=None)
72
+
73
+
74
+ class DMap(BaseModel):
75
+ name: Optional[str] = Field(default=None)
76
+ website: Optional[str] = Field(default=None)
77
+ thumbnail: Optional[str] = Field(default=None)
78
+ web_preview: Optional[str] = Field(default=None)
79
+ type: Optional[str] = Field(default=None)
80
+ points: Optional[int] = Field(default=None)
81
+ difficulty: Optional[int] = Field(default=None)
82
+ mapper: Optional[str] = Field(default=None)
83
+ release: Optional[int] = Field(default=None)
84
+ median_time: Optional[float] = Field(default=None)
85
+ first_finish: Optional[int] = Field(default=None)
86
+ last_finish: Optional[int] = Field(default=None)
87
+ finishes: Optional[int] = Field(default=None)
88
+ finishers: Optional[int] = Field(default=None)
89
+ biggest_team: Optional[int] = Field(default=None)
90
+ width: Optional[int] = Field(default=None)
91
+ height: Optional[int] = Field(default=None)
92
+ tiles: Optional[list] = Field(default=None)
93
+ team_ranks: Optional[list[DDTMRanks]] = Field(default=None)
94
+ ranks: Optional[list[DDRanks]] = Field(default=None)
95
+ max_finishes: Optional[list[MaxFinishes]] = Field(default=None)
96
+
97
+
98
+ class DRank(BaseModel):
99
+ points: Optional[int] = Field(default=None)
100
+ rank: Optional[int] = Field(default=None)
101
+
102
+
103
+ class FirstFinish(BaseModel):
104
+ timestamp: Optional[float] = Field(default=None)
105
+ map: Optional[str] = Field(default=None)
106
+ time: Optional[float] = Field(default=None)
107
+
108
+
109
+ class LastFinish(BaseModel):
110
+ timestamp: Optional[float] = Field(default=None)
111
+ map: Optional[str] = Field(default=None)
112
+ time: Optional[float] = Field(default=None)
113
+ country: Optional[str] = Field(default=None)
114
+ type: Optional[str] = Field(default=None)
115
+
116
+
117
+ class FavorPart(BaseModel):
118
+ name: Optional[str] = Field(default=None)
119
+ finishes: Optional[int] = Field(default=None)
120
+
121
+
122
+ class DData(BaseModel):
123
+ points: Optional[DPoints] = Field(default=None)
124
+ team_rank: Optional[DRank] = Field(default=None)
125
+ rank: Optional[DRank] = Field(default=None)
126
+ maps: Optional[dict] = Field(default=None)
127
+
128
+
129
+ class DDType(BaseModel):
130
+ Novice: Optional[DData] = Field(default=None)
131
+ Moderate: Optional[DData] = Field(default=None)
132
+ Brutal: Optional[DData] = Field(default=None)
133
+ Insane: Optional[DData] = Field(default=None)
134
+ Dummy: Optional[DData] = Field(default=None)
135
+ DDmaX_Easy: Optional[DData] = Field(default=None, validation_alias='DDmaX.Easy')
136
+ DDmaX_Next: Optional[DData] = Field(default=None, validation_alias='DDmaX.Next')
137
+ DDmaX_Nut: Optional[DData] = Field(default=None, validation_alias='DDmaX.Nut')
138
+ DDmaX_Pro: Optional[DData] = Field(default=None, validation_alias='DDmaX.Pro')
139
+ Oldschool: Optional[DData] = Field(default=None)
140
+ Race: Optional[DData] = Field(default=None)
141
+ Solo: Optional[DData] = Field(default=None)
142
+ total: Optional[DData] = Field(default=None)
143
+
144
+
145
+ class DActiov(BaseModel):
146
+ date: Optional[str] = Field(default=None)
147
+ hours_played: Optional[int] = Field(default=None)
148
+
149
+
150
+ class DDPlayer(BaseModel):
151
+ emoji: str = Field(default='')
152
+ player: Optional[str] = Field(default=None)
153
+ points: Optional[DPoints] = Field(default=None)
154
+ team_rank: Optional[DRank] = Field(default=None)
155
+ rank: Optional[DRank] = Field(default=None)
156
+ points_last_month: Optional[DRank] = Field(default=None)
157
+ points_last_week: Optional[DRank] = Field(default=None)
158
+ first_finish: Optional[FirstFinish] = Field(default=None)
159
+ last_finishes: Optional[list[LastFinish]] = Field(default=None)
160
+ favorite_partners: Optional[list[FavorPart]] = Field(default=None)
161
+ types: Optional[DDType] = Field(default=None)
162
+ activity: Optional[list[DActiov]] = Field(default=None)
163
+ hours_played_past_365_days: Optional[int] = Field(default=None)
164
+
165
+
166
+ # qwik
167
+
168
+ class PData(BaseModel):
169
+ rank: int | None = None
170
+ points: int | None = None
171
+
172
+
173
+ class PPoints(BaseModel):
174
+ Novice: Optional[PData] = None
175
+ Moderate: Optional[PData] = None
176
+ Brutal: Optional[PData] = None
177
+ Insane: Optional[PData] = None
178
+ Dummy: Optional[PData] = None
179
+ DDmaX_Easy: Optional[PData] = Field(default=None, validation_alias='DDmaX.Easy')
180
+ DDmaX_Next: Optional[PData] = Field(default=None, validation_alias='DDmaX.Next')
181
+ DDmaX_Nut: Optional[PData] = Field(default=None, validation_alias='DDmaX.Nut')
182
+ DDmaX_Pro: Optional[PData] = Field(default=None, validation_alias='DDmaX.Pro')
183
+ Oldschool: Optional[PData] = None
184
+ Race: Optional[PData] = None
185
+ Solo: Optional[PData] = None
186
+ total: Optional[PData] = None
187
+
188
+
189
+ class PointG(BaseModel):
190
+ date: Optional[str] | None = None
191
+ points: Optional[int] | None = None
192
+ rank_points: Optional[int] | None = None
193
+ team_points: Optional[int] | None = None
194
+
195
+
196
+ class Profile(BaseModel):
197
+ name: Optional[str] | None = None
198
+ points: Optional[int] | None = None
199
+ clan: Optional[str] | None = None
200
+ country: Optional[int] | None = None
201
+ skin_name: Optional[str] | None = None
202
+ skin_color_body: Optional[int] | None = None
203
+ skin_color_feet: Optional[int] | None = None
204
+
205
+
206
+ class Map(BaseModel):
207
+ map: Optional[str] | None = None
208
+ server: Optional[str] | None = None
209
+ points: Optional[int] | None = None
210
+ stars: Optional[int] | None = None
211
+ mapper: Optional[str] | None = None
212
+ timestamp: Optional[datetime] | None = None
213
+
214
+
215
+ class RecentFinishes(BaseModel):
216
+ map: Optional[Map] | None = None
217
+ time: Optional[float] | None = None
218
+ timestamp: Optional[datetime] | None = None
219
+ server: Optional[str] | None = None
220
+ cp1: Optional[float] | None = None
221
+ cp2: Optional[float] | None = None
222
+ cp3: Optional[float] | None = None
223
+ cp4: Optional[float] | None = None
224
+ cp5: Optional[float] | None = None
225
+ cp6: Optional[float] | None = None
226
+ cp7: Optional[float] | None = None
227
+ cp8: Optional[float] | None = None
228
+ cp9: Optional[float] | None = None
229
+ cp10: Optional[float] | None = None
230
+ cp11: Optional[float] | None = None
231
+ cp12: Optional[float] | None = None
232
+ cp13: Optional[float] | None = None
233
+ cp14: Optional[float] | None = None
234
+ cp15: Optional[float] | None = None
235
+ cp16: Optional[float] | None = None
236
+ cp17: Optional[float] | None = None
237
+ cp18: Optional[float] | None = None
238
+ cp19: Optional[float] | None = None
239
+ cp20: Optional[float] | None = None
240
+ cp21: Optional[float] | None = None
241
+ cp22: Optional[float] | None = None
242
+ cp23: Optional[float] | None = None
243
+ cp24: Optional[float] | None = None
244
+ cp25: Optional[float] | None = None
245
+
246
+
247
+ class FavouriteTeammates(BaseModel):
248
+ name: str | None = None
249
+ ranks_together: int | None = None
250
+
251
+
252
+ class Finishes(BaseModel):
253
+ map: Map | None = None
254
+ name: str | None = None
255
+ time: float | None = None
256
+ timestamp: Optional[datetime] = None
257
+ server: str | None = None
258
+ rank: int | None = None
259
+ team_rank: int | None = None
260
+ seconds_played: int | None = None
261
+
262
+
263
+ class Points(BaseModel):
264
+ weekly_points: PData | None = None
265
+ monthly_points: PData | None = None
266
+ yearly_points: PData | None = None
267
+ points: PPoints | None = None
268
+ rank_points: PPoints | None = None
269
+ team_points: PPoints | None = None
270
+
271
+
272
+ class RecentActivity(BaseModel):
273
+ name: str | None = Field(default=None)
274
+ date: str | None = Field(default=None)
275
+ map_name: str | None = Field(default=None)
276
+ map: Map | None = Field(default=None)
277
+ seconds_played: int | None = Field(default=None)
278
+
279
+
280
+ class RecentPlayerInfo(BaseModel):
281
+ name: str | None = None
282
+ clan: str | None = None
283
+ country: int | None = None
284
+ skin_name: str | None = None
285
+ skin_color_body: int | None = None
286
+ skin_color_feet: int | None = None
287
+ last_seen: str | None = None
288
+ seconds_played: int | None = None
289
+
290
+
291
+ class MostPlayedMaps(BaseModel):
292
+ map_name: str | None = None
293
+ seconds_played: int | None = None
294
+ map: Map | None = None
295
+
296
+
297
+ class MostPlayed(BaseModel):
298
+ key: str | None = None
299
+ seconds_played: int | None = None
300
+
301
+
302
+ class PlaytimePerMonth(BaseModel):
303
+ year_month: str | None = None
304
+ month: str | None = None
305
+ seconds_played: int | None = None
306
+
307
+
308
+ class FavouriteRank1sTeammates(BaseModel):
309
+ name: str
310
+ ranks_together: int
311
+
312
+
313
+ class AllTop10s(BaseModel):
314
+ map: Map | None = None
315
+ name: str | None = None
316
+ time: float | None = None
317
+ rank: int | None = None
318
+ team_rank: int | None = None
319
+ team_time: float | None = None
320
+
321
+
322
+ class RecentTop10s(BaseModel):
323
+ rank_type: str | None = None
324
+ map: str | None = None
325
+ time: float | None = None
326
+ rank: int | None = None
327
+ timestamp: datetime | None = None
328
+ server: str | None = None
329
+
330
+
331
+ class Player(BaseModel):
332
+ emoji: str = Field(default='')
333
+ points_graph: Optional[list[PointG]] = None
334
+ recent_finishes: Optional[list[RecentFinishes]] = None
335
+ favourite_teammates: Optional[list[FavouriteTeammates]] = None
336
+ profile: Optional[Profile] = None
337
+ is_mapper: bool = None
338
+ finishes: Optional[list[Finishes]] = None
339
+ points: Points = None
340
+ recent_activity: Optional[list[RecentActivity]] = None
341
+ recent_player_info: Optional[list[RecentPlayerInfo]] = None
342
+ most_played_maps: Optional[list[MostPlayedMaps]] = None
343
+ most_played_gametypes: Optional[list[MostPlayed]] = None
344
+ most_played_categories: Optional[list[MostPlayed]] = None
345
+ most_played_locations: Optional[list[MostPlayed]] = None
346
+ playtime_per_month: Optional[list[PlaytimePerMonth]] = None
347
+ favourite_rank1s_teammates: Optional[list[FavouriteRank1sTeammates]] = None
348
+ all_top_10s: Optional[list[AllTop10s]] = None
349
+ recent_top_10s: Optional[list[RecentTop10s]] = None
350
+
351
+
352
+ class Client(BaseModel):
353
+ name: str | None = Field(default='')
354
+ clan: str | None = Field(default='')
355
+ country: int | None = Field(default=-1)
356
+ score: int | None = Field(default=-9999)
357
+ is_player: bool | None = Field(default=None)
358
+ skin: dict | None = Field(default=None)
359
+ afk: bool | None = Field(default=None)
360
+ team: int | None = Field(default=0)
361
+
362
+
363
+ class Info(BaseModel):
364
+ max_clients: int | None = Field(default=0)
365
+ max_players: int | None = Field(default=0)
366
+ passworded: bool | None = Field(default=None)
367
+ game_type: str | None = Field(default=None)
368
+ name: str | None = Field(default=None)
369
+ map: dict | None = Field(default=None)
370
+ version: str | None = Field(default=None)
371
+ clients: list[Client] | None = Field(default=None)
372
+
373
+ def __len__(self) -> int:
374
+ return len(self.clients)
375
+
376
+
377
+ class Server(BaseModel):
378
+ addresses: Union[list, str] = Field(default=None)
379
+ location: str = Field(default=None)
380
+ info: Info = Field(default=None)
381
+
382
+ def __len__(self) -> int:
383
+ return len(self.info.clients if self.info is not None else 0)
384
+
385
+ def get_count_client(self) -> int:
386
+ if self.info is not None and self.info.clients is not None:
387
+ return len(self.info.clients)
388
+ return 0
389
+
390
+
391
+ class Master(BaseModel):
392
+ servers: list[Server]
393
+
394
+ def __len__(self) -> int:
395
+ return len(self.servers)
396
+
397
+ async def get_info(self) -> AsyncGenerator[Info, None]:
398
+ for i in self.servers:
399
+ if i.info is None:
400
+ continue
401
+ yield i.info
402
+
403
+ async def get_clients(self) -> AsyncGenerator[Client, None]:
404
+ for i in self.servers:
405
+ if i.info is None or i.info.clients is None:
406
+ continue
407
+ yield i.info.clients
408
+
409
+ def get_clans(self, limit: int = 50, rm: list[str] = None) -> list[tuple[Any, int]]:
410
+ if rm is None:
411
+ rm = []
412
+ rm.extend(rm_list)
413
+ if not self.servers:
414
+ return []
415
+ dat = Counter(client.clan
416
+ for server in self.servers
417
+ for client in server.info.clients
418
+ if server.info is not None
419
+ and server.info.clients is not None
420
+ and client != '')
421
+ for i in rm:
422
+ del dat[i]
423
+ return sorted(dat.items(), key=lambda x: x[1], reverse=True)[:limit]
424
+
425
+ def get_count_servers(self, limit: int = 10) -> list[tuple[int, list | Any, str | None, str | None]]:
426
+ dat = []
427
+ for i in self.servers:
428
+ add = i.addresses
429
+ if isinstance(i.addresses, list):
430
+ add = i.addresses[0]
431
+ dat.append((i.get_count_client(), add, i.info.game_type, i.info.name))
432
+ return sorted(dat, key=lambda x: x[0], reverse=True)[:limit]
433
+
434
+
435
+ class QueryData(BaseModel):
436
+ points: int
437
+ name: str
438
+
439
+
440
+ class Query(BaseModel):
441
+ emoji: str = Field(default='')
442
+ data: list[QueryData]
443
+
444
+
445
+ class DDStatusData(BaseModel):
446
+ name: str | None = Field(default=None)
447
+ type: str | None = Field(default=None)
448
+ host: str | None = Field(default=None)
449
+ location: str | None = Field(default=None)
450
+ online4: bool | None = Field(default=None)
451
+ online6: bool | None = Field(default=None)
452
+ uptime: str | None = Field(default=None)
453
+ load: float | None = Field(default=None)
454
+ network_rx: int | None = Field(default=None)
455
+ network_tx: int | None = Field(default=None)
456
+ packets_rx: int | None = Field(default=None)
457
+ packets_tx: int | None = Field(default=None)
458
+ cpu: int | None = Field(default=None)
459
+ memory_total: int | None = Field(default=None)
460
+ memory_used: int | None = Field(default=None)
461
+ swap_total: int | None = Field(default=None)
462
+ swap_used: int | None = Field(default=None)
463
+ hdd_total: int | None = Field(default=None)
464
+ hdd_used: int | None = Field(default=None)
465
+
466
+
467
+ class DDStatus(BaseModel):
468
+ servers: list[DDStatusData] | None = Field(default=[])
@@ -0,0 +1,63 @@
1
+ from abc import ABC
2
+ from typing import Union, Any
3
+
4
+ import aiohttp
5
+ from aiohttp import ClientSession, ClientConnectorError
6
+ from aiohttp.typedefs import DEFAULT_JSON_DECODER, JSONDecoder
7
+
8
+
9
+ class API(ABC):
10
+ def __init__(self,
11
+ session: ClientSession = None,
12
+ json_loads: JSONDecoder = DEFAULT_JSON_DECODER,
13
+ emojis: dict[str, str] = None):
14
+ self.emojis = emojis
15
+ if emojis is None:
16
+ self.emojis = {"fox": "🦊"}
17
+ self.session = session
18
+ self.json_loads = json_loads
19
+ self.url = "https://ddstats.qwik.space/player/json?player={0}"
20
+
21
+ def __del__(self):
22
+ self.session = None
23
+
24
+ @staticmethod
25
+ def powered() -> str:
26
+ return ''
27
+
28
+ def _get_emoji(self, player_name: str) -> str:
29
+ for name, emoji in self.emojis.items():
30
+ if name in player_name.lower():
31
+ return emoji
32
+ return ''
33
+
34
+ def closed(self):
35
+ return self.session.closed is None or self.session.closed
36
+
37
+ async def _send(self, url: str) -> Union[dict, None]:
38
+ if self.session is None:
39
+ self.session = aiohttp.ClientSession()
40
+ try:
41
+ async with self.session.get(url) as req:
42
+ if req.status == 200:
43
+ usr = await req.text()
44
+ if usr == '{}' or usr is None:
45
+ return
46
+ del usr
47
+ return await req.json(loads=self.json_loads)
48
+ return
49
+ except ClientConnectorError:
50
+ return
51
+
52
+ async def _generate(self, url: str, model, k: str = None, emoji: str = None) -> Any:
53
+ dat = await self._send(url)
54
+ if dat is None:
55
+ return
56
+ if k is not None:
57
+ dat = {k: dat}
58
+ if emoji is not None:
59
+ dat["emoji"] = emoji
60
+ return model(**dat)
61
+
62
+ async def close(self) -> None:
63
+ return await self.session.close()