ddapi 0.8.1__tar.gz → 0.9.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ddapi
3
- Version: 0.8.1
3
+ Version: 0.9.1
4
4
  Summary: DDnet api
5
5
  Home-page: https://github.com/ByFox213/ddapi
6
6
  Author: ByFox
@@ -2,6 +2,6 @@
2
2
  from .main import DDnetApi, DDstats, Status
3
3
  from .scheme import *
4
4
 
5
- __version__ = "0.8.1"
5
+ __version__ = "0.9.1"
6
6
  __author__ = 'ByFox'
7
7
  __LICENSE__ = "MIT"
@@ -0,0 +1,232 @@
1
+ from urllib.parse import quote
2
+
3
+ from .api import API
4
+ from .scheme import *
5
+
6
+ __all__ = (
7
+ "DDnetApi",
8
+ "DDstats",
9
+ "Status"
10
+ )
11
+
12
+
13
+ class MasterEnum(StrEnum):
14
+ master1 = "master1"
15
+ master2 = "master2"
16
+ master3 = "master3"
17
+ master4 = "master4"
18
+
19
+
20
+ class DDnetApi(API):
21
+ def __init__(self):
22
+ super().__init__()
23
+ self.domain = "ddnet.org"
24
+
25
+ @staticmethod
26
+ def powered() -> str:
27
+ return DDnetApi().domain
28
+
29
+ async def player(self, player: str) -> DDPlayer:
30
+ """Fetch player data from the API and return it as a dictionary."""
31
+ return await self._generate_model_instance(
32
+ f"https://{self.domain}/players/?json2={quote(player)}",
33
+ DDPlayer
34
+ )
35
+
36
+ async def status(self) -> DDStatus:
37
+ return await self._generate_model_instance(
38
+ f"https://{self.domain}/status/json/stats.json",
39
+ DDStatus
40
+ )
41
+
42
+ async def releases_map(self) -> ReleasesMaps:
43
+ return await self._generate_model_instance(
44
+ f"https://{self.domain}/releases/maps.json",
45
+ ReleasesMaps,
46
+ "maps"
47
+ )
48
+
49
+ async def query(self, player: str) -> Query:
50
+ return await self._generate_model_instance(
51
+ f"https://{self.domain}/players/?query={quote(player)}",
52
+ Query,
53
+ "players"
54
+ )
55
+
56
+ async def query_map(self, map_name: str) -> QueryMap:
57
+ return await self._generate_model_instance(
58
+ f"https://{self.domain}/maps/?query={quote(map_name)}",
59
+ QueryMap,
60
+ 'maps',
61
+ )
62
+
63
+ async def query_mapper(self, player: str) -> QueryMapper:
64
+ return await self._generate_model_instance(
65
+ f"https://{self.domain}/maps/?qmapper={quote(player)}",
66
+ QueryMapper,
67
+ 'players',
68
+ )
69
+
70
+ async def master(self, master: MasterEnum = MasterEnum.master1) -> Master:
71
+ return await self._generate_model_instance(
72
+ f"https://{master}.{self.domain}/ddnet/15/servers.json",
73
+ Master
74
+ )
75
+
76
+ async def map(self, map_name: str) -> DMap:
77
+ return await self._generate_model_instance(
78
+ f"https://{self.domain}/maps/?json={quote(map_name)}",
79
+ DMap
80
+ )
81
+
82
+
83
+ class DDstats(API):
84
+ def __init__(self):
85
+ super().__init__()
86
+ self.domain = 'ddstats.tw'
87
+
88
+ @staticmethod
89
+ def powered() -> str:
90
+ return DDstats().domain
91
+
92
+ async def player(self, player_name: str) -> Player:
93
+ """Fetch player data from the API and return it as a dictionary."""
94
+ return await self._generate_model_instance(
95
+ f"https://{self.domain}/player/json?player={quote(player_name)}",
96
+ Player
97
+ )
98
+
99
+
100
+ class Status(API):
101
+ def __init__(self):
102
+ super().__init__()
103
+ self.domain = 'status.tw'
104
+
105
+ @staticmethod
106
+ def powered() -> str:
107
+ return Status().domain
108
+
109
+ async def info(self) -> Info:
110
+ return await self._generate_model_instance(
111
+ f"https://api.{self.domain}/info",
112
+ Info
113
+ )
114
+
115
+ async def master_bans(self) -> BannedMaster:
116
+ return await self._generate_model_instance(
117
+ f"https://api.{self.domain}/master/bans/list",
118
+ BannedMaster,
119
+ "servers"
120
+ )
121
+
122
+ async def map_list(self) -> List:
123
+ return await self._generate_model_instance(
124
+ f"https://api.{self.domain}/map/list",
125
+ List,
126
+ "data"
127
+ )
128
+
129
+ async def map(self, name: str) -> ListData:
130
+ return await self._generate_model_instance(
131
+ f"https://api.{self.domain}/map/name/{quote(name)}",
132
+ ListData
133
+ )
134
+
135
+ async def gametype_list(self) -> List:
136
+ return await self._generate_model_instance(
137
+ f"https://api.{self.domain}/gametype/list",
138
+ List,
139
+ "data"
140
+ )
141
+
142
+ async def gametype(self, name: str) -> ListData:
143
+ return await self._generate_model_instance(
144
+ f"https://api.{self.domain}/gametype/name/{quote(name)}",
145
+ ListData
146
+ )
147
+
148
+ async def version_list(self) -> List:
149
+ return await self._generate_model_instance(
150
+ f"https://api.{self.domain}/version/list",
151
+ List,
152
+ "data"
153
+ )
154
+
155
+ async def version(self, name: str) -> ListData:
156
+ return await self._generate_model_instance(
157
+ f"https://api.{self.domain}/version/name/{quote(name)}",
158
+ ListData
159
+ )
160
+
161
+ async def server_list(self) -> MasterTw:
162
+ """Fetch player data from the API and return it as a dictionary."""
163
+ return await self._generate_model_instance(
164
+ f"https://api.{self.domain}/server/list",
165
+ MasterTw,
166
+ "servers"
167
+ )
168
+
169
+ async def server(self, ip: str, port: int | str) -> ServerTwOne:
170
+ return await self._generate_model_instance(
171
+ f"https://api.{self.domain}/server/{quote(ip)}/{port}",
172
+ ServerTwOne,
173
+ )
174
+
175
+ async def server_charts(self, ip: str, port: int | str, chart: ChartEnum = ChartEnum.day) -> Charts:
176
+ return await self._generate_model_instance(
177
+ f"https://api.{self.domain}/server/{quote(ip)}/{port}/chart/{chart}",
178
+ Charts,
179
+ "charts"
180
+ )
181
+
182
+ async def server_history(self, ip: str, port: int | str) -> None:
183
+ # https://api.status.tw/server/{ip}/{port}/history
184
+ raise NotImplementedError()
185
+
186
+ async def server_stats(self, ip: str, port: int | str) -> None:
187
+ # https://api.status.tw/server/{ip}/{port}/stats
188
+ raise NotImplementedError()
189
+
190
+ async def clan_list(self) -> ListPl:
191
+ return await self._generate_model_instance(
192
+ f"https://api.{self.domain}/clan/list",
193
+ ListPl,
194
+ "data"
195
+ )
196
+
197
+ async def clan(self, name: str) -> ListPlData:
198
+ return await self._generate_model_instance(
199
+ f"https://api.{self.domain}/clan/name/{quote(name)}",
200
+ ListPlData
201
+ )
202
+
203
+ async def player_list(self) -> ListPl:
204
+ return await self._generate_model_instance(
205
+ f"https://api.{self.domain}/player/list",
206
+ ListPl,
207
+ "data"
208
+ )
209
+
210
+ async def player(self, name: str) -> ListPlData:
211
+ return await self._generate_model_instance(
212
+ f"https://api.{self.domain}/player/name/{quote(name)}",
213
+ ListPlData
214
+ )
215
+
216
+ async def player_history(self, name: str) -> None:
217
+ # https://api.status.tw/player/name/{name}/history
218
+ raise NotImplementedError()
219
+
220
+ async def stats(self) -> Stats:
221
+ return await self._generate_model_instance(
222
+ f"https://api.{self.domain}/stats",
223
+ Stats
224
+ )
225
+
226
+ async def stats_players(self, t: str) -> None:
227
+ # https://api.status.tw/stats/players/day | week | month
228
+ raise NotImplementedError()
229
+
230
+ async def stats_servers(self, t: str) -> None:
231
+ # https://api.status.tw/stats/servers/week | month
232
+ raise NotImplementedError()
@@ -1,3 +1,7 @@
1
1
  from .ddnet import *
