rlstatsapi 0.1.1__tar.gz → 0.1.2__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.
- {rlstatsapi-0.1.1/src/rlstatsapi.egg-info → rlstatsapi-0.1.2}/PKG-INFO +30 -4
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/README.md +30 -4
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/pyproject.toml +30 -30
- rlstatsapi-0.1.2/src/rlstatsapi/__init__.py +25 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/src/rlstatsapi/client.py +1 -1
- rlstatsapi-0.1.2/src/rlstatsapi/types.py +373 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2/src/rlstatsapi.egg-info}/PKG-INFO +30 -4
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/src/rlstatsapi.egg-info/SOURCES.txt +1 -0
- rlstatsapi-0.1.1/src/rlstatsapi/__init__.py +0 -7
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/LICENSE +0 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/setup.cfg +0 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/src/rlstatsapi/events.py +0 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/src/rlstatsapi/models.py +0 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/src/rlstatsapi.egg-info/dependency_links.txt +0 -0
- {rlstatsapi-0.1.1 → rlstatsapi-0.1.2}/src/rlstatsapi.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rlstatsapi
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Rocket League Stats API client
|
|
5
5
|
Author: Manuel Cabral
|
|
6
6
|
License: MIT
|
|
@@ -32,7 +32,7 @@ pip install rlstatsapi
|
|
|
32
32
|
From GitHub (latest `main`):
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
pip install git+https://github.com/
|
|
35
|
+
pip install git+https://github.com/manucabral/RocketLeagueStatsAPI.git
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## Rocket League setup
|
|
@@ -57,7 +57,6 @@ from rlstatsapi import StatsClient
|
|
|
57
57
|
|
|
58
58
|
logging.basicConfig(level=logging.INFO)
|
|
59
59
|
|
|
60
|
-
|
|
61
60
|
async def main() -> None:
|
|
62
61
|
client = StatsClient(log_enabled=True)
|
|
63
62
|
client.on_any(lambda msg: print(msg.event, msg.data))
|
|
@@ -68,17 +67,44 @@ async def main() -> None:
|
|
|
68
67
|
finally:
|
|
69
68
|
await client.disconnect()
|
|
70
69
|
|
|
70
|
+
asyncio.run(main())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Example Event (Goals)
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from rlstatsapi import StatsClient
|
|
78
|
+
from rlstatsapi.models import EventMessage
|
|
79
|
+
from rlstatsapi.types import GoalScoredPayload, cast_event_data
|
|
80
|
+
|
|
81
|
+
async def on_goal(msg: EventMessage) -> None:
|
|
82
|
+
data: GoalScoredPayload = cast_event_data("GoalScored", msg.data)
|
|
83
|
+
scorer = data.get("Scorer", {})
|
|
84
|
+
print("Goal by:", scorer.get("Name"))
|
|
85
|
+
|
|
86
|
+
async def main() -> None:
|
|
87
|
+
client = StatsClient()
|
|
88
|
+
client.on("GoalScored", on_goal)
|
|
89
|
+
await client.connect()
|
|
90
|
+
try:
|
|
91
|
+
await asyncio.Event().wait()
|
|
92
|
+
finally:
|
|
93
|
+
await client.disconnect()
|
|
71
94
|
|
|
72
95
|
asyncio.run(main())
|
|
73
96
|
```
|
|
74
97
|
|
|
98
|
+
|
|
75
99
|
## Public API
|
|
76
100
|
|
|
77
|
-
- `StatsClient(
|
|
101
|
+
- `StatsClient(...)`
|
|
78
102
|
- `connect()` / `disconnect()`
|
|
79
103
|
- `on(event_name, handler)`
|
|
80
104
|
- `on_any(handler)`
|
|
81
105
|
- `events()`
|
|
106
|
+
- typed helpers: `EventName`, `TypedEventMessage[...]`, `cast_event_data(...)`
|
|
107
|
+
|
|
82
108
|
|
|
83
109
|
## Notes
|
|
84
110
|
|
|
@@ -13,7 +13,7 @@ pip install rlstatsapi
|
|
|
13
13
|
From GitHub (latest `main`):
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
pip install git+https://github.com/
|
|
16
|
+
pip install git+https://github.com/manucabral/RocketLeagueStatsAPI.git
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## Rocket League setup
|
|
@@ -38,7 +38,6 @@ from rlstatsapi import StatsClient
|
|
|
38
38
|
|
|
39
39
|
logging.basicConfig(level=logging.INFO)
|
|
40
40
|
|
|
41
|
-
|
|
42
41
|
async def main() -> None:
|
|
43
42
|
client = StatsClient(log_enabled=True)
|
|
44
43
|
client.on_any(lambda msg: print(msg.event, msg.data))
|
|
@@ -49,19 +48,46 @@ async def main() -> None:
|
|
|
49
48
|
finally:
|
|
50
49
|
await client.disconnect()
|
|
51
50
|
|
|
51
|
+
asyncio.run(main())
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Example Event (Goals)
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import asyncio
|
|
58
|
+
from rlstatsapi import StatsClient
|
|
59
|
+
from rlstatsapi.models import EventMessage
|
|
60
|
+
from rlstatsapi.types import GoalScoredPayload, cast_event_data
|
|
61
|
+
|
|
62
|
+
async def on_goal(msg: EventMessage) -> None:
|
|
63
|
+
data: GoalScoredPayload = cast_event_data("GoalScored", msg.data)
|
|
64
|
+
scorer = data.get("Scorer", {})
|
|
65
|
+
print("Goal by:", scorer.get("Name"))
|
|
66
|
+
|
|
67
|
+
async def main() -> None:
|
|
68
|
+
client = StatsClient()
|
|
69
|
+
client.on("GoalScored", on_goal)
|
|
70
|
+
await client.connect()
|
|
71
|
+
try:
|
|
72
|
+
await asyncio.Event().wait()
|
|
73
|
+
finally:
|
|
74
|
+
await client.disconnect()
|
|
52
75
|
|
|
53
76
|
asyncio.run(main())
|
|
54
77
|
```
|
|
55
78
|
|
|
79
|
+
|
|
56
80
|
## Public API
|
|
57
81
|
|
|
58
|
-
- `StatsClient(
|
|
82
|
+
- `StatsClient(...)`
|
|
59
83
|
- `connect()` / `disconnect()`
|
|
60
84
|
- `on(event_name, handler)`
|
|
61
85
|
- `on_any(handler)`
|
|
62
86
|
- `events()`
|
|
87
|
+
- typed helpers: `EventName`, `TypedEventMessage[...]`, `cast_event_data(...)`
|
|
88
|
+
|
|
63
89
|
|
|
64
90
|
## Notes
|
|
65
91
|
|
|
66
92
|
- Works for regular matches. Some fields like `MatchGuid` are only present in online/LAN contexts.
|
|
67
|
-
- In current builds this endpoint may behave as plain TCP JSON stream instead of websocket upgrade. This library handles the TCP stream format.
|
|
93
|
+
- In current builds this endpoint may behave as plain TCP JSON stream instead of websocket upgrade. This library handles the TCP stream format.
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["setuptools>=69", "wheel"]
|
|
3
|
-
build-backend = "setuptools.build_meta"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "rlstatsapi"
|
|
7
|
-
version = "0.1.
|
|
8
|
-
description = "Rocket League Stats API client"
|
|
9
|
-
readme = "README.md"
|
|
10
|
-
requires-python = ">=3.11"
|
|
11
|
-
license = { text = "MIT" }
|
|
12
|
-
authors = [{ name = "Manuel Cabral" }]
|
|
13
|
-
keywords = ["rocket-league", "stats", "socket", "asyncio"]
|
|
14
|
-
classifiers = [
|
|
15
|
-
"Programming Language :: Python :: 3",
|
|
16
|
-
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
-
"License :: OSI Approved :: MIT License",
|
|
18
|
-
"Operating System :: OS Independent",
|
|
19
|
-
"Topic :: Games/Entertainment",
|
|
20
|
-
"Topic :: Software Development :: Libraries",
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
[project.urls]
|
|
24
|
-
Homepage = "https://github.com/manucabral/RocketLeagueStatsAPI"
|
|
25
|
-
|
|
26
|
-
[tool.setuptools]
|
|
27
|
-
package-dir = {"" = "src"}
|
|
28
|
-
|
|
29
|
-
[tool.setuptools.packages.find]
|
|
30
|
-
where = ["src"]
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "rlstatsapi"
|
|
7
|
+
version = "0.1.2"
|
|
8
|
+
description = "Rocket League Stats API client"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Manuel Cabral" }]
|
|
13
|
+
keywords = ["rocket-league", "stats", "socket", "asyncio"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Topic :: Games/Entertainment",
|
|
20
|
+
"Topic :: Software Development :: Libraries",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://github.com/manucabral/RocketLeagueStatsAPI"
|
|
25
|
+
|
|
26
|
+
[tool.setuptools]
|
|
27
|
+
package-dir = {"" = "src"}
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.packages.find]
|
|
30
|
+
where = ["src"]
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""rlstatsapi public API."""
|
|
2
|
+
|
|
3
|
+
from .client import StatsClient
|
|
4
|
+
from .events import KNOWN_EVENTS
|
|
5
|
+
from .models import EventMessage
|
|
6
|
+
from .types import (
|
|
7
|
+
EventName,
|
|
8
|
+
GoalScoredPayload,
|
|
9
|
+
KnownEventMessage,
|
|
10
|
+
TypedEventMessage,
|
|
11
|
+
UpdateStatePayload,
|
|
12
|
+
cast_event_data,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"StatsClient",
|
|
17
|
+
"EventMessage",
|
|
18
|
+
"KNOWN_EVENTS",
|
|
19
|
+
"EventName",
|
|
20
|
+
"TypedEventMessage",
|
|
21
|
+
"KnownEventMessage",
|
|
22
|
+
"UpdateStatePayload",
|
|
23
|
+
"GoalScoredPayload",
|
|
24
|
+
"cast_event_data",
|
|
25
|
+
]
|
|
@@ -181,4 +181,4 @@ def _parse_message_obj(
|
|
|
181
181
|
if not isinstance(event, str) or not isinstance(data, dict):
|
|
182
182
|
return None
|
|
183
183
|
|
|
184
|
-
return EventMessage(event=event, data=data, raw=raw if include_raw else None)
|
|
184
|
+
return EventMessage(event=event, data=data, raw=raw if include_raw else None)
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Generic, Literal, Mapping, TypeAlias, TypeVar, TypedDict, cast, overload
|
|
5
|
+
|
|
6
|
+
EventName: TypeAlias = Literal[
|
|
7
|
+
"UpdateState",
|
|
8
|
+
"BallHit",
|
|
9
|
+
"ClockUpdatedSeconds",
|
|
10
|
+
"CountdownBegin",
|
|
11
|
+
"CrossbarHit",
|
|
12
|
+
"GoalReplayEnd",
|
|
13
|
+
"GoalReplayStart",
|
|
14
|
+
"GoalReplayWillEnd",
|
|
15
|
+
"GoalScored",
|
|
16
|
+
"MatchCreated",
|
|
17
|
+
"MatchInitialized",
|
|
18
|
+
"MatchDestroyed",
|
|
19
|
+
"MatchEnded",
|
|
20
|
+
"MatchPaused",
|
|
21
|
+
"MatchUnpaused",
|
|
22
|
+
"PodiumStart",
|
|
23
|
+
"ReplayCreated",
|
|
24
|
+
"RoundStarted",
|
|
25
|
+
"StatfeedEvent",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Vector3(TypedDict):
|
|
30
|
+
X: float
|
|
31
|
+
Y: float
|
|
32
|
+
Z: float
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PlayerRef(TypedDict):
|
|
36
|
+
Name: str
|
|
37
|
+
Shortcut: int
|
|
38
|
+
TeamNum: int
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class TeamState(TypedDict):
|
|
42
|
+
Name: str
|
|
43
|
+
TeamNum: int
|
|
44
|
+
Score: int
|
|
45
|
+
ColorPrimary: str
|
|
46
|
+
ColorSecondary: str
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class BallState(TypedDict):
|
|
50
|
+
Speed: float
|
|
51
|
+
TeamNum: int
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class PlayerAttacker(TypedDict):
|
|
55
|
+
Name: str
|
|
56
|
+
Shortcut: int
|
|
57
|
+
TeamNum: int
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class TargetRef(TypedDict):
|
|
61
|
+
Name: str
|
|
62
|
+
Shortcut: int
|
|
63
|
+
TeamNum: int
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class UpdateStatePlayer(TypedDict, total=False):
|
|
67
|
+
Name: str
|
|
68
|
+
PrimaryId: str
|
|
69
|
+
Shortcut: int
|
|
70
|
+
TeamNum: int
|
|
71
|
+
Score: int
|
|
72
|
+
Goals: int
|
|
73
|
+
Shots: int
|
|
74
|
+
Assists: int
|
|
75
|
+
Saves: int
|
|
76
|
+
Touches: int
|
|
77
|
+
CarTouches: int
|
|
78
|
+
Demos: int
|
|
79
|
+
bHasCar: bool
|
|
80
|
+
Speed: float
|
|
81
|
+
Boost: int
|
|
82
|
+
bBoosting: bool
|
|
83
|
+
bOnGround: bool
|
|
84
|
+
bOnWall: bool
|
|
85
|
+
bPowersliding: bool
|
|
86
|
+
bDemolished: bool
|
|
87
|
+
Attacker: PlayerAttacker
|
|
88
|
+
bSupersonic: bool
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class UpdateStateGame(TypedDict, total=False):
|
|
92
|
+
Teams: list[TeamState]
|
|
93
|
+
TimeSeconds: int
|
|
94
|
+
bOvertime: bool
|
|
95
|
+
Frame: int
|
|
96
|
+
Elapsed: float
|
|
97
|
+
Ball: BallState
|
|
98
|
+
bReplay: bool
|
|
99
|
+
bHasWinner: bool
|
|
100
|
+
Winner: str
|
|
101
|
+
Arena: str
|
|
102
|
+
bHasTarget: bool
|
|
103
|
+
Target: TargetRef
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class UpdateStatePayload(TypedDict, total=False):
|
|
107
|
+
MatchGuid: str
|
|
108
|
+
Players: list[UpdateStatePlayer]
|
|
109
|
+
Game: UpdateStateGame
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class BallHitBall(TypedDict):
|
|
113
|
+
PreHitSpeed: float
|
|
114
|
+
PostHitSpeed: float
|
|
115
|
+
Location: Vector3
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class BallHitPayload(TypedDict, total=False):
|
|
119
|
+
MatchGuid: str
|
|
120
|
+
Players: list[PlayerRef]
|
|
121
|
+
Ball: BallHitBall
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class ClockUpdatedSecondsPayload(TypedDict, total=False):
|
|
125
|
+
MatchGuid: str
|
|
126
|
+
TimeSeconds: int
|
|
127
|
+
bOvertime: bool
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class CountdownBeginPayload(TypedDict, total=False):
|
|
131
|
+
MatchGuid: str
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class BallLastTouch(TypedDict):
|
|
135
|
+
Player: PlayerRef
|
|
136
|
+
Speed: float
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class CrossbarHitPayload(TypedDict, total=False):
|
|
140
|
+
MatchGuid: str
|
|
141
|
+
BallLocation: Vector3
|
|
142
|
+
BallSpeed: float
|
|
143
|
+
ImpactForce: float
|
|
144
|
+
BallLastTouch: BallLastTouch
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class GoalReplayEndPayload(TypedDict, total=False):
|
|
148
|
+
MatchGuid: str
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class GoalReplayStartPayload(TypedDict, total=False):
|
|
152
|
+
MatchGuid: str
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class GoalReplayWillEndPayload(TypedDict, total=False):
|
|
156
|
+
MatchGuid: str
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class GoalScoredPayload(TypedDict, total=False):
|
|
160
|
+
MatchGuid: str
|
|
161
|
+
GoalSpeed: float
|
|
162
|
+
GoalTime: float
|
|
163
|
+
ImpactLocation: Vector3
|
|
164
|
+
Scorer: PlayerRef
|
|
165
|
+
Assister: PlayerRef
|
|
166
|
+
BallLastTouch: BallLastTouch
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class MatchCreatedPayload(TypedDict, total=False):
|
|
170
|
+
MatchGuid: str
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
class MatchInitializedPayload(TypedDict, total=False):
|
|
174
|
+
MatchGuid: str
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class MatchDestroyedPayload(TypedDict, total=False):
|
|
178
|
+
MatchGuid: str
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class MatchEndedPayload(TypedDict, total=False):
|
|
182
|
+
MatchGuid: str
|
|
183
|
+
WinnerTeamNum: int
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class MatchPausedPayload(TypedDict, total=False):
|
|
187
|
+
MatchGuid: str
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class MatchUnpausedPayload(TypedDict, total=False):
|
|
191
|
+
MatchGuid: str
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
class PodiumStartPayload(TypedDict, total=False):
|
|
195
|
+
MatchGuid: str
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
class ReplayCreatedPayload(TypedDict, total=False):
|
|
199
|
+
MatchGuid: str
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class RoundStartedPayload(TypedDict, total=False):
|
|
203
|
+
MatchGuid: str
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class StatfeedEventPayload(TypedDict, total=False):
|
|
207
|
+
MatchGuid: str
|
|
208
|
+
EventName: str
|
|
209
|
+
Type: str
|
|
210
|
+
MainTarget: PlayerRef
|
|
211
|
+
SecondaryTarget: PlayerRef
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
KnownEventPayload: TypeAlias = (
|
|
215
|
+
UpdateStatePayload
|
|
216
|
+
| BallHitPayload
|
|
217
|
+
| ClockUpdatedSecondsPayload
|
|
218
|
+
| CountdownBeginPayload
|
|
219
|
+
| CrossbarHitPayload
|
|
220
|
+
| GoalReplayEndPayload
|
|
221
|
+
| GoalReplayStartPayload
|
|
222
|
+
| GoalReplayWillEndPayload
|
|
223
|
+
| GoalScoredPayload
|
|
224
|
+
| MatchCreatedPayload
|
|
225
|
+
| MatchInitializedPayload
|
|
226
|
+
| MatchDestroyedPayload
|
|
227
|
+
| MatchEndedPayload
|
|
228
|
+
| MatchPausedPayload
|
|
229
|
+
| MatchUnpausedPayload
|
|
230
|
+
| PodiumStartPayload
|
|
231
|
+
| ReplayCreatedPayload
|
|
232
|
+
| RoundStartedPayload
|
|
233
|
+
| StatfeedEventPayload
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
KnownEventPayloadMap: TypeAlias = dict[EventName, KnownEventPayload]
|
|
237
|
+
|
|
238
|
+
TData = TypeVar("TData", bound=Mapping[str, Any])
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
@dataclass(slots=True)
|
|
242
|
+
class TypedEventMessage(Generic[TData]):
|
|
243
|
+
event: str
|
|
244
|
+
data: TData
|
|
245
|
+
raw: str | None = None
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
KnownEventMessage: TypeAlias = TypedEventMessage[KnownEventPayload]
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
@overload
|
|
252
|
+
def cast_event_data(
|
|
253
|
+
event_name: Literal["UpdateState"], data: Mapping[str, Any]
|
|
254
|
+
) -> UpdateStatePayload: ...
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
@overload
|
|
258
|
+
def cast_event_data(
|
|
259
|
+
event_name: Literal["BallHit"], data: Mapping[str, Any]
|
|
260
|
+
) -> BallHitPayload: ...
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@overload
|
|
264
|
+
def cast_event_data(
|
|
265
|
+
event_name: Literal["ClockUpdatedSeconds"], data: Mapping[str, Any]
|
|
266
|
+
) -> ClockUpdatedSecondsPayload: ...
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
@overload
|
|
270
|
+
def cast_event_data(
|
|
271
|
+
event_name: Literal["CountdownBegin"], data: Mapping[str, Any]
|
|
272
|
+
) -> CountdownBeginPayload: ...
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@overload
|
|
276
|
+
def cast_event_data(
|
|
277
|
+
event_name: Literal["CrossbarHit"], data: Mapping[str, Any]
|
|
278
|
+
) -> CrossbarHitPayload: ...
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@overload
|
|
282
|
+
def cast_event_data(
|
|
283
|
+
event_name: Literal["GoalReplayEnd"], data: Mapping[str, Any]
|
|
284
|
+
) -> GoalReplayEndPayload: ...
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@overload
|
|
288
|
+
def cast_event_data(
|
|
289
|
+
event_name: Literal["GoalReplayStart"], data: Mapping[str, Any]
|
|
290
|
+
) -> GoalReplayStartPayload: ...
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
@overload
|
|
294
|
+
def cast_event_data(
|
|
295
|
+
event_name: Literal["GoalReplayWillEnd"], data: Mapping[str, Any]
|
|
296
|
+
) -> GoalReplayWillEndPayload: ...
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
@overload
|
|
300
|
+
def cast_event_data(
|
|
301
|
+
event_name: Literal["GoalScored"], data: Mapping[str, Any]
|
|
302
|
+
) -> GoalScoredPayload: ...
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
@overload
|
|
306
|
+
def cast_event_data(
|
|
307
|
+
event_name: Literal["MatchCreated"], data: Mapping[str, Any]
|
|
308
|
+
) -> MatchCreatedPayload: ...
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
@overload
|
|
312
|
+
def cast_event_data(
|
|
313
|
+
event_name: Literal["MatchInitialized"], data: Mapping[str, Any]
|
|
314
|
+
) -> MatchInitializedPayload: ...
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@overload
|
|
318
|
+
def cast_event_data(
|
|
319
|
+
event_name: Literal["MatchDestroyed"], data: Mapping[str, Any]
|
|
320
|
+
) -> MatchDestroyedPayload: ...
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@overload
|
|
324
|
+
def cast_event_data(
|
|
325
|
+
event_name: Literal["MatchEnded"], data: Mapping[str, Any]
|
|
326
|
+
) -> MatchEndedPayload: ...
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@overload
|
|
330
|
+
def cast_event_data(
|
|
331
|
+
event_name: Literal["MatchPaused"], data: Mapping[str, Any]
|
|
332
|
+
) -> MatchPausedPayload: ...
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
@overload
|
|
336
|
+
def cast_event_data(
|
|
337
|
+
event_name: Literal["MatchUnpaused"], data: Mapping[str, Any]
|
|
338
|
+
) -> MatchUnpausedPayload: ...
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@overload
|
|
342
|
+
def cast_event_data(
|
|
343
|
+
event_name: Literal["PodiumStart"], data: Mapping[str, Any]
|
|
344
|
+
) -> PodiumStartPayload: ...
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@overload
|
|
348
|
+
def cast_event_data(
|
|
349
|
+
event_name: Literal["ReplayCreated"], data: Mapping[str, Any]
|
|
350
|
+
) -> ReplayCreatedPayload: ...
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
@overload
|
|
354
|
+
def cast_event_data(
|
|
355
|
+
event_name: Literal["RoundStarted"], data: Mapping[str, Any]
|
|
356
|
+
) -> RoundStartedPayload: ...
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@overload
|
|
360
|
+
def cast_event_data(
|
|
361
|
+
event_name: Literal["StatfeedEvent"], data: Mapping[str, Any]
|
|
362
|
+
) -> StatfeedEventPayload: ...
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
@overload
|
|
366
|
+
def cast_event_data(event_name: str, data: Mapping[str, Any]) -> Mapping[str, Any]: ...
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
def cast_event_data(event_name: str, data: Mapping[str, Any]) -> Mapping[str, Any]:
|
|
370
|
+
"""Type-only helper to narrow `data` based on event name."""
|
|
371
|
+
|
|
372
|
+
_ = event_name
|
|
373
|
+
return cast(Mapping[str, Any], data)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rlstatsapi
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: Rocket League Stats API client
|
|
5
5
|
Author: Manuel Cabral
|
|
6
6
|
License: MIT
|
|
@@ -32,7 +32,7 @@ pip install rlstatsapi
|
|
|
32
32
|
From GitHub (latest `main`):
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
pip install git+https://github.com/
|
|
35
|
+
pip install git+https://github.com/manucabral/RocketLeagueStatsAPI.git
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
## Rocket League setup
|
|
@@ -57,7 +57,6 @@ from rlstatsapi import StatsClient
|
|
|
57
57
|
|
|
58
58
|
logging.basicConfig(level=logging.INFO)
|
|
59
59
|
|
|
60
|
-
|
|
61
60
|
async def main() -> None:
|
|
62
61
|
client = StatsClient(log_enabled=True)
|
|
63
62
|
client.on_any(lambda msg: print(msg.event, msg.data))
|
|
@@ -68,17 +67,44 @@ async def main() -> None:
|
|
|
68
67
|
finally:
|
|
69
68
|
await client.disconnect()
|
|
70
69
|
|
|
70
|
+
asyncio.run(main())
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Example Event (Goals)
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
import asyncio
|
|
77
|
+
from rlstatsapi import StatsClient
|
|
78
|
+
from rlstatsapi.models import EventMessage
|
|
79
|
+
from rlstatsapi.types import GoalScoredPayload, cast_event_data
|
|
80
|
+
|
|
81
|
+
async def on_goal(msg: EventMessage) -> None:
|
|
82
|
+
data: GoalScoredPayload = cast_event_data("GoalScored", msg.data)
|
|
83
|
+
scorer = data.get("Scorer", {})
|
|
84
|
+
print("Goal by:", scorer.get("Name"))
|
|
85
|
+
|
|
86
|
+
async def main() -> None:
|
|
87
|
+
client = StatsClient()
|
|
88
|
+
client.on("GoalScored", on_goal)
|
|
89
|
+
await client.connect()
|
|
90
|
+
try:
|
|
91
|
+
await asyncio.Event().wait()
|
|
92
|
+
finally:
|
|
93
|
+
await client.disconnect()
|
|
71
94
|
|
|
72
95
|
asyncio.run(main())
|
|
73
96
|
```
|
|
74
97
|
|
|
98
|
+
|
|
75
99
|
## Public API
|
|
76
100
|
|
|
77
|
-
- `StatsClient(
|
|
101
|
+
- `StatsClient(...)`
|
|
78
102
|
- `connect()` / `disconnect()`
|
|
79
103
|
- `on(event_name, handler)`
|
|
80
104
|
- `on_any(handler)`
|
|
81
105
|
- `events()`
|
|
106
|
+
- typed helpers: `EventName`, `TypedEventMessage[...]`, `cast_event_data(...)`
|
|
107
|
+
|
|
82
108
|
|
|
83
109
|
## Notes
|
|
84
110
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|