ddapi 0.9.3__tar.gz → 0.12.0__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.
- {ddapi-0.9.3 → ddapi-0.12.0}/PKG-INFO +16 -18
- ddapi-0.12.0/README.md +45 -0
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi/__init__.py +3 -3
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi/api.py +47 -16
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi/main.py +53 -24
- ddapi-0.12.0/ddapi/ddapi/scheme/__init__.py +4 -0
- ddapi-0.12.0/ddapi/ddapi/scheme/base.py +21 -0
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi/scheme/ddnet.py +30 -18
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi/scheme/ddstats_tw.py +80 -45
- ddapi-0.12.0/ddapi/ddapi/scheme/status_tw.py +131 -0
- ddapi-0.12.0/ddapi/ddapi/types.py +3 -0
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi.egg-info/PKG-INFO +16 -18
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi.egg-info/SOURCES.txt +2 -0
- {ddapi-0.9.3 → ddapi-0.12.0}/setup.cfg +3 -6
- {ddapi-0.9.3 → ddapi-0.12.0}/setup.py +2 -6
- ddapi-0.9.3/README.md +0 -45
- ddapi-0.9.3/ddapi/ddapi/scheme/__init__.py +0 -3
- ddapi-0.9.3/ddapi/ddapi/scheme/status_tw.py +0 -131
- {ddapi-0.9.3 → ddapi-0.12.0}/LICENSE +0 -0
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi.egg-info/dependency_links.txt +0 -0
- {ddapi-0.9.3 → ddapi-0.12.0}/ddapi/ddapi.egg-info/top_level.txt +0 -0
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ddapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: DDnet api
|
|
5
5
|
Home-page: https://github.com/ByFox213/ddapi
|
|
6
6
|
Author: ByFox
|
|
7
|
+
License: MIT
|
|
7
8
|
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
9
|
Requires-Python: >=3.8
|
|
12
10
|
Description-Content-Type: text/markdown
|
|
13
11
|
License-File: LICENSE
|
|
14
12
|
Dynamic: author
|
|
15
|
-
Dynamic: classifier
|
|
16
13
|
Dynamic: description
|
|
17
14
|
Dynamic: description-content-type
|
|
18
15
|
Dynamic: home-page
|
|
16
|
+
Dynamic: license
|
|
19
17
|
Dynamic: license-file
|
|
20
18
|
Dynamic: project-url
|
|
21
19
|
Dynamic: requires-python
|
|
@@ -41,28 +39,28 @@ DDnet
|
|
|
41
39
|
|
|
42
40
|
```python
|
|
43
41
|
import asyncio
|
|
42
|
+
|
|
44
43
|
from ddapi import DDnetApi, DDPlayer
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
async def main():
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
user
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
assert isinstance(user, DDPlayer)
|
|
47
|
+
async with DDnetApi() as obj:
|
|
48
|
+
user: DDPlayer = await obj.player("Cor")
|
|
49
|
+
if user is not None:
|
|
50
|
+
text = f"{user.player}: {user.points.points}/{user.points.total}"
|
|
51
|
+
percent = round(user.points.total / user.points.points * 100)
|
|
52
|
+
print(f"{text}({percent}%)")
|
|
53
|
+
# Cor: 32950/32950(100%)
|
|
54
|
+
else:
|
|
55
|
+
print("Player not found")
|
|
58
56
|
|
|
59
57
|
|
|
60
58
|
asyncio.run(main())
|
|
61
59
|
```
|
|
62
60
|
|
|
63
61
|
Tested on Python
|
|
64
|
-
| 3.
|
|
65
|
-
|
|
66
|
-
|
|
|
62
|
+
| 3.10 | 3.11 | 3.12 |
|
|
63
|
+
|------|------|------|
|
|
64
|
+
| ✅ | ✅ | ✅ |
|
|
67
65
|
|
|
68
66
|
[other examples](https://github.com/ByFox213/ddapi/tree/main/example)
|
ddapi-0.12.0/README.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
ddapi is an api from the ddnet and qwik website
|
|
2
|
+
|
|
3
|
+
## Installation
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install ddapi
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
or
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install git+https://github.com/ByFox213/ddapi
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage/Examples
|
|
16
|
+
|
|
17
|
+
DDnet
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
import asyncio
|
|
21
|
+
|
|
22
|
+
from ddapi import DDnetApi, DDPlayer
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
async def main():
|
|
26
|
+
async with DDnetApi() as obj:
|
|
27
|
+
user: DDPlayer = await obj.player("Cor")
|
|
28
|
+
if user is not None:
|
|
29
|
+
text = f"{user.player}: {user.points.points}/{user.points.total}"
|
|
30
|
+
percent = round(user.points.total / user.points.points * 100)
|
|
31
|
+
print(f"{text}({percent}%)")
|
|
32
|
+
# Cor: 32950/32950(100%)
|
|
33
|
+
else:
|
|
34
|
+
print("Player not found")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
asyncio.run(main())
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Tested on Python
|
|
41
|
+
| 3.10 | 3.11 | 3.12 |
|
|
42
|
+
|------|------|------|
|
|
43
|
+
| ✅ | ✅ | ✅ |
|
|
44
|
+
|
|
45
|
+
[other examples](https://github.com/ByFox213/ddapi/tree/main/example)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""the module is made for the convenience of users to download and use"""
|
|
2
2
|
from .main import DDnetApi, DDstats, Status
|
|
3
|
-
from .scheme import *
|
|
3
|
+
from .scheme import * # noqa: F403
|
|
4
4
|
|
|
5
|
-
__version__ = "0.
|
|
6
|
-
__author__ =
|
|
5
|
+
__version__ = "0.12.0"
|
|
6
|
+
__author__ = "ByFox"
|
|
7
7
|
__LICENSE__ = "MIT"
|
|
@@ -1,43 +1,66 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from abc import ABC
|
|
2
|
-
from typing import Optional,
|
|
3
|
+
from typing import Optional, Type, Any
|
|
3
4
|
|
|
4
5
|
import aiohttp
|
|
5
|
-
from aiohttp import ClientSession
|
|
6
|
-
from aiohttp.typedefs import DEFAULT_JSON_DECODER
|
|
6
|
+
from aiohttp import ClientSession
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
from ddapi.types import T
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
import orjson
|
|
12
|
+
|
|
13
|
+
DEFAULT_JSON_DECODER = orjson.loads
|
|
14
|
+
except ImportError:
|
|
15
|
+
from aiohttp.typedefs import DEFAULT_JSON_DECODER
|
|
9
16
|
|
|
10
17
|
|
|
11
18
|
class API(ABC):
|
|
12
19
|
def __init__(
|
|
13
20
|
self,
|
|
14
21
|
session: ClientSession = None,
|
|
22
|
+
autoclose: bool = True,
|
|
15
23
|
json_loads: Any = DEFAULT_JSON_DECODER
|
|
16
24
|
):
|
|
17
25
|
self.__session = session
|
|
18
26
|
self.json_loads = json_loads
|
|
27
|
+
self.autoclose = autoclose
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return None
|
|
29
|
+
if self.__session is None:
|
|
30
|
+
self.__session = aiohttp.ClientSession()
|
|
23
31
|
|
|
24
|
-
async def
|
|
25
|
-
"""Send a GET request to the given URL and return the response as JSON."""
|
|
32
|
+
async def __aenter__(self):
|
|
26
33
|
if self.__session is None:
|
|
27
34
|
self.__session = aiohttp.ClientSession()
|
|
35
|
+
return self
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
async def __aexit__(self, _exc_type, _exc_val, _exc_tb):
|
|
38
|
+
if self.autoclose:
|
|
39
|
+
await self.close()
|
|
40
|
+
|
|
41
|
+
def __del__(self):
|
|
42
|
+
if self.__session is not None and not self.__session.closed:
|
|
43
|
+
loop = asyncio.get_event_loop()
|
|
44
|
+
if loop.is_running():
|
|
45
|
+
loop.create_task(self.close())
|
|
46
|
+
else:
|
|
47
|
+
loop.run_until_complete(self.close())
|
|
48
|
+
|
|
49
|
+
async def _get(self, url: str) -> Optional[dict]:
|
|
50
|
+
"""Send a GET request to the given URL and return the response as JSON."""
|
|
51
|
+
async with self.__session.get(url) as req:
|
|
52
|
+
return (
|
|
53
|
+
await req.json(loads=self.json_loads)
|
|
54
|
+
if req.status == 200
|
|
55
|
+
else None
|
|
56
|
+
)
|
|
34
57
|
|
|
35
58
|
async def _generate_model_instance(
|
|
36
59
|
self,
|
|
37
60
|
url: str,
|
|
38
|
-
model: Type[
|
|
61
|
+
model: Type[T],
|
|
39
62
|
k: Optional[str] = None
|
|
40
|
-
) -> Optional[
|
|
63
|
+
) -> Optional[T]:
|
|
41
64
|
"""Generate a model instance from the given URL and optional keyword arguments.
|
|
42
65
|
|
|
43
66
|
Args:
|
|
@@ -64,3 +87,11 @@ class API(ABC):
|
|
|
64
87
|
if self.__session is not None:
|
|
65
88
|
await self.__session.close()
|
|
66
89
|
self.__session = None
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def domain(self) -> str:
|
|
93
|
+
return "ddnet.org"
|
|
94
|
+
|
|
95
|
+
@staticmethod
|
|
96
|
+
def powered() -> None:
|
|
97
|
+
return None
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
from enum import StrEnum
|
|
1
2
|
from urllib.parse import quote
|
|
2
3
|
|
|
3
4
|
from .api import API
|
|
4
|
-
from .scheme import
|
|
5
|
+
from .scheme import DDPlayer, DDStatus, ReleasesMaps, Query, QueryMap, QueryMapper, \
|
|
6
|
+
Master, DMap, DProfile, SMap, Maps, Player, Info, BannedMaster, List, ListData, \
|
|
7
|
+
ListPl, ListPlData, MasterTw, ServerTwOne, Charts, ChartEnum, Stats
|
|
5
8
|
|
|
6
9
|
__all__ = (
|
|
10
|
+
"MasterEnum",
|
|
7
11
|
"DDnetApi",
|
|
8
12
|
"DDstats",
|
|
9
13
|
"Status"
|
|
@@ -11,16 +15,16 @@ __all__ = (
|
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class MasterEnum(StrEnum):
|
|
14
|
-
master1 = "
|
|
15
|
-
master2 = "
|
|
16
|
-
master3 = "
|
|
17
|
-
master4 = "
|
|
18
|
+
master1 = "1"
|
|
19
|
+
master2 = "2"
|
|
20
|
+
master3 = "3"
|
|
21
|
+
master4 = "4"
|
|
18
22
|
|
|
19
23
|
|
|
20
24
|
class DDnetApi(API):
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
@property
|
|
26
|
+
def domain(self) -> str:
|
|
27
|
+
return "ddnet.org"
|
|
24
28
|
|
|
25
29
|
@staticmethod
|
|
26
30
|
def powered() -> str:
|
|
@@ -57,19 +61,19 @@ class DDnetApi(API):
|
|
|
57
61
|
return await self._generate_model_instance(
|
|
58
62
|
f"https://{self.domain}/maps/?query={quote(map_name)}",
|
|
59
63
|
QueryMap,
|
|
60
|
-
|
|
64
|
+
"maps",
|
|
61
65
|
)
|
|
62
66
|
|
|
63
67
|
async def query_mapper(self, player: str) -> QueryMapper:
|
|
64
68
|
return await self._generate_model_instance(
|
|
65
69
|
f"https://{self.domain}/maps/?qmapper={quote(player)}",
|
|
66
70
|
QueryMapper,
|
|
67
|
-
|
|
71
|
+
"players",
|
|
68
72
|
)
|
|
69
73
|
|
|
70
|
-
async def master(self,
|
|
74
|
+
async def master(self, number: MasterEnum = MasterEnum.master1) -> Master:
|
|
71
75
|
return await self._generate_model_instance(
|
|
72
|
-
f"https://{
|
|
76
|
+
f"https://master{number}.{self.domain}/ddnet/15/servers.json",
|
|
73
77
|
Master
|
|
74
78
|
)
|
|
75
79
|
|
|
@@ -81,14 +85,34 @@ class DDnetApi(API):
|
|
|
81
85
|
|
|
82
86
|
|
|
83
87
|
class DDstats(API):
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
88
|
+
@property
|
|
89
|
+
def domain(self) -> str:
|
|
90
|
+
return "ddstats.tw"
|
|
87
91
|
|
|
88
92
|
@staticmethod
|
|
89
93
|
def powered() -> str:
|
|
90
94
|
return DDstats().domain
|
|
91
95
|
|
|
96
|
+
async def profile(self, player_name: str) -> DProfile:
|
|
97
|
+
return await self._generate_model_instance(
|
|
98
|
+
f"https://{self.domain}/profile/json?player={quote(player_name)}",
|
|
99
|
+
DProfile,
|
|
100
|
+
"profile"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
async def map(self, map_name: str) -> SMap:
|
|
104
|
+
return await self._generate_model_instance(
|
|
105
|
+
f"https://{self.domain}/map/json?map={quote(map_name)}",
|
|
106
|
+
SMap
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
async def maps(self) -> Maps:
|
|
110
|
+
return await self._generate_model_instance(
|
|
111
|
+
f"https://{self.domain}/maps/json",
|
|
112
|
+
Maps,
|
|
113
|
+
"maps"
|
|
114
|
+
)
|
|
115
|
+
|
|
92
116
|
async def player(self, player_name: str) -> Player:
|
|
93
117
|
"""Fetch player data from the API and return it as a dictionary."""
|
|
94
118
|
return await self._generate_model_instance(
|
|
@@ -98,9 +122,9 @@ class DDstats(API):
|
|
|
98
122
|
|
|
99
123
|
|
|
100
124
|
class Status(API):
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
125
|
+
@property
|
|
126
|
+
def domain(self) -> str:
|
|
127
|
+
return "status.tw"
|
|
104
128
|
|
|
105
129
|
@staticmethod
|
|
106
130
|
def powered() -> str:
|
|
@@ -172,7 +196,12 @@ class Status(API):
|
|
|
172
196
|
ServerTwOne,
|
|
173
197
|
)
|
|
174
198
|
|
|
175
|
-
async def server_charts(
|
|
199
|
+
async def server_charts(
|
|
200
|
+
self,
|
|
201
|
+
ip: str,
|
|
202
|
+
port: int | str,
|
|
203
|
+
chart: ChartEnum = ChartEnum.day
|
|
204
|
+
) -> Charts:
|
|
176
205
|
return await self._generate_model_instance(
|
|
177
206
|
f"https://api.{self.domain}/server/{quote(ip)}/{port}/chart/{chart}",
|
|
178
207
|
Charts,
|
|
@@ -180,11 +209,11 @@ class Status(API):
|
|
|
180
209
|
)
|
|
181
210
|
|
|
182
211
|
async def server_history(self, ip: str, port: int | str) -> None:
|
|
183
|
-
# https://api.status.tw/server/{ip}/{port}/history
|
|
212
|
+
# TODO: https://api.status.tw/server/{ip}/{port}/history
|
|
184
213
|
raise NotImplementedError()
|
|
185
214
|
|
|
186
215
|
async def server_stats(self, ip: str, port: int | str) -> None:
|
|
187
|
-
# https://api.status.tw/server/{ip}/{port}/stats
|
|
216
|
+
# TODO: https://api.status.tw/server/{ip}/{port}/stats
|
|
188
217
|
raise NotImplementedError()
|
|
189
218
|
|
|
190
219
|
async def clan_list(self) -> ListPl:
|
|
@@ -214,7 +243,7 @@ class Status(API):
|
|
|
214
243
|
)
|
|
215
244
|
|
|
216
245
|
async def player_history(self, name: str) -> None:
|
|
217
|
-
# https://api.status.tw/player/name/{name}/history
|
|
246
|
+
# TODO: https://api.status.tw/player/name/{name}/history
|
|
218
247
|
raise NotImplementedError()
|
|
219
248
|
|
|
220
249
|
async def stats(self) -> Stats:
|
|
@@ -224,9 +253,9 @@ class Status(API):
|
|
|
224
253
|
)
|
|
225
254
|
|
|
226
255
|
async def stats_players(self, t: str) -> None:
|
|
227
|
-
# https://api.status.tw/stats/players/day | week | month
|
|
256
|
+
# TODO: https://api.status.tw/stats/players/day | week | month
|
|
228
257
|
raise NotImplementedError()
|
|
229
258
|
|
|
230
259
|
async def stats_servers(self, t: str) -> None:
|
|
231
|
-
# https://api.status.tw/stats/servers/week | month
|
|
260
|
+
# TODO: https://api.status.tw/stats/servers/week | month
|
|
232
261
|
raise NotImplementedError()
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
from ddapi import DData
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DDType(BaseModel):
|
|
9
|
+
Novice: Optional[DData] = None
|
|
10
|
+
Moderate: Optional[DData] = None
|
|
11
|
+
Brutal: Optional[DData] = None
|
|
12
|
+
Insane: Optional[DData] = None
|
|
13
|
+
Dummy: Optional[DData] = None
|
|
14
|
+
DDmaX_Easy: Optional[DData] = Field(default=None, validation_alias="DDmaX.Easy")
|
|
15
|
+
DDmaX_Next: Optional[DData] = Field(default=None, validation_alias="DDmaX.Next")
|
|
16
|
+
DDmaX_Nut: Optional[DData] = Field(default=None, validation_alias="DDmaX.Nut")
|
|
17
|
+
DDmaX_Pro: Optional[DData] = Field(default=None, validation_alias="DDmaX.Pro")
|
|
18
|
+
Oldschool: Optional[DData] = Field(default=None)
|
|
19
|
+
Race: Optional[DData] = None
|
|
20
|
+
Solo: Optional[DData] = None
|
|
21
|
+
total: Optional[DData] = None
|
|
@@ -5,7 +5,9 @@ from typing import Optional, Any
|
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
from .base import DDType
|
|
9
|
+
|
|
10
|
+
rm_list = ["DD-Persian", "/vDQMHSss8W", ""]
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class DPoints(BaseModel):
|
|
@@ -94,22 +96,6 @@ class DData(BaseModel):
|
|
|
94
96
|
maps: Optional[dict] = Field(default=None)
|
|
95
97
|
|
|
96
98
|
|
|
97
|
-
class DDType(BaseModel):
|
|
98
|
-
Novice: Optional[DData] = None
|
|
99
|
-
Moderate: Optional[DData] = None
|
|
100
|
-
Brutal: Optional[DData] = None
|
|
101
|
-
Insane: Optional[DData] = None
|
|
102
|
-
Dummy: Optional[DData] = None
|
|
103
|
-
DDmaX_Easy: Optional[DData] = Field(default=None, validation_alias='DDmaX.Easy')
|
|
104
|
-
DDmaX_Next: Optional[DData] = Field(default=None, validation_alias='DDmaX.Next')
|
|
105
|
-
DDmaX_Nut: Optional[DData] = Field(default=None, validation_alias='DDmaX.Nut')
|
|
106
|
-
DDmaX_Pro: Optional[DData] = Field(default=None, validation_alias='DDmaX.Pro')
|
|
107
|
-
Oldschool: Optional[DData] = Field(default=None)
|
|
108
|
-
Race: Optional[DData] = None
|
|
109
|
-
Solo: Optional[DData] = None
|
|
110
|
-
total: Optional[DData] = None
|
|
111
|
-
|
|
112
|
-
|
|
113
99
|
class Activity(BaseModel):
|
|
114
100
|
date: str
|
|
115
101
|
hours_played: int
|
|
@@ -220,7 +206,7 @@ class Master(BaseModel):
|
|
|
220
206
|
client.clan
|
|
221
207
|
for server in self.servers
|
|
222
208
|
for client in server.info.clients
|
|
223
|
-
if client !=
|
|
209
|
+
if client != ""
|
|
224
210
|
)
|
|
225
211
|
|
|
226
212
|
for i in remove_list:
|
|
@@ -297,3 +283,29 @@ class QueryMapData(BaseModel):
|
|
|
297
283
|
|
|
298
284
|
class QueryMap(BaseModel):
|
|
299
285
|
maps: list[QueryMapData]
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
class DDStatusData(BaseModel):
|
|
289
|
+
name: str = None
|
|
290
|
+
type: str = None
|
|
291
|
+
host: str = None
|
|
292
|
+
location: str = None
|
|
293
|
+
online4: bool = None
|
|
294
|
+
online6: bool = None
|
|
295
|
+
uptime: str = None
|
|
296
|
+
load: float = None
|
|
297
|
+
network_rx: int = None
|
|
298
|
+
network_tx: int = None
|
|
299
|
+
packets_rx: int = None
|
|
300
|
+
packets_tx: int = None
|
|
301
|
+
cpu: int = None
|
|
302
|
+
memory_total: int = None
|
|
303
|
+
memory_used: int = None
|
|
304
|
+
swap_total: int = None
|
|
305
|
+
swap_used: int = None
|
|
306
|
+
hdd_total: int = None
|
|
307
|
+
hdd_used: int = None
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class DDStatus(BaseModel):
|
|
311
|
+
servers: list[DDStatusData]
|
|
@@ -4,7 +4,7 @@ from typing import Optional
|
|
|
4
4
|
|
|
5
5
|
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
from .base import DDType
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class PData(BaseModel):
|
|
@@ -12,22 +12,6 @@ class PData(BaseModel):
|
|
|
12
12
|
points: int
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
class PPoints(BaseModel):
|
|
16
|
-
Novice: Optional[PData] = None
|
|
17
|
-
Moderate: Optional[PData] = None
|
|
18
|
-
Brutal: Optional[PData] = None
|
|
19
|
-
Insane: Optional[PData] = None
|
|
20
|
-
Dummy: Optional[PData] = None
|
|
21
|
-
DDmaX_Easy: Optional[PData] = Field(default=None, validation_alias='DDmaX.Easy')
|
|
22
|
-
DDmaX_Next: Optional[PData] = Field(default=None, validation_alias='DDmaX.Next')
|
|
23
|
-
DDmaX_Nut: Optional[PData] = Field(default=None, validation_alias='DDmaX.Nut')
|
|
24
|
-
DDmaX_Pro: Optional[PData] = Field(default=None, validation_alias='DDmaX.Pro')
|
|
25
|
-
Oldschool: Optional[PData] = None
|
|
26
|
-
Race: Optional[PData] = None
|
|
27
|
-
Solo: Optional[PData] = None
|
|
28
|
-
total: Optional[PData] = None
|
|
29
|
-
|
|
30
|
-
|
|
31
15
|
class PointG(BaseModel):
|
|
32
16
|
date: str
|
|
33
17
|
points: int
|
|
@@ -45,6 +29,10 @@ class Profile(BaseModel):
|
|
|
45
29
|
skin_color_feet: Optional[int] = None
|
|
46
30
|
|
|
47
31
|
|
|
32
|
+
class DProfile(BaseModel):
|
|
33
|
+
profile: Profile
|
|
34
|
+
|
|
35
|
+
|
|
48
36
|
class DDMap(BaseModel):
|
|
49
37
|
map: str
|
|
50
38
|
server: str
|
|
@@ -113,9 +101,9 @@ class Points(BaseModel):
|
|
|
113
101
|
weekly_points: Optional[PData] = None
|
|
114
102
|
monthly_points: Optional[PData] = None
|
|
115
103
|
yearly_points: Optional[PData] = None
|
|
116
|
-
points:
|
|
117
|
-
rank_points:
|
|
118
|
-
team_points:
|
|
104
|
+
points: DDType
|
|
105
|
+
rank_points: DDType
|
|
106
|
+
team_points: DDType
|
|
119
107
|
|
|
120
108
|
|
|
121
109
|
class RecentActivity(BaseModel):
|
|
@@ -173,7 +161,7 @@ class RecentTop10s(BaseModel):
|
|
|
173
161
|
map: str
|
|
174
162
|
time: float
|
|
175
163
|
rank: int
|
|
176
|
-
timestamp: Optional[datetime]
|
|
164
|
+
timestamp: Optional[datetime] = None
|
|
177
165
|
server: str
|
|
178
166
|
|
|
179
167
|
|
|
@@ -205,27 +193,74 @@ class Player(BaseModel):
|
|
|
205
193
|
recent_top_10s: Optional[list[RecentTop10s]] = None
|
|
206
194
|
|
|
207
195
|
|
|
208
|
-
class
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
196
|
+
class Maps(BaseModel):
|
|
197
|
+
maps: list[DDMap]
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
class InfoSMap(BaseModel):
|
|
201
|
+
map: DDMap
|
|
202
|
+
finishes: int
|
|
203
|
+
finishes_rank: int
|
|
204
|
+
median_time: float
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
class RankingSMap(BaseModel):
|
|
208
|
+
rank: int
|
|
209
|
+
timestamp: Optional[datetime] = None
|
|
210
|
+
name: str
|
|
211
|
+
time: float
|
|
212
|
+
map: str
|
|
213
|
+
server: str
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class TeamRankingSMap(BaseModel):
|
|
217
|
+
rank: int
|
|
218
|
+
timestamp: Optional[datetime] = None
|
|
219
|
+
id: list[int]
|
|
220
|
+
players: list[str]
|
|
221
|
+
time: float
|
|
222
|
+
map: str
|
|
223
|
+
server: str
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class TimeCpsSMap(BaseModel):
|
|
227
|
+
name: str
|
|
228
|
+
cp1: float
|
|
229
|
+
cp2: float
|
|
230
|
+
cp3: float
|
|
231
|
+
cp4: float
|
|
232
|
+
cp5: float
|
|
233
|
+
cp6: float
|
|
234
|
+
cp7: float
|
|
235
|
+
cp8: float
|
|
236
|
+
cp9: float
|
|
237
|
+
cp10: float
|
|
238
|
+
cp11: float
|
|
239
|
+
cp12: float
|
|
240
|
+
cp13: float
|
|
241
|
+
cp14: float
|
|
242
|
+
cp15: float
|
|
243
|
+
cp16: float
|
|
244
|
+
cp17: float
|
|
245
|
+
cp18: float
|
|
246
|
+
cp19: float
|
|
247
|
+
cp20: float
|
|
248
|
+
cp21: float
|
|
249
|
+
cp22: float
|
|
250
|
+
cp23: float
|
|
251
|
+
cp24: float
|
|
252
|
+
cp25: float
|
|
253
|
+
time: float
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
class PlaytimeSMap(BaseModel):
|
|
257
|
+
name: str
|
|
258
|
+
seconds_played: int
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
class SMap(BaseModel):
|
|
262
|
+
info: InfoSMap
|
|
263
|
+
rankings: list[RankingSMap]
|
|
264
|
+
team_rankings: list[TeamRankingSMap]
|
|
265
|
+
time_cps: list[TimeCpsSMap]
|
|
266
|
+
playtime: list[PlaytimeSMap]
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Status.tw
|
|
2
|
+
from datetime import datetime
|
|
3
|
+
from enum import StrEnum
|
|
4
|
+
from typing import Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ChartEnum(StrEnum):
|
|
10
|
+
day = "day"
|
|
11
|
+
week = "week"
|
|
12
|
+
month = "month"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DataTw(BaseModel):
|
|
16
|
+
name: str
|
|
17
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class VersionTw(BaseModel):
|
|
21
|
+
version: str
|
|
22
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class CountryTw(BaseModel):
|
|
26
|
+
identifier: str
|
|
27
|
+
code: int
|
|
28
|
+
icon_url: str = Field(serialization_alias="iconUrl")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ClientTw(BaseModel):
|
|
32
|
+
name: str
|
|
33
|
+
country: CountryTw
|
|
34
|
+
score: int
|
|
35
|
+
is_player: bool = Field(serialization_alias="isPlayer")
|
|
36
|
+
is_afk: bool = Field(serialization_alias="isAfk")
|
|
37
|
+
team: int
|
|
38
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
39
|
+
clan: DataTw | None
|
|
40
|
+
server: "ServerTw" = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class ServerTw(BaseModel):
|
|
44
|
+
ip: str
|
|
45
|
+
port: int
|
|
46
|
+
name: str
|
|
47
|
+
num_clients: int = Field(serialization_alias="numClients")
|
|
48
|
+
num_players: int = Field(serialization_alias="numPlayers")
|
|
49
|
+
max_clients: int = Field(serialization_alias="maxClients")
|
|
50
|
+
max_players: int = Field(serialization_alias="maxPlayers")
|
|
51
|
+
has_password: bool = Field(serialization_alias="hasPassword")
|
|
52
|
+
supports6: bool
|
|
53
|
+
supports7: bool
|
|
54
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
55
|
+
relevance_score: int = Field(serialization_alias="relevanceScore")
|
|
56
|
+
client_score_kind: str | None = Field(serialization_alias="clientScoreKind")
|
|
57
|
+
logo_url: str = Field(serialization_alias="logoUrl")
|
|
58
|
+
map: DataTw
|
|
59
|
+
website: Optional[str] = None
|
|
60
|
+
discord_invite: Optional[str] = Field(None, serialization_alias="discordInvite")
|
|
61
|
+
description: Optional[str] = None
|
|
62
|
+
game_type: DataTw = Field(serialization_alias="gameType")
|
|
63
|
+
version: VersionTw
|
|
64
|
+
clients: list[ClientTw]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ServerTwOne(BaseModel):
|
|
68
|
+
ip: str
|
|
69
|
+
port: int
|
|
70
|
+
online: ServerTw
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class Chart(BaseModel):
|
|
74
|
+
avg_players: float = Field(serialization_alias="avgPlayers")
|
|
75
|
+
max_players: int = Field(serialization_alias="maxPlayers")
|
|
76
|
+
min_players: int = Field(serialization_alias="minPlayers")
|
|
77
|
+
timestamp: datetime
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class Charts(BaseModel):
|
|
81
|
+
charts: list[Chart]
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class MasterTw(BaseModel):
|
|
85
|
+
servers: list[ServerTw]
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Info(BaseModel):
|
|
89
|
+
app: str
|
|
90
|
+
version: str
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class BannedMasterData(BaseModel):
|
|
94
|
+
ip: str
|
|
95
|
+
is_active: bool = Field(serialization_alias="isActive")
|
|
96
|
+
reason: str | None
|
|
97
|
+
unban_date: datetime | None = Field(serialization_alias="unbanDate")
|
|
98
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class BannedMaster(BaseModel):
|
|
102
|
+
servers: list[BannedMasterData]
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class ListData(BaseModel):
|
|
106
|
+
name: str
|
|
107
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
108
|
+
servers: list[ServerTw]
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class List(BaseModel):
|
|
112
|
+
data: list[ListData]
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class ListPlData(BaseModel):
|
|
116
|
+
name: str
|
|
117
|
+
created_at: datetime = Field(serialization_alias="createdAt")
|
|
118
|
+
players: list[ClientTw]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class ListPl(BaseModel):
|
|
122
|
+
data: list[ListPlData]
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class Stats(BaseModel):
|
|
126
|
+
num_players: int = Field(serialization_alias="numPlayers")
|
|
127
|
+
num_clans: int = Field(serialization_alias="numClans")
|
|
128
|
+
num_servers: int = Field(serialization_alias="numServers")
|
|
129
|
+
num_maps: int = Field(serialization_alias="numMaps")
|
|
130
|
+
num_game_types: int = Field(serialization_alias="numGameTypes")
|
|
131
|
+
num_versions: int = Field(serialization_alias="numVersions")
|
|
@@ -1,21 +1,19 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ddapi
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.12.0
|
|
4
4
|
Summary: DDnet api
|
|
5
5
|
Home-page: https://github.com/ByFox213/ddapi
|
|
6
6
|
Author: ByFox
|
|
7
|
+
License: MIT
|
|
7
8
|
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
9
|
Requires-Python: >=3.8
|
|
12
10
|
Description-Content-Type: text/markdown
|
|
13
11
|
License-File: LICENSE
|
|
14
12
|
Dynamic: author
|
|
15
|
-
Dynamic: classifier
|
|
16
13
|
Dynamic: description
|
|
17
14
|
Dynamic: description-content-type
|
|
18
15
|
Dynamic: home-page
|
|
16
|
+
Dynamic: license
|
|
19
17
|
Dynamic: license-file
|
|
20
18
|
Dynamic: project-url
|
|
21
19
|
Dynamic: requires-python
|
|
@@ -41,28 +39,28 @@ DDnet
|
|
|
41
39
|
|
|
42
40
|
```python
|
|
43
41
|
import asyncio
|
|
42
|
+
|
|
44
43
|
from ddapi import DDnetApi, DDPlayer
|
|
45
44
|
|
|
46
45
|
|
|
47
46
|
async def main():
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
user
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
assert isinstance(user, DDPlayer)
|
|
47
|
+
async with DDnetApi() as obj:
|
|
48
|
+
user: DDPlayer = await obj.player("Cor")
|
|
49
|
+
if user is not None:
|
|
50
|
+
text = f"{user.player}: {user.points.points}/{user.points.total}"
|
|
51
|
+
percent = round(user.points.total / user.points.points * 100)
|
|
52
|
+
print(f"{text}({percent}%)")
|
|
53
|
+
# Cor: 32950/32950(100%)
|
|
54
|
+
else:
|
|
55
|
+
print("Player not found")
|
|
58
56
|
|
|
59
57
|
|
|
60
58
|
asyncio.run(main())
|
|
61
59
|
```
|
|
62
60
|
|
|
63
61
|
Tested on Python
|
|
64
|
-
| 3.
|
|
65
|
-
|
|
66
|
-
|
|
|
62
|
+
| 3.10 | 3.11 | 3.12 |
|
|
63
|
+
|------|------|------|
|
|
64
|
+
| ✅ | ✅ | ✅ |
|
|
67
65
|
|
|
68
66
|
[other examples](https://github.com/ByFox213/ddapi/tree/main/example)
|
|
@@ -5,11 +5,13 @@ setup.py
|
|
|
5
5
|
ddapi/ddapi/__init__.py
|
|
6
6
|
ddapi/ddapi/api.py
|
|
7
7
|
ddapi/ddapi/main.py
|
|
8
|
+
ddapi/ddapi/types.py
|
|
8
9
|
ddapi/ddapi.egg-info/PKG-INFO
|
|
9
10
|
ddapi/ddapi.egg-info/SOURCES.txt
|
|
10
11
|
ddapi/ddapi.egg-info/dependency_links.txt
|
|
11
12
|
ddapi/ddapi.egg-info/top_level.txt
|
|
12
13
|
ddapi/ddapi/scheme/__init__.py
|
|
14
|
+
ddapi/ddapi/scheme/base.py
|
|
13
15
|
ddapi/ddapi/scheme/ddnet.py
|
|
14
16
|
ddapi/ddapi/scheme/ddstats_tw.py
|
|
15
17
|
ddapi/ddapi/scheme/status_tw.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = ddapi
|
|
3
|
-
version = 0.
|
|
3
|
+
version = 0.12.0
|
|
4
4
|
author = ByFox
|
|
5
5
|
description = DDnet api
|
|
6
6
|
long_description = file: README.md
|
|
@@ -8,16 +8,13 @@ long_description_content_type = text/markdown
|
|
|
8
8
|
url = https://github.com/ByFox213/ddapi
|
|
9
9
|
project_urls =
|
|
10
10
|
github = https://github.com/ByFox213/ddapi
|
|
11
|
-
|
|
12
|
-
Programming Language :: Python :: 3
|
|
13
|
-
License :: OSI Approved :: MIT License
|
|
14
|
-
Operating System :: OS Independent
|
|
11
|
+
license_files = LICENSE
|
|
15
12
|
|
|
16
13
|
[options]
|
|
17
14
|
package_dir =
|
|
18
15
|
= ddapi
|
|
19
16
|
packages = find:
|
|
20
|
-
python_requires = >=3.
|
|
17
|
+
python_requires = >=3.9
|
|
21
18
|
|
|
22
19
|
[options.packages.find]
|
|
23
20
|
where = ddapi
|
|
@@ -5,20 +5,16 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setuptools.setup(
|
|
7
7
|
name="ddapi",
|
|
8
|
-
version="0.
|
|
8
|
+
version="0.12.0",
|
|
9
9
|
author="ByFox",
|
|
10
10
|
description="DDnet api",
|
|
11
11
|
long_description=long_description,
|
|
12
12
|
long_description_content_type="text/markdown",
|
|
13
13
|
url="https://github.com/ByFox213/ddapi",
|
|
14
|
+
license="MIT",
|
|
14
15
|
project_urls={
|
|
15
16
|
"Github": "https://github.com/ByFox213/ddapi"
|
|
16
17
|
},
|
|
17
|
-
classifiers=[
|
|
18
|
-
"Programming Language :: Python :: 3",
|
|
19
|
-
"License :: OSI Approved :: MIT License",
|
|
20
|
-
"Operating System :: OS Independent",
|
|
21
|
-
],
|
|
22
18
|
package_dir={"": "ddapi"},
|
|
23
19
|
packages=setuptools.find_packages(where="ddapi"),
|
|
24
20
|
python_requires=">=3.8"
|
ddapi-0.9.3/README.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
ddapi is an api from the ddnet and qwik website
|
|
2
|
-
|
|
3
|
-
## Installation
|
|
4
|
-
|
|
5
|
-
```bash
|
|
6
|
-
pip install ddapi
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
or
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
pip install git+https://github.com/ByFox213/ddapi
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
## Usage/Examples
|
|
16
|
-
|
|
17
|
-
DDnet
|
|
18
|
-
|
|
19
|
-
```python
|
|
20
|
-
import asyncio
|
|
21
|
-
from ddapi import DDnetApi, DDPlayer
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
async def main():
|
|
25
|
-
obj = DDnetApi()
|
|
26
|
-
nickname = "Cor"
|
|
27
|
-
user: DDPlayer = await obj.player(nickname)
|
|
28
|
-
if user is None:
|
|
29
|
-
return "Player not found"
|
|
30
|
-
|
|
31
|
-
print(f"{user.player}: {user.points.points}")
|
|
32
|
-
# Cor: 31473
|
|
33
|
-
await obj.close() # Closing client Not necessary
|
|
34
|
-
assert isinstance(user, DDPlayer)
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
asyncio.run(main())
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Tested on Python
|
|
41
|
-
| 3.9 | 3.10 | 3.11 | 3.12 |
|
|
42
|
-
|-----|------|------|------|
|
|
43
|
-
| ? | ? | ✅ | ✅ |
|
|
44
|
-
|
|
45
|
-
[other examples](https://github.com/ByFox213/ddapi/tree/main/example)
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
# Status.tw
|
|
2
|
-
from datetime import datetime
|
|
3
|
-
from enum import StrEnum
|
|
4
|
-
from typing import Optional
|
|
5
|
-
|
|
6
|
-
from pydantic import BaseModel
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class ChartEnum(StrEnum):
|
|
10
|
-
day = "day"
|
|
11
|
-
week = "week"
|
|
12
|
-
month = "month"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class DataTw(BaseModel):
|
|
16
|
-
name: str
|
|
17
|
-
createdAt: datetime
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class VersionTw(BaseModel):
|
|
21
|
-
version: str
|
|
22
|
-
createdAt: datetime
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class CountryTw(BaseModel):
|
|
26
|
-
identifier: str
|
|
27
|
-
code: int
|
|
28
|
-
iconUrl: str
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class ClientTw(BaseModel):
|
|
32
|
-
name: str
|
|
33
|
-
country: CountryTw
|
|
34
|
-
score: int
|
|
35
|
-
isPlayer: bool
|
|
36
|
-
isAfk: bool
|
|
37
|
-
team: int
|
|
38
|
-
createdAt: datetime
|
|
39
|
-
clan: DataTw | None
|
|
40
|
-
server: "ServerTw" = None
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class ServerTw(BaseModel):
|
|
44
|
-
ip: str
|
|
45
|
-
port: int
|
|
46
|
-
name: str
|
|
47
|
-
numClients: int
|
|
48
|
-
numPlayers: int
|
|
49
|
-
maxClients: int
|
|
50
|
-
maxPlayers: int
|
|
51
|
-
hasPassword: bool
|
|
52
|
-
supports6: bool
|
|
53
|
-
supports7: bool
|
|
54
|
-
createdAt: datetime
|
|
55
|
-
relevanceScore: int
|
|
56
|
-
clientScoreKind: str | None
|
|
57
|
-
logoUrl: str
|
|
58
|
-
map: DataTw
|
|
59
|
-
website: Optional[str] = None
|
|
60
|
-
discordInvite: Optional[str] = None
|
|
61
|
-
description: Optional[str] = None
|
|
62
|
-
gameType: DataTw
|
|
63
|
-
version: VersionTw
|
|
64
|
-
clients: list[ClientTw]
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class ServerTwOne(BaseModel):
|
|
68
|
-
ip: str
|
|
69
|
-
port: int
|
|
70
|
-
online: ServerTw
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
class Chart(BaseModel):
|
|
74
|
-
avgPlayers: float
|
|
75
|
-
maxPlayers: int
|
|
76
|
-
minPlayers: int
|
|
77
|
-
timestamp: datetime
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
class Charts(BaseModel):
|
|
81
|
-
charts: list[Chart]
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class MasterTw(BaseModel):
|
|
85
|
-
servers: list[ServerTw]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
class Info(BaseModel):
|
|
89
|
-
app: str
|
|
90
|
-
version: str
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
class BannedMasterData(BaseModel):
|
|
94
|
-
ip: str
|
|
95
|
-
isActive: bool
|
|
96
|
-
reason: str | None
|
|
97
|
-
unbanDate: datetime | None
|
|
98
|
-
createdAt: datetime
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
class BannedMaster(BaseModel):
|
|
102
|
-
servers: list[BannedMasterData]
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
class ListData(BaseModel):
|
|
106
|
-
name: str
|
|
107
|
-
createdAt: datetime
|
|
108
|
-
servers: list[ServerTw]
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
class List(BaseModel):
|
|
112
|
-
data: list[ListData]
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
class ListPlData(BaseModel):
|
|
116
|
-
name: str
|
|
117
|
-
createdAt: datetime
|
|
118
|
-
players: list[ClientTw]
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
class ListPl(BaseModel):
|
|
122
|
-
data: list[ListPlData]
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
class Stats(BaseModel):
|
|
126
|
-
numPlayers: int
|
|
127
|
-
numClans: int
|
|
128
|
-
numServers: int
|
|
129
|
-
numMaps: int
|
|
130
|
-
numGameTypes: int
|
|
131
|
-
numVersions: int
|
|
File without changes
|
|
File without changes
|
|
File without changes
|