2
- from .status_tw import *
3
2
  from .ddstats_tw import *
3
+ from .status_tw import *
4
+
5
+ __version__ = "0.9.1"
6
+ __author__ = 'ByFox'
7
+ __LICENSE__ = "MIT"
@@ -0,0 +1,299 @@
1
+ # ddnet
2
+ from collections import Counter
3
+ from datetime import datetime
4
+ from typing import Optional, Any
5
+
6
+ from pydantic import BaseModel, Field
7
+
8
+ rm_list = ["DD-Persian", "/vDQMHSss8W", '']
9
+
10
+
11
+ class DPoints(BaseModel):
12
+ total: int
13
+ points: Optional[int] = Field(default=None)
14
+ rank: Optional[int] = Field(default=None)
15
+
16
+
17
+ class MaxFinishes(BaseModel):
18
+ rank: int
19
+ player: str
20
+ num: int
21
+ time: float
22
+ min_timestamp: int
23
+ max_timestamp: int
24
+
25
+
26
+ class DDRanks(BaseModel):
27
+ rank: int
28
+ player: str
29
+ time: float
30
+ timestamp: int
31
+ country: str
32
+
33
+
34
+ class DDTeamRanks(BaseModel):
35
+ rank: int
36
+ players: list[str]
37
+ time: float
38
+ timestamp: int
39
+ country: str
40
+
41
+
42
+ class DMap(BaseModel):
43
+ name: str
44
+ website: str
45
+ thumbnail: str
46
+ web_preview: str
47
+ type: str
48
+ points: int
49
+ difficulty: int
50
+ mapper: str
51
+ release: Optional[int] = None
52
+ median_time: float
53
+ first_finish: int
54
+ last_finish: int
55
+ finishes: int
56
+ finishers: int
57
+ biggest_team: int
58
+ width: int
59
+ height: int
60
+ tiles: list[str]
61
+ team_ranks: list[DDTeamRanks]
62
+ ranks: list[DDRanks]
63
+ max_finishes: list[MaxFinishes]
64
+
65
+
66
+ class DRank(BaseModel):
67
+ points: Optional[int] = None
68
+ rank: Optional[int] = None
69
+
70
+
71
+ class FirstFinish(BaseModel):
72
+ timestamp: float
73
+ map: str
74
+ time: float
75
+
76
+
77
+ class LastFinish(BaseModel):
78
+ timestamp: float
79
+ map: str
80
+ time: float
81
+ country: str
82
+ type: Optional[str] = None
83
+
84
+
85
+ class FavoritePartner(BaseModel):
86
+ name: str
87
+ finishes: int
88
+
89
+
90
+ class DData(BaseModel):
91
+ points: Optional[DPoints] = Field(default=None)
92
+ team_rank: Optional[DRank] = Field(default=None)
93
+ rank: Optional[DRank] = Field(default=None)
94
+ maps: Optional[dict] = Field(default=None)
95
+
96
+
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
+ class Activity(BaseModel):
114
+ date: str
115
+ hours_played: int
116
+
117
+
118
+ class FavoriteServer(BaseModel):
119
+ server: str
120
+
121
+
122
+ class DDPlayer(BaseModel):
123
+ player: str
124
+ points: DPoints
125
+ team_rank: Optional[DRank] = None
126
+ rank: Optional[DRank] = None
127
+ points_last_year: Optional[DRank] = None
128
+ points_last_month: Optional[DRank] = None
129
+ points_last_week: Optional[DRank] = None
130
+ favorite_server: FavoriteServer
131
+ first_finish: FirstFinish
132
+ last_finishes: list[LastFinish]
133
+ favorite_partners: Optional[list[FavoritePartner]] = None
134
+ types: DDType
135
+ activity: list[Activity]
136
+ hours_played_past_365_days: int
137
+
138
+
139
+ class Skin(BaseModel):
140
+ name: Optional[str] = None
141
+ color_body: Optional[int] = None
142
+ color_feet: Optional[int] = None
143
+
144
+
145
+ class Client(BaseModel):
146
+ name: str
147
+ clan: str
148
+ country: int
149
+ score: int
150
+ is_player: Optional[bool] = None
151
+ skin: Optional[Skin] = None
152
+ afk: Optional[bool] = None
153
+ team: Optional[int] = None
154
+
155
+
156
+ class Map(BaseModel):
157
+ name: str
158
+ sha256: Optional[str] = None
159
+ size: Optional[int] = None
160
+
161
+
162
+ class Community(BaseModel):
163
+ id: str
164
+ icon: str
165
+ admin: list[str]
166
+ public_key: Optional[str] = None
167
+ signature: Optional[str] = None
168
+
169
+
170
+ class Info(BaseModel):
171
+ max_clients: int
172
+ max_players: int
173
+ passworded: bool
174
+ game_type: str
175
+ name: str
176
+ map: Map
177
+ version: str
178
+ clients: Optional[list[Client]] = None
179
+ requires_login: Optional[bool] = None
180
+ community: Optional[Community] = None
181
+
182
+ def __len__(self) -> int:
183
+ return len(self.clients)
184
+
185
+
186
+ class Server(BaseModel):
187
+ addresses: list | str
188
+ location: str = Field(default=None)
189
+ info: Info
190
+
191
+ def __len__(self) -> int:
192
+ return self.count_client
193
+
194
+ @property
195
+ def count_client(self) -> int:
196
+ if self.info.clients is not None:
197
+ return len(self.info.clients)
198
+ return 0
199
+
200
+
201
+ class CountServers(BaseModel):
202
+ name: str
203
+ address: str
204
+ game_type: str
205
+ count_clients: int
206
+
207
+
208
+ class Master(BaseModel):
209
+ servers: list[Server]
210
+
211
+ def __len__(self) -> int:
212
+ return len(self.servers)
213
+
214
+ def get_clans(self, rm: list[str] = None) -> list[tuple[Any, int]]:
215
+ remove_list = rm_list.copy() if rm is None else rm
216
+ if not self.servers:
217
+ return []
218
+
219
+ dat: Counter[Any] = Counter(
220
+ client.clan
221
+ for server in self.servers
222
+ for client in server.info.clients
223
+ if client != ''
224
+ )
225
+
226
+ for i in remove_list:
227
+ del dat[i]
228
+ return sorted(dat.items(), key=lambda x: x[1], reverse=True)
229
+
230
+ @property
231
+ def count_servers(self) -> list[CountServers]:
232
+ return sorted(
233
+ (
234
+ CountServers(
235
+ count_clients=i.count_client,
236
+ address=i.addresses[0],
237
+ game_type=i.info.game_type,
238
+ name=i.info.name
239
+ )
240
+ if isinstance(i.addresses, list)
241
+ else CountServers(
242
+ count_clients=i.count_client,
243
+ address=i.addresses,
244
+ game_type=i.info.game_type,
245
+ name=i.info.name
246
+ )
247
+ for i in self.servers
248
+ ), key=lambda x: x.count_clients, reverse=True)
249
+
250
+ @property
251
+ def count_clients(self) -> int:
252
+ return sum(i.count_client for i in self.servers)
253
+
254
+
255
+ class ReleasesMapsData(BaseModel):
256
+ name: str
257
+ website: str
258
+ thumbnail: str
259
+ web_preview: str
260
+ type: str
261
+ points: int
262
+ difficulty: int
263
+ mapper: str
264
+ release: datetime | str
265
+ width: int
266
+ height: int
267
+ tiles: list[str]
268
+
269
+
270
+ class ReleasesMaps(BaseModel):
271
+ maps: list[ReleasesMapsData]
272
+
273
+
274
+ class QueryData(BaseModel):
275
+ points: int
276
+ name: str
277
+
278
+
279
+ class Query(BaseModel):
280
+ players: list[QueryData]
281
+
282
+
283
+ class QueryMapperData(BaseModel):
284
+ mapper: str
285
+ num_maps: int
286
+
287
+
288
+ class QueryMapper(BaseModel):
289
+ players: list[QueryMapperData]
290
+
291
+
292
+ class QueryMapData(BaseModel):
293
+ name: str
294
+ type: str
295
+ mapper: str
296
+
297
+
298
+ class QueryMap(BaseModel):
299
+ maps: list[QueryMapData]
@@ -1,7 +1,6 @@
1
1
  # ddstats.tw
