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.
- {ddapi-0.1.1 → ddapi-0.5.1}/LICENSE +1 -1
- ddapi-0.5.1/PKG-INFO +49 -0
- {ddapi-0.1.1 → ddapi-0.5.1}/README.md +5 -21
- ddapi-0.5.1/ddapi/ddapi/__init__.py +7 -0
- ddapi-0.5.1/ddapi/ddapi/dataclass.py +468 -0
- ddapi-0.5.1/ddapi/ddapi/deflt.py +63 -0
- ddapi-0.5.1/ddapi/ddapi/main.py +79 -0
- ddapi-0.5.1/ddapi/ddapi.egg-info/PKG-INFO +49 -0
- ddapi-0.5.1/ddapi/ddapi.egg-info/SOURCES.txt +12 -0
- {ddapi-0.1.1 → ddapi-0.5.1}/setup.cfg +1 -1
- {ddapi-0.1.1 → ddapi-0.5.1}/setup.py +2 -2
- ddapi-0.1.1/PKG-INFO +0 -97
- ddapi-0.1.1/ddapi/ddapi/DDnetApiPy/__init__.py +0 -1
- ddapi-0.1.1/ddapi/ddapi/DDnetApiPy/main.py +0 -48
- ddapi-0.1.1/ddapi/ddapi/__init__.py +0 -6
- ddapi-0.1.1/ddapi/ddapi/dataclass.py +0 -251
- ddapi-0.1.1/ddapi/ddapi/errors.py +0 -2
- ddapi-0.1.1/ddapi/ddapi/misc.py +0 -26
- ddapi-0.1.1/ddapi/ddapi/qwikDDnetApiPy/__init__.py +0 -1
- ddapi-0.1.1/ddapi/ddapi/qwikDDnetApiPy/main.py +0 -43
- ddapi-0.1.1/ddapi/ddapi.egg-info/PKG-INFO +0 -97
- ddapi-0.1.1/ddapi/ddapi.egg-info/SOURCES.txt +0 -18
- ddapi-0.1.1/ddapi/ddapi.egg-info/requires.txt +0 -10
- ddapi-0.1.1/pyproject.toml +0 -29
- {ddapi-0.1.1 → ddapi-0.5.1}/ddapi/ddapi.egg-info/dependency_links.txt +0 -0
- {ddapi-0.1.1 → ddapi-0.5.1}/ddapi/ddapi.egg-info/top_level.txt +0 -0
|
@@ -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
|
-
|
|
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,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()
|