Skip to content

Commit 521e913

Browse files
committed
Add support for individual participant event endpoint
1 parent 25fdd67 commit 521e913

9 files changed

+94
-6
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Python MCC API
22

33
[![🐍 PyPI](https://img.shields.io/pypi/v/mcc-api?label=🐍%20PyPI)](https://pypi.org/project/mcc-api/)
4-
[![👑 Targeting Event API v1.4.0](https://img.shields.io/badge/👑_Targeting_Event_API-v1.4.0-red)](https://github.com/Noxcrew/mcchampionship-api/releases/tag/v1.4.0)
4+
[![👑 Targeting Event API v1.5.0](https://img.shields.io/badge/👑_Targeting_Event_API-v1.5.0-red)](https://github.com/Noxcrew/mcchampionship-api/releases/tag/v1.5.0)
55
[![🏝️ Targeting Island API v24.05.06](https://img.shields.io/badge/🏝️_Targeting_Island_API-v24.05.06-aqua)](https://github.com/Noxcrew/mccisland-api/releases/tag/v24.05.06)
66

77
A helper library for the [MC Championship](https://mcchampionship.com) APIs

docs/index.rst

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ python_mcc_api
44
.. image:: https://img.shields.io/pypi/v/mcc-api?label=🐍%20PyPI
55
:alt: 🐍 PyPI
66
:target: https://pypi.org/project/mcc-api/
7-
.. image:: https://img.shields.io/badge/👑_Targeting_Event_API-v1.4.0-red
8-
:alt: 👑 Targeting Event API v1.4.0
9-
:target: https://github.com/Noxcrew/mcchampionship-api/releases/tag/v1.4.0
7+
.. image:: https://img.shields.io/badge/👑_Targeting_Event_API-v1.5.0-red
8+
:alt: 👑 Targeting Event API v1.5.0
9+
:target: https://github.com/Noxcrew/mcchampionship-api/releases/tag/v1.5.0
1010
.. image:: https://img.shields.io/badge/🏝️_Targeting_Island_API-v24.05.06-aqua
1111
:alt: 🏝️ Targeting Island API v24.05.06
1212
:target: https://github.com/Noxcrew/mccisland-api/releases/tag/v24.05.06

mcc_api/__init__.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
"__version__"
55
]
66

7-
__version__ = "1.1.4"
7+
__version__ = "1.1.5"
88
__user_agent: t.Final[str] = f"python_mcc_api/{__version__} (https://github.com/JamesMCo/python_mcc_api)"
9+
10+
# update version of package
11+
# update targeted api version

mcc_api/event/__init__.py

+15
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
EventsResponse,
99
HallOfFameGameResponse,
1010
HallOfFameResponse,
11+
ParticipantResponse,
1112
ParticipantsResponse,
1213
ParticipantsTeamResponse,
1314
RundownResponse
@@ -129,6 +130,20 @@ def get_rundown(event: t.Optional[str] = None, *, timeout: int = 5) -> RundownRe
129130
return RundownResponse(__request("rundown", timeout))
130131

131132

133+
def get_participant(uuid: str, *, timeout: int = 5) -> ParticipantResponse:
134+
"""Get an individual participant in the current event cycle by their Minecraft UUID.
135+
136+
- Accepts both dashed (e.g. 3e7a89ee-c4e2-4392-a317-444b861b0794) and un-dashed
137+
(e.g. 3e7a89eec4e24392a317444b861b0794) UUIDs
138+
- Calls the `/participant <https://api.mcchampionship.com/docs/#/v1/AppController_getParticipant>`_ endpoint.
139+
- Returns an :class:`mcc_api.ParticipantResponse` representing the individual participant in the current event
140+
cycle's event.
141+
- May raise a :class:`requests.Timeout` exception, with the number of seconds before timing out specified by the
142+
`timeout` parameter and defaulting to 5.
143+
"""
144+
return ParticipantResponse(__request(f"participant/{uuid}", timeout))
145+
146+
132147
@t.overload
133148
def get_participants(*, timeout: int = 5) -> ParticipantsResponse: ...
134149
@t.overload

mcc_api/event/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class InvalidGameError(MCCAPIError):
2626
pass
2727

2828

29+
class InvalidParticipantError(MCCAPIError):
30+
"""Exception raised when the requested participant does not exist."""
31+
pass
32+
2933
class InvalidTeamError(MCCAPIError):
3034
"""Exception raised when the requested team does not exist."""
3135
pass

mcc_api/event/responses.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .exceptions import InvalidEventError, InvalidGameError, InvalidTeamError, RateLimitError
1+
from .exceptions import InvalidEventError, InvalidGameError, InvalidParticipantError, InvalidTeamError, RateLimitError
22
from .enums import Game, Team
33
from dataclasses import dataclass
44
from datetime import datetime
@@ -323,6 +323,27 @@ class Creator:
323323
"""The team of the participant."""
324324

325325

326+
class ParticipantResponse(BaseResponse):
327+
"""Response object representing an individual participant in the current event cycle."""
328+
329+
data: Creator
330+
331+
def __init__(self: "ParticipantResponse", request: requests.Response | dict[str, t.Any]) -> None:
332+
data: dict[str, t.Any] = super()._extract_json_data(request)
333+
super().__init__(data)
334+
335+
if self.code == 404:
336+
raise InvalidParticipantError(self.code, self.reason)
337+
338+
self.data = Creator(
339+
username=data["data"]["username"],
340+
uuid=data["data"]["uuid"],
341+
stream=data["data"]["stream"],
342+
icon=data["data"]["icon"],
343+
team=Team(data["data"]["team"])
344+
)
345+
346+
326347
class ParticipantsResponse(BaseResponse):
327348
"""Response object representing all teams and their participants in the current event cycle."""
328349

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"code": 200,
3+
"data":
4+
{
5+
"username": "Noxite",
6+
"uuid": "3e7a89eec4e24392a317444b861b0794",
7+
"stream": "https://twitch.tv/thenoxcrew",
8+
"icon": "https://static-cdn.jtvnw.net/jtv_user_pictures/a5ba63c7-923b-460c-87b0-1917e7a95ab9-profile_image-50x50.png?u=1",
9+
"team": "SPECTATORS"
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"status": 404,
3+
"reason": "Not Found - Participant not found"
4+
}

tests/event/test_participants.py

+30
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,36 @@
44
import unittest
55

66

7+
class TestEventParticipant200(unittest.TestCase):
8+
response_json: dict[str, t.Any]
9+
response_object: event_api.ParticipantResponse
10+
11+
def setUp(self: "TestEventParticipant200") -> None:
12+
with open("event/mock_data/200_participant.json") as f:
13+
f: t.TextIO
14+
self.response_json = json.loads(f.read())
15+
self.response_object = event_api.ParticipantResponse(self.response_json)
16+
17+
def test_creator_returned(self: "TestEventParticipant200") -> None:
18+
self.assertIsInstance(self.response_object.data, event_api.responses.Creator)
19+
20+
21+
class TestParticipantEndpoint404(unittest.TestCase):
22+
def test_participant_invalid_team_exception(self: "TestParticipantEndpoint404") -> None:
23+
with open("event/mock_data/404_participant.json") as f:
24+
f: t.TextIO
25+
response_json: dict[str, t.Any] = json.loads(f.read())
26+
self.assertRaises(event_api.exceptions.InvalidParticipantError, event_api.ParticipantResponse, response_json)
27+
28+
29+
class TestParticipantEndpoint429(unittest.TestCase):
30+
def test_participant_ratelimit_exception(self: "TestParticipantEndpoint429") -> None:
31+
with open("event/mock_data/429_ratelimit.json") as f:
32+
f: t.TextIO
33+
response_json: dict[str, t.Any] = json.loads(f.read())
34+
self.assertRaises(event_api.exceptions.RateLimitError, event_api.ParticipantResponse, response_json)
35+
36+
737
class TestEventParticipants200(unittest.TestCase):
838
response_json: dict[str, t.Any]
939
response_object: event_api.ParticipantsResponse

0 commit comments

Comments
 (0)