2
- from collections import Counter
3
2
  from datetime import datetime
4
- from typing import Any, Union, Optional
3
+ from typing import Optional
5
4
 
6
5
  from pydantic import BaseModel, Field
7
6
 
@@ -178,6 +177,12 @@ class RecentTop10s(BaseModel):
178
177
  server: str
179
178
 
180
179
 
180
+ class GeneralActivity(BaseModel):
181
+ total_seconds_played: int
182
+ start_of_playtime: datetime
183
+ average_seconds_played: int
184
+
185
+
181
186
  class Player(BaseModel):
182
187
  points_graph: list[PointG]
183
188
  recent_finishes: list[RecentFinishes]
@@ -194,136 +199,12 @@ class Player(BaseModel):
194
199
  most_played_categories: Optional[list[MostPlayed]] = None
195
200
  most_played_locations: Optional[list[MostPlayed]] = None
196
201
  playtime_per_month: list[PlaytimePerMonth]
202
+ general_activity: GeneralActivity
197
203
  favourite_rank1s_teammates: Optional[list[FavouriteRank1sTeammates]] = None
198
204
  all_top_10s: Optional[list[AllTop10s]] = None
199
205
  recent_top_10s: Optional[list[RecentTop10s]] = None
200
206
 
201
207
 
202
- class Skin(BaseModel):
203
- name: Optional[str] = None
204
- color_body: Optional[int] = None
205
- color_feet: Optional[int] = None
206
-
207
-
208
- class Client(BaseModel):
209
- name: str
210
- clan: str
211
- country: int
212
- score: int
213
- is_player: Optional[bool] = None
214
- skin: Optional[Skin] = None
215
- afk: Optional[bool] = None
216
- team: Optional[int] = None
217
-
218
-
219
- class Map(BaseModel):
220
- name: str
221
- sha256: Optional[str] = None
222
- size: Optional[int] = None
223
-
224
-
225
- class Community(BaseModel):
226
- id: str
227
- icon: str
228
- admin: list[str]
229
- public_key: Optional[str] = None
230
- signature: Optional[str] = None
231
-
232
-
233
- class Info(BaseModel):
234
- max_clients: int
235
- max_players: int
236
- passworded: bool
237
- game_type: str
238
- name: str
239
- map: Map
240
- version: str
241
- clients: Optional[list[Client]] = None
242
- requires_login: Optional[bool] = None
243
- community: Optional[Community] = None
244
-
245
- def __len__(self) -> int:
246
- return len(self.clients)
247
-
248
-
249
- class Server(BaseModel):
250
- addresses: Union[list, str]
251
- location: str = Field(default=None)
252
- info: Info
253
-
254
- def __len__(self) -> int:
255
- return self.count_client
256
-
257
- @property
258
- def count_client(self) -> int:
259
- if self.info.clients is not None:
260
- return len(self.info.clients)
261
- return 0
262
-
263
-
264
- class CountServers(BaseModel):
265
- name: str
266
- address: str
267
- game_type: str
268
- count_clients: int
269
-
270
-
271
- class Master(BaseModel):
272
- servers: list[Server]
273
-
274
- def __len__(self) -> int:
275
- return len(self.servers)
276
-
277
- def get_clans(self, rm: list[str] = None) -> list[tuple[Any, int]]:
278
- remove_list = rm_list.copy() if rm is None else rm
279
- if not self.servers:
280
- return []
281
-
282
- dat: Counter[Any] = Counter(
283
- client.clan
284
- for server in self.servers
285
- for client in server.info.clients
286
- if client != ''
287
- )
288
-
289
- for i in remove_list:
290
- del dat[i]
291
- return sorted(dat.items(), key=lambda x: x[1], reverse=True)
292
-
293
- @property
294
- def count_servers(self) -> list[CountServers]:
295
- return sorted(
296
- (
297
- CountServers(
298
- count_clients=i.count_client,
299
- address=i.addresses[0],
300
- game_type=i.info.game_type,
301
- name=i.info.name
302
- )
303
- if isinstance(i.addresses, list)
304
- else CountServers(
305
- count_clients=i.count_client,
306
- address=i.addresses,
307
- game_type=i.info.game_type,
308
- name=i.info.name
309
- )
310
- for i in self.servers
311
- ), key=lambda x: x.count_clients, reverse=True)
312
-
313
- @property
314
- def count_clients(self) -> int:
315
- return sum(i.count_client for i in self.servers)
316
-
317
-
318
- class QueryData(BaseModel):
319
- points: int
320
- name: str
321
-
322
-
323
- class Query(BaseModel):
324
- data: list[QueryData]
325
-
326
-
327
208
  class DDStatusData(BaseModel):
328
209
  name: str = None
329
210
  type: str = None
@@ -37,6 +37,7 @@ class ClientTw(BaseModel):
37
37
  team: int
38
38
  createdAt: datetime
39
39
  clan: DataTw | None
40
+ server: "ServerTw" = None
40
41
 
41
42
 
42
43
  class ServerTw(BaseModel):
@@ -82,3 +83,49 @@ class Charts(BaseModel):
82
83
 
83
84
  class MasterTw(BaseModel):
84
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ddapi
3
- Version: 0.8.1
3
+ Version: 0.9.1
4
4
  Summary: DDnet api
5
5
  Home-page: https://github.com/ByFox213/ddapi
6
6
  Author: ByFox
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = ddapi
3
- version = 0.8.1
3
+ version = 0.9.1
4
4
  author = ByFox
5
5
  description = DDnet api
6
6
  long_description = file: README.md
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="ddapi",
8
- version="0.8.1",
8
+ version="0.9.1",
9
9
  author="ByFox",
10
10
  description="DDnet api",
11
11
  long_description=long_description,
@@ -1,173 +0,0 @@
1
- from typing import Union
2
- from urllib.parse import quote
3
-
4
- from .api import API
5
- from .scheme import DDPlayer, Master, Query, DMap, DDStatus, Player, MasterTw, ServerTwOne, ChartEnum, Charts
6
-
7
- __all__ = (
8
- "DDnetApi",
9
- "DDstats",
10
- "Status"
11
- )
12
-
13
-
14
- class DDnetApi(API):
15
- def __init__(self):
16
- super().__init__()
17
- self.domain = "ddnet.org"
18
-
19
- @staticmethod
20
- def powered() -> str:
21
- return DDnetApi().domain
22
-
23
- async def player(self, player_name: str) -> DDPlayer:
24
- """Fetch player data from the API and return it as a dictionary."""
25
- return await self._generate_model_instance(
26
- f"https://{self.domain}/players/?json2={quote(player_name)}",
27
- DDPlayer
28
- )
29
-
30
- async def status(self) -> Union[DDStatus, None]:
31
- return await self._generate_model_instance(
32
- f"https://{self.domain}/status/json/stats.json",
33
- DDStatus
34
- )
35
-
36
- async def query(self, player: str) -> Union[Query, None]:
37
- return await self._generate_model_instance(
38
- f"https://{self.domain}/players/?query={quote(player)}",
39
- Query,
40
- "data"
41
- )
42
-
43
- async def master(self) -> Union[Master, None]:
44
- return await self._generate_model_instance(
45
- f"https://master1.{self.domain}/ddnet/15/servers.json",
46
- Master
47
- )
48
-
49
- async def map(self, map_name: str) -> Union[DMap, None]:
50
- return await self._generate_model_instance(
51
- f"https://{self.domain}/maps/?json={quote(map_name)}",
52
- DMap
53
- )
54
-
55
-
56
- class DDstats(API):
57
- def __init__(self):
58
- super().__init__()
59
- self.domain = 'ddstats.tw'
60
-
61
- @staticmethod
62
- def powered() -> str:
63
- return DDstats().domain
64
-
65
- async def player(self, player_name: str) -> Player:
66
- """Fetch player data from the API and return it as a dictionary."""
67
- return await self._generate_model_instance(
68
- f"https://{self.domain}/player/json?player={quote(player_name)}",
69
- Player
70
- )
71
-
72
-
73
- class Status(API):
74
- def __init__(self):
75
- super().__init__()
76
- self.domain = 'status.tw'
77
-
78
- @staticmethod
79
- def powered() -> str:
80
- return Status().domain
81
-
82
- async def info(self) -> None:
83
- # https://api.status.tw/info
84
- raise NotImplementedError()
85
-
86
- async def master_bans(self) -> None:
87
- # https://api.status.tw/master/bans/list
88
- raise NotImplementedError()
89
-
90
- async def map_list(self) -> None:
91
- # https://api.status.tw/map/list
92
- raise NotImplementedError()
93
-
94
- async def map(self, name: str) -> None:
95
- # https://api.status.tw/map/name/{name}
96
- raise NotImplementedError()
97
-
98
- async def gametype_list(self) -> None:
99
- # https://api.status.tw/gametype/list
100
- raise NotImplementedError()
101
-
102
- async def gametype(self, name: str) -> None:
103
- # https://api.status.tw/gametype/name/{name}
104
- raise NotImplementedError()
105
-
106
- async def version_list(self) -> None:
107
- # https://api.status.tw/version/list
108
- raise NotImplementedError()
109
-
110
- async def version(self, name: str) -> None:
111
- # https://api.status.tw/version/name/{name}
112
- raise NotImplementedError()
113
-
114
- async def server_list(self) -> MasterTw:
115
- """Fetch player data from the API and return it as a dictionary."""
116
- return await self._generate_model_instance(
117
- f"https://api.{self.domain}/server/list",
118
- MasterTw,
119
- "servers"
120
- )
121
-
122
- async def server(self, ip: str, port: Union[int, str]) -> ServerTwOne:
123
- return await self._generate_model_instance(
124
- f"https://api.{self.domain}/server/{quote(ip)}/{port}",
125
- ServerTwOne,
126
- )
127
-
128
- async def server_charts(self, ip: str, port: Union[int, str], chart: ChartEnum = ChartEnum.day) -> Charts:
129
- return await self._generate_model_instance(
130
- f"https://api.{self.domain}/server/{quote(ip)}/{port}/chart/{chart}",
131
- Charts,
132
- "charts"
133
- )
134
-
135
- async def server_history(self, ip: str, port: Union[int, str]) -> None:
136
- # https://api.status.tw/server/{ip}/{port}/history
137
- raise NotImplementedError()
138
-
139
- async def server_stats(self, ip: str, port: Union[int, str]) -> None:
140
- # https://api.status.tw/server/{ip}/{port}/stats
141
- raise NotImplementedError()
142
-
143
- async def clan_list(self) -> None:
144
- # https://api.status.tw/clan/list
145
- raise NotImplementedError()
146
-
147
- async def clan(self, name: str) -> None:
148
- # https://api.status.tw/clan/name/{name}
149
- raise NotImplementedError()
150
-
151
- async def player_list(self) -> None:
152
- # https://api.status.tw/player/list
153
- raise NotImplementedError()
154
-
155
- async def player(self, name: str) -> None:
156
- # https://api.status.tw/player/name/{name}
157
- raise NotImplementedError()
158
-
159
- async def player_history(self, name: str) -> None:
160
- # https://api.status.tw/player/name/{name}/history
161
- raise NotImplementedError()
162
-
163
- async def stats(self) -> None:
164
- # https://api.status.tw/stats
165
- raise NotImplementedError()
166
-
167
- async def stats_players(self, t: str) -> None:
168
- # https://api.status.tw/stats/players/day week month
169
- raise NotImplementedError()
170
-
171
- async def stats_servers(self, t: str) -> None:
172
- # https://api.status.tw/stats/servers/week month
173
- raise NotImplementedError()
@@ -1,132 +0,0 @@
1
- # ddnet
2
- from typing import Optional
3
-
4
- from pydantic import BaseModel, Field
5
-
6
-
7
- class DPoints(BaseModel):
8
- total: int
9
- points: Optional[int] = Field(default=None)
10
- rank: Optional[int] = Field(default=None)
11
-
12
-
13
- class MaxFinishes(BaseModel):
14
- rank: int
15
- player: str
16
- num: int
17
- time: float
18
- min_timestamp: int
19
- max_timestamp: int
20
-
21
-
22
- class DDRanks(BaseModel):
23
- rank: int
24
- player: str
25
- time: float
26
- timestamp: int
27
- country: str
28
-
29
-
30
- class DDTeamRanks(BaseModel):
31
- rank: int
32
- players: list[str]
33
- time: float
34
- timestamp: int
35
- country: str
36
-
37
-
38
- class DMap(BaseModel):
39
- name: str
40
- website: str
41
- thumbnail: str
42
- web_preview: str
43
- type: str
44
- points: int
45
- difficulty: int
46
- mapper: str
47
- release: Optional[int] = None
48
- median_time: float
49
- first_finish: int
50
- last_finish: int
51
- finishes: int
52
- finishers: int
53
- biggest_team: int
54
- width: int
55
- height: int
56
- tiles: list[str]
57
- team_ranks: list[DDTeamRanks]
58
- ranks: list[DDRanks]
59
- max_finishes: list[MaxFinishes]
60
-
61
-
62
- class DRank(BaseModel):
63
- points: Optional[int] = None
64
- rank: Optional[int] = None
65
-
66
-
67
- class FirstFinish(BaseModel):
68
- timestamp: float
69
- map: str
70
- time: float
71
-
72
-
73
- class LastFinish(BaseModel):
74
- timestamp: float
75
- map: str
76
- time: float
77
- country: str
78
- type: Optional[str] = None
79
-
80
-
81
- class FavoritePartner(BaseModel):
82
- name: str
83
- finishes: int
84
-
85
-
86
- class DData(BaseModel):
87
- points: Optional[DPoints] = Field(default=None)
88
- team_rank: Optional[DRank] = Field(default=None)
89
- rank: Optional[DRank] = Field(default=None)
90
- maps: Optional[dict] = Field(default=None)
91
-
92
-
93
- class DDType(BaseModel):
94
- Novice: Optional[DData] = None
95
- Moderate: Optional[DData] = None
96
- Brutal: Optional[DData] = None
97
- Insane: Optional[DData] = None
98
- Dummy: Optional[DData] = None
99
- DDmaX_Easy: Optional[DData] = Field(default=None, validation_alias='DDmaX.Easy')
100
- DDmaX_Next: Optional[DData] = Field(default=None, validation_alias='DDmaX.Next')
101
- DDmaX_Nut: Optional[DData] = Field(default=None, validation_alias='DDmaX.Nut')
102
- DDmaX_Pro: Optional[DData] = Field(default=None, validation_alias='DDmaX.Pro')
103
- Oldschool: Optional[DData] = Field(default=None)
104
- Race: Optional[DData] = None
105
- Solo: Optional[DData] = None
106
- total: Optional[DData] = None
107
-
108
-
109
- class Activity(BaseModel):
110
- date: str
111
- hours_played: int
112
-
113
-
114
- class FavoriteServer(BaseModel):
115
- server: str
116
-
117
-
118
- class DDPlayer(BaseModel):
119
- player: str
120
- points: DPoints
121
- team_rank: Optional[DRank] = None
122
- rank: Optional[DRank] = None
123
- points_last_year: Optional[DRank] = None
124
- points_last_month: Optional[DRank] = None
125
- points_last_week: Optional[DRank] = None
126
- favorite_server: FavoriteServer
127
- first_finish: FirstFinish
128
- last_finishes: list[LastFinish]
129
- favorite_partners: Optional[list[FavoritePartner]] = None
130
- types: DDType
131
- activity: list[Activity]
132
- hours_played_past_365_days: int
File without changes
File without changes
File without changes