Skip to content

services

This module contains the services used to interact with different portions of the WOM API.

BaseService

Bases: ABC

The base service all API services inherit from.

Parameters:

Name Type Description Default
http_service HttpService

The http service to use for requests.

required
serializer Serializer

The serializer to use for handling incoming JSON data from the API.

required
Source code in wom/services/base.py
class BaseService(abc.ABC):
    """The base service all API services inherit from.

    Parameters
    ----------
    http_service : HttpService
        The http service to use for requests.
    serializer : Serializer
        The serializer to use for handling incoming
        JSON data from the API.
    """

    __slots__ = ("_http", "_serializer")

    def __init__(self, http_service: HttpService, serializer: serializer.Serializer) -> None:
        self._http = http_service
        self._serializer = serializer

    def _generate_map(self, **kwargs: t.Any) -> t.Dict[str, t.Any]:
        return {k: v for k, v in kwargs.items() if v is not None}

    def _ok(self, data: bytes, model_type: t.Type[T]) -> ResultT[T]:
        return result.Ok(self._serializer.decode(data, model_type))

    def _ok_or_err(
        self, data: t.Union[bytes, models.HttpErrorResponse], model_type: t.Type[T]
    ) -> ResultT[T]:
        if isinstance(data, models.HttpErrorResponse):
            return result.Err(data)

        return self._ok(data, model_type)

    def _success_or_err(
        self,
        data: t.Union[bytes, models.HttpErrorResponse],
        *,
        predicate: t.Optional[t.Callable[[str], bool]] = None,
    ) -> ResultT[models.HttpSuccessResponse]:
        if isinstance(data, bytes):
            err = self._serializer.decode(data, models.HttpErrorResponse)
            return result.Err(err)

        predicate = predicate or (lambda m: m.startswith("Success"))

        if not predicate(data.message):
            return result.Err(data)

        return result.Ok(models.HttpSuccessResponse(data.message, data.status))

CompetitionService

Bases: BaseService

Handles endpoints related to competitions.

Source code in wom/services/competitions.py
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
class CompetitionService(BaseService):
    """Handles endpoints related to competitions."""

    __slots__ = ()

    async def search_competitions(
        self,
        *,
        title: t.Optional[str] = None,
        type: t.Optional[models.CompetitionType] = None,
        status: t.Optional[models.CompetitionStatus] = None,
        metric: t.Optional[enums.Metric] = None,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.Competition]]:
        """Searches for competitions with the given criteria.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.search_competitions(
                title="Sick Competition",
                type=wom.CompetitionType.Classic,
                status=wom.CompetitionStatus.Ongoing,
                limit=3,
                offset=1
            )
            ```

        Parameters
        ----------
        title : str, optional
            The optional title of the competition. Defaults to
            `None`.
        type : CompetitionType, optional
            The optional competition type filter. Defaults to `None`
        status : CompetitionStatus, optional
            The optional competition status filter. Defaults to `None`.
        metric : Metric, optional
            The optional metric filter. Defaults to `None`.
        limit : int, optional
            The maximum number of paginated items to receive.
            Defaults to `None` (I think thats 20 items?).
        offset : int, optional
            The page offset for requesting multiple pages.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of competitions
            or an error.
        """
        params = self._generate_map(
            title=title,
            limit=limit,
            offset=offset,
            type=type.value if type else None,
            status=status.value if status else None,
            metric=metric.value if metric else None,
        )

        route = routes.SEARCH_COMPETITIONS.compile().with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Competition])

    async def get_details(
        self, id: int, *, metric: t.Optional[enums.Metric] = None
    ) -> ResultT[models.CompetitionDetail]:
        """Gets details for the given competition.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.get_details(123)

            result2 = await client.competitions.get_details(
                123, wom.Metric.Attack
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        metric : Metric, optional
            The optional metric to view the competition progress in.
            As if this competition was actually for that metric.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the competition details.
        """
        params = self._generate_map(metric=metric.value if metric else None)
        route = routes.COMPETITION_DETAILS.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.CompetitionDetail)

    async def get_top_participant_history(
        self, id: int, *, metric: t.Optional[enums.Metric] = None
    ) -> ResultT[t.List[models.Top5ProgressResult]]:
        """Gets details for the players with the top 5 progress in the
        competition.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            result = await client.competitions.get_competition_details(123)

            result2 = await client.competitions.get_competition_details(
                123, wom.Metric.Attack
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        metric : Metric, optional
            The optional metric to view the competition progress in.
            As if this competition was actually for that metric.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of top 5
            progress players.
        """
        params = self._generate_map(metric=metric.value if metric else None)
        route = routes.TOP_PARTICIPANT_HISTORY.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Top5ProgressResult])

    async def create_competition(
        self,
        title: str,
        metric: enums.Metric,
        starts_at: datetime,
        ends_at: datetime,
        *,
        group_id: t.Optional[int] = None,
        group_verification_code: t.Optional[str] = None,
        teams: t.Optional[t.List[models.Team]] = None,
        participants: t.Optional[t.List[str]] = None,
    ) -> ResultT[models.CreatedCompetitionDetail]:
        """Creates a new competition.

        !!! info

            The `group_id`, `participants`, and `teams` parameters are
            mutually exclusive.

            - If `group_id` is provided, this method will create a
                classic competition with all members of that group as
                participants.

            - If `participants` is provided and `group_id` isn't, this
                method will create a classic competition with all those
                participants included.

            - If `teams` is provided, this endpoint will create a team
                competition with all those participants included.
                Also accepts `group_id` as a way to link this
                competition to the group.

        ??? example

            ```py
            from datetime import datetime, timedelta
            import wom

            client = wom.Client(...)

            result = await client.competitions.create_competition(
                "Slayer week",
                wom.Metric.Slayer,
                starts_at=datetime.now() + timedelta(days=7),
                ends_at=datetime.now() + timedelta(days=14),
                group_verification_code="111-111-111",
                group_id=123,
            )
            ```

        Parameters
        ----------
        title : str
            The title of the competition.
        metric : Metric
            The metric the competition should measure.
        starts_at : datetime
            The start date for the competition.
        ends_at : datetime
            The end date for the competition.
        group_id : int, optional
            The optional group id to tie to this competition.
            Defaults to `None`.
        group_verification_code : str, optional
            The optional group verification
            code. Required if group_id is supplied. Defaults to
            `None`.
        participants : list[str], optional
            The optional list of participants to include
            in the competition. Defaults to `None`.
        teams : list[Team], optional
            The optional teams to include in the competition.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the newly created
            competition detail.
        """
        payload = self._generate_map(
            title=title,
            teams=teams,
            groupId=group_id,
            participants=participants,
            endsAt=ends_at.isoformat(),
            startsAt=starts_at.isoformat(),
            metric=metric.value if metric else None,
            groupVerificationCode=group_verification_code,
        )

        route = routes.CREATE_COMPETITION.compile()
        data = await self._http.fetch(route, payload=payload)
        return self._ok_or_err(data, models.CreatedCompetitionDetail)

    async def edit_competition(
        self,
        id: int,
        verification_code: str,
        *,
        title: t.Optional[str] = None,
        metric: t.Optional[enums.Metric] = None,
        starts_at: t.Optional[datetime] = None,
        ends_at: t.Optional[datetime] = None,
        teams: t.Optional[t.List[models.Team]] = None,
        participants: t.Optional[t.List[str]] = None,
    ) -> ResultT[models.Competition]:
        """Edits an existing competition.

        !!! warning

            The teams/participants parameters will completely
            overwrite the existing participants/teams. If you're looking
            to add users, check out [`add_participants()`]
            [wom.CompetitionService.add_participants].

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.edit_competition(
                123, "111-111-111", title="New title"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.
        title : str, optional
            The optional updated title of the competition.
            Defaults to `None`.
        metric : Metric, optional
            The optional new metric the competition should measure.
            Defaults to `None`.
        starts_at : datetime, optional
            The optional new start date for the competition.
            Defaults to `None`.
        ends_at : datetime, optional
            The optional new end date for the competition.
            Defaults to `None`.
        participants : list[str], optional
            The optional list of participants to replace
            the existing participants with. Defaults to `None`.
        teams : list[Team], optional
            The optional list of teams to replace the existing
            participants with. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the edited competition
            with participations.
        """
        payload = self._generate_map(
            title=title,
            teams=teams,
            participants=participants,
            startsAt=starts_at.isoformat() if starts_at else None,
            endsAt=ends_at.isoformat() if ends_at else None,
            metric=metric.value if metric else None,
            verificationCode=verification_code,
        )

        route = routes.EDIT_COMPETITION.compile(id)
        data = await self._http.fetch(route, payload=payload)
        return self._ok_or_err(data, models.Competition)

    async def delete_competition(
        self, id: int, verification_code: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Deletes a competition.

        !!! warning

            This action can not be reversed.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.delete_competition(
                123, "111-111-111"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.DELETE_COMPETITION.compile(id)
        payload = self._generate_map(verificationCode=verification_code)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def add_participants(
        self, id: int, verification_code: str, *participants: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Adds participants to a competition. Only adds valid
        participants, and ignores duplicates.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.add_participants(
                123, "111-111-111", "Jonxslays", "Zezima"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.
        *participants : str
            The participants you would like to add.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.ADD_PARTICIPANTS.compile(id)
        payload = self._generate_map(verificationCode=verification_code, participants=participants)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def remove_participants(
        self, id: int, verification_code: str, *participants: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Removes participants from a competition. Ignores usernames
        that are not competing.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.remove_participants(
                123, "111-111-111", "Jonxslays"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.
        *participants : str
            The participants you would like to remove.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.REMOVE_PARTICIPANTS.compile(id)
        payload = self._generate_map(verificationCode=verification_code, participants=participants)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def add_teams(
        self, id: int, verification_code: str, *teams: models.Team
    ) -> ResultT[models.HttpSuccessResponse]:
        """Adds teams to a competition. Ignores duplicates.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.add_teams(
                123,
                "111-111-111",
                wom.Team("Team 1", ["Jonxslays", "lilyuffie88"]),
                wom.Team("Team 2", ["Zezima", "the old nite"]),
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.
        *teams : Team
            The teams you would like to add.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.ADD_TEAMS.compile(id)
        payload = self._generate_map(verificationCode=verification_code, teams=teams)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def remove_teams(
        self, id: int, verification_code: str, *teams: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Removes teams from a competition. Ignores teams that don't
        exist.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.remove_teams(
                123, "111-111-111", "Team 1", "Team 2"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.
        *teams : str
            The team names you would like to remove.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.REMOVE_TEAMS.compile(id)
        payload = self._generate_map(verificationCode=verification_code, teamNames=teams)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def update_outdated_participants(
        self, id: int, verification_code: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Attempts to update all outdated competition participants.

        !!! info

            Participants are outdated when either:

            - Competition is ending or started within 6h of now and
                the player hasn't been updated in over 1h.

            - Player hasn't been updated in over 24h.

        !!! warning

            This method adds every outdated participant to an
            "update queue", and the WOM servers try to update players
            in the queue one by one, with a delay in between each. For
            each player in the queue, an attempt is made to update it
            up to 3 times, with 30s in between each attempt.

            Please note that this is dependent on the OSRS hiscores
            functioning correctly, and therefore this method does NOT
            guarantee the players will be updated, it only guarantees
            that an attempt will be made to update them, up to 3 times.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.update_outdated_participants(
                123, "111-111-111"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        verification_code : str
            The verification code for the
            competition.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.UPDATE_OUTDATED_PARTICIPANTS.compile(id)
        payload = self._generate_map(verificationCode=verification_code)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data, predicate=lambda m: "players are being updated" in m)

    async def get_details_csv(
        self,
        id: int,
        *,
        metric: t.Optional[enums.Metric] = None,
        team_name: t.Optional[str] = None,
        table_type: t.Optional[models.CompetitionCSVTableType] = None,
    ) -> ResultT[str]:
        """Gets details about the competition in CSV format.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.competitions.get_details_csv(
                123, team_name="Cool team"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the competition.
        metric : Metric, optional
            The optional metric to view the competition progress in.
            As if this competition was actually for that metric.
            Defaults to `None`.
        team_name : str, optional
            The optional team name you would like to get details
            for. Defaults to `None`.
        table_type : CompetitionCSVTableType, optional
            The optional table type formatting to apply.
            Defaults to `Participants`.

        Returns
        -------
        Result
            A result containing the CSV string.
        """
        params = self._generate_map(metric=metric, teamName=team_name, table=table_type)
        route = routes.COMPETITION_DETAILS_CSV.compile(id).with_params(params)
        data = await self._http.fetch(route)

        if isinstance(data, models.HttpErrorResponse):
            return result.Err(data)

        return result.Ok(data.decode())

add_participants async

add_participants(
    id: int, verification_code: str, *participants: str
) -> ResultT[models.HttpSuccessResponse]

Adds participants to a competition. Only adds valid participants, and ignores duplicates.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.add_participants(
    123, "111-111-111", "Jonxslays", "Zezima"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required
*participants str

The participants you would like to add.

()

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/competitions.py
async def add_participants(
    self, id: int, verification_code: str, *participants: str
) -> ResultT[models.HttpSuccessResponse]:
    """Adds participants to a competition. Only adds valid
    participants, and ignores duplicates.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.add_participants(
            123, "111-111-111", "Jonxslays", "Zezima"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.
    *participants : str
        The participants you would like to add.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.ADD_PARTICIPANTS.compile(id)
    payload = self._generate_map(verificationCode=verification_code, participants=participants)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

add_teams async

add_teams(
    id: int, verification_code: str, *teams: models.Team
) -> ResultT[models.HttpSuccessResponse]

Adds teams to a competition. Ignores duplicates.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.add_teams(
    123,
    "111-111-111",
    wom.Team("Team 1", ["Jonxslays", "lilyuffie88"]),
    wom.Team("Team 2", ["Zezima", "the old nite"]),
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required
*teams Team

The teams you would like to add.

()

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/competitions.py
async def add_teams(
    self, id: int, verification_code: str, *teams: models.Team
) -> ResultT[models.HttpSuccessResponse]:
    """Adds teams to a competition. Ignores duplicates.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.add_teams(
            123,
            "111-111-111",
            wom.Team("Team 1", ["Jonxslays", "lilyuffie88"]),
            wom.Team("Team 2", ["Zezima", "the old nite"]),
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.
    *teams : Team
        The teams you would like to add.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.ADD_TEAMS.compile(id)
    payload = self._generate_map(verificationCode=verification_code, teams=teams)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

create_competition async

create_competition(
    title: str,
    metric: enums.Metric,
    starts_at: datetime,
    ends_at: datetime,
    *,
    group_id: t.Optional[int] = None,
    group_verification_code: t.Optional[str] = None,
    teams: t.Optional[t.List[models.Team]] = None,
    participants: t.Optional[t.List[str]] = None
) -> ResultT[models.CreatedCompetitionDetail]

Creates a new competition.

Info

The group_id, participants, and teams parameters are mutually exclusive.

  • If group_id is provided, this method will create a classic competition with all members of that group as participants.

  • If participants is provided and group_id isn't, this method will create a classic competition with all those participants included.

  • If teams is provided, this endpoint will create a team competition with all those participants included. Also accepts group_id as a way to link this competition to the group.

Example
from datetime import datetime, timedelta
import wom

client = wom.Client(...)

result = await client.competitions.create_competition(
    "Slayer week",
    wom.Metric.Slayer,
    starts_at=datetime.now() + timedelta(days=7),
    ends_at=datetime.now() + timedelta(days=14),
    group_verification_code="111-111-111",
    group_id=123,
)

Parameters:

Name Type Description Default
title str

The title of the competition.

required
metric Metric

The metric the competition should measure.

required
starts_at datetime

The start date for the competition.

required
ends_at datetime

The end date for the competition.

required
group_id int

The optional group id to tie to this competition. Defaults to None.

None
group_verification_code str

The optional group verification code. Required if group_id is supplied. Defaults to None.

None
participants list[str]

The optional list of participants to include in the competition. Defaults to None.

None
teams list[Team]

The optional teams to include in the competition. Defaults to None.

None

Returns:

Type Description
Result

A result containing the newly created competition detail.

Source code in wom/services/competitions.py
async def create_competition(
    self,
    title: str,
    metric: enums.Metric,
    starts_at: datetime,
    ends_at: datetime,
    *,
    group_id: t.Optional[int] = None,
    group_verification_code: t.Optional[str] = None,
    teams: t.Optional[t.List[models.Team]] = None,
    participants: t.Optional[t.List[str]] = None,
) -> ResultT[models.CreatedCompetitionDetail]:
    """Creates a new competition.

    !!! info

        The `group_id`, `participants`, and `teams` parameters are
        mutually exclusive.

        - If `group_id` is provided, this method will create a
            classic competition with all members of that group as
            participants.

        - If `participants` is provided and `group_id` isn't, this
            method will create a classic competition with all those
            participants included.

        - If `teams` is provided, this endpoint will create a team
            competition with all those participants included.
            Also accepts `group_id` as a way to link this
            competition to the group.

    ??? example

        ```py
        from datetime import datetime, timedelta
        import wom

        client = wom.Client(...)

        result = await client.competitions.create_competition(
            "Slayer week",
            wom.Metric.Slayer,
            starts_at=datetime.now() + timedelta(days=7),
            ends_at=datetime.now() + timedelta(days=14),
            group_verification_code="111-111-111",
            group_id=123,
        )
        ```

    Parameters
    ----------
    title : str
        The title of the competition.
    metric : Metric
        The metric the competition should measure.
    starts_at : datetime
        The start date for the competition.
    ends_at : datetime
        The end date for the competition.
    group_id : int, optional
        The optional group id to tie to this competition.
        Defaults to `None`.
    group_verification_code : str, optional
        The optional group verification
        code. Required if group_id is supplied. Defaults to
        `None`.
    participants : list[str], optional
        The optional list of participants to include
        in the competition. Defaults to `None`.
    teams : list[Team], optional
        The optional teams to include in the competition.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the newly created
        competition detail.
    """
    payload = self._generate_map(
        title=title,
        teams=teams,
        groupId=group_id,
        participants=participants,
        endsAt=ends_at.isoformat(),
        startsAt=starts_at.isoformat(),
        metric=metric.value if metric else None,
        groupVerificationCode=group_verification_code,
    )

    route = routes.CREATE_COMPETITION.compile()
    data = await self._http.fetch(route, payload=payload)
    return self._ok_or_err(data, models.CreatedCompetitionDetail)

delete_competition async

delete_competition(
    id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]

Deletes a competition.

Warning

This action can not be reversed.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.delete_competition(
    123, "111-111-111"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/competitions.py
async def delete_competition(
    self, id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]:
    """Deletes a competition.

    !!! warning

        This action can not be reversed.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.delete_competition(
            123, "111-111-111"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.DELETE_COMPETITION.compile(id)
    payload = self._generate_map(verificationCode=verification_code)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

edit_competition async

edit_competition(
    id: int,
    verification_code: str,
    *,
    title: t.Optional[str] = None,
    metric: t.Optional[enums.Metric] = None,
    starts_at: t.Optional[datetime] = None,
    ends_at: t.Optional[datetime] = None,
    teams: t.Optional[t.List[models.Team]] = None,
    participants: t.Optional[t.List[str]] = None
) -> ResultT[models.Competition]

Edits an existing competition.

Warning

The teams/participants parameters will completely overwrite the existing participants/teams. If you're looking to add users, check out add_participants().

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.edit_competition(
    123, "111-111-111", title="New title"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required
title str

The optional updated title of the competition. Defaults to None.

None
metric Metric

The optional new metric the competition should measure. Defaults to None.

None
starts_at datetime

The optional new start date for the competition. Defaults to None.

None
ends_at datetime

The optional new end date for the competition. Defaults to None.

None
participants list[str]

The optional list of participants to replace the existing participants with. Defaults to None.

None
teams list[Team]

The optional list of teams to replace the existing participants with. Defaults to None.

None

Returns:

Type Description
Result

A result containing the edited competition with participations.

Source code in wom/services/competitions.py
async def edit_competition(
    self,
    id: int,
    verification_code: str,
    *,
    title: t.Optional[str] = None,
    metric: t.Optional[enums.Metric] = None,
    starts_at: t.Optional[datetime] = None,
    ends_at: t.Optional[datetime] = None,
    teams: t.Optional[t.List[models.Team]] = None,
    participants: t.Optional[t.List[str]] = None,
) -> ResultT[models.Competition]:
    """Edits an existing competition.

    !!! warning

        The teams/participants parameters will completely
        overwrite the existing participants/teams. If you're looking
        to add users, check out [`add_participants()`]
        [wom.CompetitionService.add_participants].

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.edit_competition(
            123, "111-111-111", title="New title"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.
    title : str, optional
        The optional updated title of the competition.
        Defaults to `None`.
    metric : Metric, optional
        The optional new metric the competition should measure.
        Defaults to `None`.
    starts_at : datetime, optional
        The optional new start date for the competition.
        Defaults to `None`.
    ends_at : datetime, optional
        The optional new end date for the competition.
        Defaults to `None`.
    participants : list[str], optional
        The optional list of participants to replace
        the existing participants with. Defaults to `None`.
    teams : list[Team], optional
        The optional list of teams to replace the existing
        participants with. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the edited competition
        with participations.
    """
    payload = self._generate_map(
        title=title,
        teams=teams,
        participants=participants,
        startsAt=starts_at.isoformat() if starts_at else None,
        endsAt=ends_at.isoformat() if ends_at else None,
        metric=metric.value if metric else None,
        verificationCode=verification_code,
    )

    route = routes.EDIT_COMPETITION.compile(id)
    data = await self._http.fetch(route, payload=payload)
    return self._ok_or_err(data, models.Competition)

get_details async

get_details(
    id: int, *, metric: t.Optional[enums.Metric] = None
) -> ResultT[models.CompetitionDetail]

Gets details for the given competition.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.get_details(123)

result2 = await client.competitions.get_details(
    123, wom.Metric.Attack
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
metric Metric

The optional metric to view the competition progress in. As if this competition was actually for that metric. Defaults to None.

None

Returns:

Type Description
Result

A result containing the competition details.

Source code in wom/services/competitions.py
async def get_details(
    self, id: int, *, metric: t.Optional[enums.Metric] = None
) -> ResultT[models.CompetitionDetail]:
    """Gets details for the given competition.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.get_details(123)

        result2 = await client.competitions.get_details(
            123, wom.Metric.Attack
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    metric : Metric, optional
        The optional metric to view the competition progress in.
        As if this competition was actually for that metric.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the competition details.
    """
    params = self._generate_map(metric=metric.value if metric else None)
    route = routes.COMPETITION_DETAILS.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.CompetitionDetail)

get_details_csv async

get_details_csv(
    id: int,
    *,
    metric: t.Optional[enums.Metric] = None,
    team_name: t.Optional[str] = None,
    table_type: t.Optional[
        models.CompetitionCSVTableType
    ] = None
) -> ResultT[str]

Gets details about the competition in CSV format.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.get_details_csv(
    123, team_name="Cool team"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
metric Metric

The optional metric to view the competition progress in. As if this competition was actually for that metric. Defaults to None.

None
team_name str

The optional team name you would like to get details for. Defaults to None.

None
table_type CompetitionCSVTableType

The optional table type formatting to apply. Defaults to Participants.

None

Returns:

Type Description
Result

A result containing the CSV string.

Source code in wom/services/competitions.py
async def get_details_csv(
    self,
    id: int,
    *,
    metric: t.Optional[enums.Metric] = None,
    team_name: t.Optional[str] = None,
    table_type: t.Optional[models.CompetitionCSVTableType] = None,
) -> ResultT[str]:
    """Gets details about the competition in CSV format.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.get_details_csv(
            123, team_name="Cool team"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    metric : Metric, optional
        The optional metric to view the competition progress in.
        As if this competition was actually for that metric.
        Defaults to `None`.
    team_name : str, optional
        The optional team name you would like to get details
        for. Defaults to `None`.
    table_type : CompetitionCSVTableType, optional
        The optional table type formatting to apply.
        Defaults to `Participants`.

    Returns
    -------
    Result
        A result containing the CSV string.
    """
    params = self._generate_map(metric=metric, teamName=team_name, table=table_type)
    route = routes.COMPETITION_DETAILS_CSV.compile(id).with_params(params)
    data = await self._http.fetch(route)

    if isinstance(data, models.HttpErrorResponse):
        return result.Err(data)

    return result.Ok(data.decode())

get_top_participant_history async

get_top_participant_history(
    id: int, *, metric: t.Optional[enums.Metric] = None
) -> ResultT[t.List[models.Top5ProgressResult]]

Gets details for the players with the top 5 progress in the competition.

Example
import wom

client = wom.Client(...)

result = await client.competitions.get_competition_details(123)

result2 = await client.competitions.get_competition_details(
    123, wom.Metric.Attack
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
metric Metric

The optional metric to view the competition progress in. As if this competition was actually for that metric. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of top 5 progress players.

Source code in wom/services/competitions.py
async def get_top_participant_history(
    self, id: int, *, metric: t.Optional[enums.Metric] = None
) -> ResultT[t.List[models.Top5ProgressResult]]:
    """Gets details for the players with the top 5 progress in the
    competition.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        result = await client.competitions.get_competition_details(123)

        result2 = await client.competitions.get_competition_details(
            123, wom.Metric.Attack
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    metric : Metric, optional
        The optional metric to view the competition progress in.
        As if this competition was actually for that metric.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of top 5
        progress players.
    """
    params = self._generate_map(metric=metric.value if metric else None)
    route = routes.TOP_PARTICIPANT_HISTORY.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Top5ProgressResult])

remove_participants async

remove_participants(
    id: int, verification_code: str, *participants: str
) -> ResultT[models.HttpSuccessResponse]

Removes participants from a competition. Ignores usernames that are not competing.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.remove_participants(
    123, "111-111-111", "Jonxslays"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required
*participants str

The participants you would like to remove.

()

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/competitions.py
async def remove_participants(
    self, id: int, verification_code: str, *participants: str
) -> ResultT[models.HttpSuccessResponse]:
    """Removes participants from a competition. Ignores usernames
    that are not competing.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.remove_participants(
            123, "111-111-111", "Jonxslays"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.
    *participants : str
        The participants you would like to remove.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.REMOVE_PARTICIPANTS.compile(id)
    payload = self._generate_map(verificationCode=verification_code, participants=participants)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

remove_teams async

remove_teams(
    id: int, verification_code: str, *teams: str
) -> ResultT[models.HttpSuccessResponse]

Removes teams from a competition. Ignores teams that don't exist.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.remove_teams(
    123, "111-111-111", "Team 1", "Team 2"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required
*teams str

The team names you would like to remove.

()

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/competitions.py
async def remove_teams(
    self, id: int, verification_code: str, *teams: str
) -> ResultT[models.HttpSuccessResponse]:
    """Removes teams from a competition. Ignores teams that don't
    exist.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.remove_teams(
            123, "111-111-111", "Team 1", "Team 2"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.
    *teams : str
        The team names you would like to remove.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.REMOVE_TEAMS.compile(id)
    payload = self._generate_map(verificationCode=verification_code, teamNames=teams)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

search_competitions async

search_competitions(
    *,
    title: t.Optional[str] = None,
    type: t.Optional[models.CompetitionType] = None,
    status: t.Optional[models.CompetitionStatus] = None,
    metric: t.Optional[enums.Metric] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.Competition]]

Searches for competitions with the given criteria.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.search_competitions(
    title="Sick Competition",
    type=wom.CompetitionType.Classic,
    status=wom.CompetitionStatus.Ongoing,
    limit=3,
    offset=1
)

Parameters:

Name Type Description Default
title str

The optional title of the competition. Defaults to None.

None
type CompetitionType

The optional competition type filter. Defaults to None

None
status CompetitionStatus

The optional competition status filter. Defaults to None.

None
metric Metric

The optional metric filter. Defaults to None.

None
limit int

The maximum number of paginated items to receive. Defaults to None (I think thats 20 items?).

None
offset int

The page offset for requesting multiple pages. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of competitions or an error.

Source code in wom/services/competitions.py
async def search_competitions(
    self,
    *,
    title: t.Optional[str] = None,
    type: t.Optional[models.CompetitionType] = None,
    status: t.Optional[models.CompetitionStatus] = None,
    metric: t.Optional[enums.Metric] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.Competition]]:
    """Searches for competitions with the given criteria.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.search_competitions(
            title="Sick Competition",
            type=wom.CompetitionType.Classic,
            status=wom.CompetitionStatus.Ongoing,
            limit=3,
            offset=1
        )
        ```

    Parameters
    ----------
    title : str, optional
        The optional title of the competition. Defaults to
        `None`.
    type : CompetitionType, optional
        The optional competition type filter. Defaults to `None`
    status : CompetitionStatus, optional
        The optional competition status filter. Defaults to `None`.
    metric : Metric, optional
        The optional metric filter. Defaults to `None`.
    limit : int, optional
        The maximum number of paginated items to receive.
        Defaults to `None` (I think thats 20 items?).
    offset : int, optional
        The page offset for requesting multiple pages.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of competitions
        or an error.
    """
    params = self._generate_map(
        title=title,
        limit=limit,
        offset=offset,
        type=type.value if type else None,
        status=status.value if status else None,
        metric=metric.value if metric else None,
    )

    route = routes.SEARCH_COMPETITIONS.compile().with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Competition])

update_outdated_participants async

update_outdated_participants(
    id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]

Attempts to update all outdated competition participants.

Info

Participants are outdated when either:

  • Competition is ending or started within 6h of now and the player hasn't been updated in over 1h.

  • Player hasn't been updated in over 24h.

Warning

This method adds every outdated participant to an "update queue", and the WOM servers try to update players in the queue one by one, with a delay in between each. For each player in the queue, an attempt is made to update it up to 3 times, with 30s in between each attempt.

Please note that this is dependent on the OSRS hiscores functioning correctly, and therefore this method does NOT guarantee the players will be updated, it only guarantees that an attempt will be made to update them, up to 3 times.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.competitions.update_outdated_participants(
    123, "111-111-111"
)

Parameters:

Name Type Description Default
id int

The ID of the competition.

required
verification_code str

The verification code for the competition.

required

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/competitions.py
async def update_outdated_participants(
    self, id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]:
    """Attempts to update all outdated competition participants.

    !!! info

        Participants are outdated when either:

        - Competition is ending or started within 6h of now and
            the player hasn't been updated in over 1h.

        - Player hasn't been updated in over 24h.

    !!! warning

        This method adds every outdated participant to an
        "update queue", and the WOM servers try to update players
        in the queue one by one, with a delay in between each. For
        each player in the queue, an attempt is made to update it
        up to 3 times, with 30s in between each attempt.

        Please note that this is dependent on the OSRS hiscores
        functioning correctly, and therefore this method does NOT
        guarantee the players will be updated, it only guarantees
        that an attempt will be made to update them, up to 3 times.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.competitions.update_outdated_participants(
            123, "111-111-111"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the competition.
    verification_code : str
        The verification code for the
        competition.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.UPDATE_OUTDATED_PARTICIPANTS.compile(id)
    payload = self._generate_map(verificationCode=verification_code)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data, predicate=lambda m: "players are being updated" in m)

DeltaService

Bases: BaseService

Handles endpoints related to deltas.

Source code in wom/services/deltas.py
class DeltaService(BaseService):
    """Handles endpoints related to deltas."""

    __slots__ = ()

    async def get_global_leaderboards(
        self,
        metric: enums.Metric,
        period: enums.Period,
        *,
        player_type: t.Optional[models.PlayerType] = None,
        player_build: t.Optional[models.PlayerBuild] = None,
        country: t.Optional[models.Country] = None,
    ) -> ResultT[t.List[models.DeltaLeaderboardEntry]]:
        """Gets the top global delta leaderboard for a specific
        metric and period.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.deltas.get_global_leaderboards(
                wom.Metric.Attack,
                wom.Period.Day,
                country=wom.Country.Gb,
            )
            ```

        Parameters
        ----------
        metric : Metric
            The metric to filter on.
        period : Period
            The period of time to filter on.
        player_type : PlayerType, optional
            The optional player type to filter on. Defaults
            to `None`.
        player_build : PlayerBuild, optional
            The optional player build to filter on.
            Defaults to `None`.
        country : Country, optional
            The optional country to filter on. Defaults to
            `None`.

        Returns
        -------
        Result
            A result containing a list of delta
            leaderboard entries.
        """
        params = self._generate_map(
            metric=metric.value,
            period=period.value,
            playerType=player_type.value if player_type else None,
            playerBuild=player_build.value if player_build else None,
            country=country.value if country else None,
        )

        route = routes.GLOBAL_DELTA_LEADERS.compile()
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.DeltaLeaderboardEntry])

get_global_leaderboards async

get_global_leaderboards(
    metric: enums.Metric,
    period: enums.Period,
    *,
    player_type: t.Optional[models.PlayerType] = None,
    player_build: t.Optional[models.PlayerBuild] = None,
    country: t.Optional[models.Country] = None
) -> ResultT[t.List[models.DeltaLeaderboardEntry]]

Gets the top global delta leaderboard for a specific metric and period.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.deltas.get_global_leaderboards(
    wom.Metric.Attack,
    wom.Period.Day,
    country=wom.Country.Gb,
)

Parameters:

Name Type Description Default
metric Metric

The metric to filter on.

required
period Period

The period of time to filter on.

required
player_type PlayerType

The optional player type to filter on. Defaults to None.

None
player_build PlayerBuild

The optional player build to filter on. Defaults to None.

None
country Country

The optional country to filter on. Defaults to None.

None

Returns:

Type Description
Result

A result containing a list of delta leaderboard entries.

Source code in wom/services/deltas.py
async def get_global_leaderboards(
    self,
    metric: enums.Metric,
    period: enums.Period,
    *,
    player_type: t.Optional[models.PlayerType] = None,
    player_build: t.Optional[models.PlayerBuild] = None,
    country: t.Optional[models.Country] = None,
) -> ResultT[t.List[models.DeltaLeaderboardEntry]]:
    """Gets the top global delta leaderboard for a specific
    metric and period.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.deltas.get_global_leaderboards(
            wom.Metric.Attack,
            wom.Period.Day,
            country=wom.Country.Gb,
        )
        ```

    Parameters
    ----------
    metric : Metric
        The metric to filter on.
    period : Period
        The period of time to filter on.
    player_type : PlayerType, optional
        The optional player type to filter on. Defaults
        to `None`.
    player_build : PlayerBuild, optional
        The optional player build to filter on.
        Defaults to `None`.
    country : Country, optional
        The optional country to filter on. Defaults to
        `None`.

    Returns
    -------
    Result
        A result containing a list of delta
        leaderboard entries.
    """
    params = self._generate_map(
        metric=metric.value,
        period=period.value,
        playerType=player_type.value if player_type else None,
        playerBuild=player_build.value if player_build else None,
        country=country.value if country else None,
    )

    route = routes.GLOBAL_DELTA_LEADERS.compile()
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.DeltaLeaderboardEntry])

EfficiencyService

Bases: BaseService

Handles endpoints related to efficiency.

Source code in wom/services/efficiency.py
class EfficiencyService(BaseService):
    """Handles endpoints related to efficiency."""

    __slots__ = ()

    async def get_global_leaderboards(
        self,
        metric: enums.Metric = enums.Metric.Ehp,
        *,
        player_type: t.Optional[models.PlayerType] = None,
        player_build: t.Optional[models.PlayerBuild] = None,
        country: t.Optional[models.Country] = None,
        both: bool = False,
    ) -> ResultT[t.List[models.Player]]:
        """Gets the top global efficiency leaderboard.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.efficiency.get_global_leaderboards(
                player_type=wom.PlayerType.Ironman,
            )
            ```

        Parameters
        ----------
        metric : Metric
            The computed metric to filter on. Defaults to `Ehp`,
            must be one of `Ehp` or `Ehb` if supplied.
        player_type : PlayerType, optional
            The optional player type to filter on. Defaults
            to `None`.
        player_build : PlayerBuild, optional
            The optional player build to filter on.
            Defaults to `None`.
        country : Country, optional
            The optional country to filter on. Defaults to
            `None`.
        both : bool
            If `True`, request both ehp and ehb computed metric
            leaderboards. This will override the `metric` if it was
            provided. Defaults to `False`.

        Returns
        -------
        Result
            A result containing a list of the top
            players.
        """
        params = self._generate_map(
            playerType=player_type.value if player_type else None,
            playerBuild=player_build.value if player_build else None,
            country=country.value if country else None,
            metric=(
                metric.value
                if not both
                else "+".join(sorted((m.value for m in enums.ComputedMetrics), reverse=True))
            ),
        )

        route = routes.GLOBAL_EFFICIENCY_LEADERS.compile()
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.Player])

get_global_leaderboards async

get_global_leaderboards(
    metric: enums.Metric = enums.Metric.Ehp,
    *,
    player_type: t.Optional[models.PlayerType] = None,
    player_build: t.Optional[models.PlayerBuild] = None,
    country: t.Optional[models.Country] = None,
    both: bool = False
) -> ResultT[t.List[models.Player]]

Gets the top global efficiency leaderboard.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.efficiency.get_global_leaderboards(
    player_type=wom.PlayerType.Ironman,
)

Parameters:

Name Type Description Default
metric Metric

The computed metric to filter on. Defaults to Ehp, must be one of Ehp or Ehb if supplied.

Ehp
player_type PlayerType

The optional player type to filter on. Defaults to None.

None
player_build PlayerBuild

The optional player build to filter on. Defaults to None.

None
country Country

The optional country to filter on. Defaults to None.

None
both bool

If True, request both ehp and ehb computed metric leaderboards. This will override the metric if it was provided. Defaults to False.

False

Returns:

Type Description
Result

A result containing a list of the top players.

Source code in wom/services/efficiency.py
async def get_global_leaderboards(
    self,
    metric: enums.Metric = enums.Metric.Ehp,
    *,
    player_type: t.Optional[models.PlayerType] = None,
    player_build: t.Optional[models.PlayerBuild] = None,
    country: t.Optional[models.Country] = None,
    both: bool = False,
) -> ResultT[t.List[models.Player]]:
    """Gets the top global efficiency leaderboard.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.efficiency.get_global_leaderboards(
            player_type=wom.PlayerType.Ironman,
        )
        ```

    Parameters
    ----------
    metric : Metric
        The computed metric to filter on. Defaults to `Ehp`,
        must be one of `Ehp` or `Ehb` if supplied.
    player_type : PlayerType, optional
        The optional player type to filter on. Defaults
        to `None`.
    player_build : PlayerBuild, optional
        The optional player build to filter on.
        Defaults to `None`.
    country : Country, optional
        The optional country to filter on. Defaults to
        `None`.
    both : bool
        If `True`, request both ehp and ehb computed metric
        leaderboards. This will override the `metric` if it was
        provided. Defaults to `False`.

    Returns
    -------
    Result
        A result containing a list of the top
        players.
    """
    params = self._generate_map(
        playerType=player_type.value if player_type else None,
        playerBuild=player_build.value if player_build else None,
        country=country.value if country else None,
        metric=(
            metric.value
            if not both
            else "+".join(sorted((m.value for m in enums.ComputedMetrics), reverse=True))
        ),
    )

    route = routes.GLOBAL_EFFICIENCY_LEADERS.compile()
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.Player])

GroupService

Bases: BaseService

Handles endpoints related to groups.

Source code in wom/services/groups.py
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
class GroupService(BaseService):
    """Handles endpoints related to groups."""

    __slots__ = ()

    def _prepare_member_fragments(
        self, members: t.Iterable[t.Union[str, models.GroupMemberFragment]]
    ) -> tuple[t.Dict[str, t.Any], ...]:
        return tuple(
            {k: str(v) for k, v in m.to_dict().items() if v}
            for m in self._parse_member_fragments(members)
        )

    def _parse_member_fragments(
        self, members: t.Iterable[t.Union[str, models.GroupMemberFragment]]
    ) -> t.Generator[models.GroupMemberFragment, None, None]:
        return (models.GroupMemberFragment(m, None) if isinstance(m, str) else m for m in members)

    async def search_groups(
        self,
        name: t.Optional[str] = None,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.Group]]:
        """Searches for groups that at least partially match the given
        name.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.search_groups("Some group", limit=3)
            ```

        Parameters
        ----------
        name : str, optional
            The group name to search for.
        limit : int, optional
            The pagination limit.
        offset : int, optional
            The pagination offset.

        Returns
        -------
        Result
            A result containing the list of matching
            groups.
        """
        params = self._generate_map(name=name, limit=limit, offset=offset)
        route = routes.SEARCH_GROUPS.compile().with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Group])

    async def get_details(self, id: int) -> ResultT[models.GroupDetail]:
        """Gets the details for the given group id.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_details(1234)
            ```

        Parameters
        ----------
        id : int
            The group ID to get details for.

        Returns
        -------
        Result
            A result containing the group details.
        """
        route = routes.GROUP_DETAILS.compile(id)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.GroupDetail)

    async def create_group(
        self,
        name: str,
        *members: t.Union[str, models.GroupMemberFragment],
        clan_chat: t.Optional[str] = None,
        description: t.Optional[str] = None,
        homeworld: t.Optional[int] = None,
    ) -> ResultT[models.CreatedGroupDetail]:
        """Creates a new group.

        !!! note

            A mixture of strings and GroupMemberFragments can be passed for
            members. If a string is passed, no role will be added for that
            member.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.create_group(
                "My new group",
                wom.GroupMemberFragment("Jonxslays", wom.GroupRole.Owner),
                "Faabvk",
                "psikoi",
                "rro",
                description="The most epic group."
            )
            ```

        Parameters
        ----------
        name : str
            The name for the group.
        *members : str or GroupMemberFragment
            The optional members to add to the group.
        clan_chat : str, optional
            The optional clan chat for the group. Defaults to
            `None`.
        description : str, optional
            The optional group description. Defaults to
            `None`.
        homeworld : int, optional
            The optional homeworld for the group. Defaults to
            `None`.

        Returns
        -------
        Result
            A result containing the created group details.
        """
        payload = self._generate_map(
            name=name,
            clanChat=clan_chat,
            homeworld=homeworld,
            description=description,
            members=self._prepare_member_fragments(members),
        )

        route = routes.CREATE_GROUP.compile()
        data = await self._http.fetch(route, payload=payload)
        return self._ok_or_err(data, models.CreatedGroupDetail)

    async def edit_group(
        self,
        id: int,
        verification_code: str,
        *,
        name: t.Optional[str] = None,
        members: t.Optional[t.Iterable[t.Union[str, models.GroupMemberFragment]]] = None,
        clan_chat: t.Optional[str] = None,
        description: t.Optional[str] = None,
        homeworld: t.Optional[int] = None,
        social_links: t.Optional[models.SocialLinks] = None,
    ) -> ResultT[models.GroupDetail]:
        """Edits an existing group.

        !!! warning

            The members list provided will completely replace the
            existing members. If you want to add members, see
            [`add_members()`][wom.GroupService.add_members]

        !!! note

             A mixture of strings and GroupMemberFragments can be passed for
             members. If a string is passed, no role will be added for that
             member.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.edit_group(
                123,
                "111-111-111",
                name="My new group name",
                members=[
                    wom.GroupMemberFragment("Jonxslays", wom.GroupRole.Owner),
                    "Faabvk",
                ],
                description="Some new description."
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        verification_code : str
            The group verification code.
        name : str, optional
            The optional new name for the group. Defaults to
            `None`.
        members : Iterable[str or GroupMemberFragment], optional
            The optional iterable of members to replace the
            existing group members with. Defaults to `None`.
        clan_chat : str, optional
            The optional new clan chat for the group.
            Defaults to `None`.
        description : str, optional
            The optional new group description. Defaults to
            `None`.
        homeworld : int, optional
            The optional new homeworld for the group.
            Defaults to `None`.
        social_links : SocialLinks, optional
            The optional new social links for the group.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the group details.
        """
        payload = self._generate_map(
            name=name,
            clanChat=clan_chat,
            homeworld=homeworld,
            description=description,
            verificationCode=verification_code,
            members=self._prepare_member_fragments(members) if members else None,
            socialLinks=social_links.to_dict() if social_links else None,
        )

        route = routes.EDIT_GROUP.compile(id)
        data = await self._http.fetch(route, payload=payload)
        return self._ok_or_err(data, models.GroupDetail)

    async def delete_group(
        self, id: int, verification_code: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Deletes an existing group.

        !!! warning

            This action is irreversible.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.delete_group(123, "111-111-111")
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        verification_code : str
            The group verification code.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.DELETE_GROUP.compile(id)
        payload = self._generate_map(verificationCode=verification_code)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def add_members(
        self, id: int, verification_code: str, *members: t.Union[str, models.GroupMemberFragment]
    ) -> ResultT[models.HttpSuccessResponse]:
        """Adds members to an existing group.

        !!! note

             A mixture of strings and GroupMemberFragments can be passed for
             members. If a string is passed, no role will be added for that
             member.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.add_members(
                123,
                "111-111-111",
                wom.GroupMemberFragment(
                    "Jonxslays", wom.GroupRole.Administrator
                ),
                "Zezima",
                "Psikoi",
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        verification_code : str
            The group verification code.
        *members : str or GroupMemberFragment
            The members to add to the group.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        payload = self._generate_map(
            verificationCode=verification_code,
            members=self._prepare_member_fragments(members),
        )

        route = routes.ADD_MEMBERS.compile(id)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def remove_members(
        self, id: int, verification_code: str, *members: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Removes members from an existing group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.remove_members(
                123,
                "111-111-111",
                "Jonxslays",
                "Zezima",
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        verification_code : str
            The group verification code.
        *members : str
            The usernames of members to remove from the group.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.REMOVE_MEMBERS.compile(id)
        payload = self._generate_map(verificationCode=verification_code, members=members)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data)

    async def change_member_role(
        self, id: int, verification_code: str, username: str, role: models.GroupRole
    ) -> ResultT[models.GroupMembership]:
        """Changes the role for a member in an existing group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.change_member_role(
                123,
                "111-111-111",
                "Jonxslays",
                wom.GroupRole.Admiral
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        verification_code : str
            The group verification code.
        username : str
            The username of the player to update.
        role : GroupRole
            The players new group role.

        Returns
        -------
        Result
            A result containing the players group
            membership.
        """
        payload = self._generate_map(
            verificationCode=verification_code, username=username, role=role.value
        )

        route = routes.CHANGE_MEMBER_ROLE.compile(id)
        data = await self._http.fetch(route, payload=payload)
        return self._ok_or_err(data, models.GroupMembership)

    async def update_outdated_members(
        self, id: int, verification_code: str
    ) -> ResultT[models.HttpSuccessResponse]:
        """Attempts to update all outdated group members.

        !!! info

            Group members are considered outdated when they haven't been
            updated in over 24h.

        !!! warning

            This method adds every outdated member to an "update queue",
            and the WOM servers try to update players in the queue one
            by one, with a delay in between each. For each player in the
            queue, an attempt is made to update it up to 3 times, with
            30s in between each attempt.

            Please note that this is dependent on the OSRS hiscores
            functioning correctly, and therefore this method does NOT
            guarantee the players will be updated, it only guarantees
            that an attempt will be made to update them, up to 3 times.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.groups.update_outdated_members(
                123, "111-111-111"
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        verification_code : str
            The verification code for the group.

        Returns
        -------
        Result
            A result containing the success response
            message.
        """
        route = routes.UPDATE_OUTDATED_MEMBERS.compile(id)
        payload = self._generate_map(verificationCode=verification_code)
        data = await self._http.fetch(route, payload=payload, allow_http_success=True)
        return self._success_or_err(data, predicate=lambda m: "players are being updated" in m)

    async def get_competitions(
        self, id: int, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
    ) -> ResultT[t.List[models.Competition]]:
        """Gets competitions for a given group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_competitions(123, limit=10)
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        limit : int, optional
            The optional pagination limit. Defaults to `None`.
        offset : int, optional
            The optional pagination offset. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of
            competitions.
        """
        params = self._generate_map(limit=limit, offset=offset)
        route = routes.GROUP_COMPETITIONS.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Competition])

    async def get_gains(
        self,
        id: int,
        metric: enums.Metric,
        *,
        period: t.Optional[enums.Period] = None,
        start_date: t.Optional[datetime] = None,
        end_date: t.Optional[datetime] = None,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.GroupMemberGains]]:
        """Gets the gains for a group over a particular time frame.

        !!! info

            You must pass one of (`period`) or (`start_date` +
            `end_date`), but not both.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_gains(
                123, wom.Metric.Zulrah, period=wom.Period.Week, limit=10
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        metric : Metric
            The metric to filter on.
        period : Period, optional
            The optional period of time to get gains for.
            Defaults to `None`.
        start_date : datetime, optional
            The minimum date to get the gains from. Defaults
            to `None`.
        end_date : datetime, optional
            The maximum date to get the gains from. Defaults
            to `None`.
        limit : int, optional
            The optional pagination limit. Defaults to `None`.
        offset : int, optional
            The optional pagination offset. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of group gains.
        """
        params = self._generate_map(
            limit=limit,
            offset=offset,
            metric=metric.value,
            period=period.value if period else None,
            endDate=end_date.isoformat() if end_date else None,
            startDate=start_date.isoformat() if start_date else None,
        )

        route = routes.GROUP_GAINS.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.GroupMemberGains])

    async def get_bulk_gains(
        self,
        id: int,
        *,
        period: t.Optional[enums.Period] = None,
        start_date: t.Optional[datetime] = None,
        end_date: t.Optional[datetime] = None,
    ) -> ResultT[t.List[models.BulkGroupMemberGains]]:
        """Gets the bulk gains of all metrics for a group over a particular time frame.

        !!! info

            You must pass one of (`period`) or (`start_date` +
            `end_date`), but not both.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_bulk_gains(
                123, period=wom.Period.Week
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        period : Period, optional
            The optional period of time to get gains for.
            Defaults to `None`.
        start_date : datetime, optional
            The minimum date to get the gains from. Defaults
            to `None`.
        end_date : datetime, optional
            The maximum date to get the gains from. Defaults
            to `None`.

        Returns
        -------
        Result
            A result containing the list of bulk group gains.
        """
        params = self._generate_map(
            period=period.value if period else None,
            endDate=end_date.isoformat() if end_date else None,
            startDate=start_date.isoformat() if start_date else None,
        )

        route = routes.GROUP_BULK_GAINS.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.BulkGroupMemberGains])

    async def get_achievements(
        self,
        id: int,
        *,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.Achievement]]:
        """Gets the achievements for the group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_achievements(123, limit=10)
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        limit : int, optional
            The optional pagination limit. Defaults to `None`.
        offset : int, optional
            The optional pagination offset. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of achievements.
        """
        params = self._generate_map(limit=limit, offset=offset)
        route = routes.GROUP_ACHIEVEMENTS.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Achievement])

    async def get_records(
        self,
        id: int,
        metric: enums.Metric,
        period: enums.Period,
        *,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.RecordLeaderboardEntry]]:
        """Gets the records held by players in the group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_records(
                123, wom.Metric.Zulrah, wom.Period.Day, limit=3
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        metric : Metric
            The metric to filter on.
        period : Period
            The period of time to get records for.
        limit : int, optional
            The optional pagination limit. Defaults to `None`.
        offset : int, optional
            The optional pagination offset. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of record
            leaderboard entries.
        """
        params = self._generate_map(
            limit=limit,
            offset=offset,
            metric=metric.value,
            period=period.value,
        )

        route = routes.GROUP_RECORDS.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.RecordLeaderboardEntry])

    async def get_hiscores(
        self,
        id: int,
        metric: enums.Metric,
        *,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.GroupHiscoresEntry]]:
        """Gets the hiscores for the group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_hiscores(
                123, wom.Metric.Runecrafting, limit=10
            )
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        metric : Metric
            The metric to filter on.
        limit : int, optional
            The optional pagination limit. Defaults to `None`.
        offset : int, optional
            The optional pagination offset. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of hiscores
            entries.
        """
        params = self._generate_map(limit=limit, offset=offset, metric=metric.value)
        route = routes.GROUP_HISCORES.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.GroupHiscoresEntry])

    async def get_bulk_hiscores(self, id: int) -> ResultT[t.List[models.BulkGroupHiscoresEntry]]:
        """Gets the bulk hiscores for the group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_bulk_hiscores(123)
            ```

        Parameters
        ----------
        id : int
            The ID of the group.

        Returns
        -------
        Result
            A result containing the list of bulk
            hiscores entries.
        """
        route = routes.GROUP_BULK_HISCORES.compile(id)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.BulkGroupHiscoresEntry])

    async def get_name_changes(
        self, id: int, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
    ) -> ResultT[t.List[models.NameChange]]:
        """Gets the past name changes for the group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_name_changes(123, limit=10)
            ```

        Parameters
        ----------
        id : int
            The ID of the group.
        limit : int, optional
            The optional pagination limit. Defaults to `None`.
        offset : int, optional
            The optional pagination offset. Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list name changes.
        """
        params = self._generate_map(limit=limit, offset=offset)
        route = routes.GROUP_NAME_CHANGES.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.NameChange])

    async def get_statistics(self, id: int) -> ResultT[models.GroupStatistics]:
        """Gets the statistics for the group.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_statistics(123)
            ```

        Parameters
        ----------
        id : int
            The ID of the group.

        Returns
        -------
        Result
            A result containing the statistics.
        """
        route = routes.GROUP_STATISTICS.compile(id)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.GroupStatistics)

    async def get_activity(
        self,
        id: int,
        *,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.GroupActivity]]:
        """Gets the activity for the group. This is a paginated endpoint.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            await client.groups.get_activity(69, limit=5)
            ```

        Parameters
        ----------
        id : int
            The ID of the group to fetch activity for.
        limit : int, optional
            The pagination limit.
        offset : int, optional
            The pagination offset.

        Returns
        -------
        Result
            A result containing the list of activities.
        """
        params = self._generate_map(limit=limit, offset=offset)
        route = routes.GROUP_ACTIVITY.compile(id).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.GroupActivity])

    async def get_members_csv(self, id: int) -> ResultT[str]:
        """Gets members in this group in CSV format.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.groups.get_members_csv(123)
            ```

        Parameters
        ----------
        id : int
            The ID of the group.

        Returns
        -------
        Result
            A result containing the CSV string.
        """
        route = routes.GROUP_MEMBERS_CSV.compile(id)
        data = await self._http.fetch(route)

        if isinstance(data, models.HttpErrorResponse):
            return result.Err(data)

        return result.Ok(data.decode())

add_members async

add_members(
    id: int,
    verification_code: str,
    *members: t.Union[str, models.GroupMemberFragment]
) -> ResultT[models.HttpSuccessResponse]

Adds members to an existing group.

Note

A mixture of strings and GroupMemberFragments can be passed for members. If a string is passed, no role will be added for that member.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.add_members(
    123,
    "111-111-111",
    wom.GroupMemberFragment(
        "Jonxslays", wom.GroupRole.Administrator
    ),
    "Zezima",
    "Psikoi",
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
verification_code str

The group verification code.

required
*members str or GroupMemberFragment

The members to add to the group.

()

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/groups.py
async def add_members(
    self, id: int, verification_code: str, *members: t.Union[str, models.GroupMemberFragment]
) -> ResultT[models.HttpSuccessResponse]:
    """Adds members to an existing group.

    !!! note

         A mixture of strings and GroupMemberFragments can be passed for
         members. If a string is passed, no role will be added for that
         member.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.add_members(
            123,
            "111-111-111",
            wom.GroupMemberFragment(
                "Jonxslays", wom.GroupRole.Administrator
            ),
            "Zezima",
            "Psikoi",
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    verification_code : str
        The group verification code.
    *members : str or GroupMemberFragment
        The members to add to the group.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    payload = self._generate_map(
        verificationCode=verification_code,
        members=self._prepare_member_fragments(members),
    )

    route = routes.ADD_MEMBERS.compile(id)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

change_member_role async

change_member_role(
    id: int,
    verification_code: str,
    username: str,
    role: models.GroupRole,
) -> ResultT[models.GroupMembership]

Changes the role for a member in an existing group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.change_member_role(
    123,
    "111-111-111",
    "Jonxslays",
    wom.GroupRole.Admiral
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
verification_code str

The group verification code.

required
username str

The username of the player to update.

required
role GroupRole

The players new group role.

required

Returns:

Type Description
Result

A result containing the players group membership.

Source code in wom/services/groups.py
async def change_member_role(
    self, id: int, verification_code: str, username: str, role: models.GroupRole
) -> ResultT[models.GroupMembership]:
    """Changes the role for a member in an existing group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.change_member_role(
            123,
            "111-111-111",
            "Jonxslays",
            wom.GroupRole.Admiral
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    verification_code : str
        The group verification code.
    username : str
        The username of the player to update.
    role : GroupRole
        The players new group role.

    Returns
    -------
    Result
        A result containing the players group
        membership.
    """
    payload = self._generate_map(
        verificationCode=verification_code, username=username, role=role.value
    )

    route = routes.CHANGE_MEMBER_ROLE.compile(id)
    data = await self._http.fetch(route, payload=payload)
    return self._ok_or_err(data, models.GroupMembership)

create_group async

create_group(
    name: str,
    *members: t.Union[str, models.GroupMemberFragment],
    clan_chat: t.Optional[str] = None,
    description: t.Optional[str] = None,
    homeworld: t.Optional[int] = None
) -> ResultT[models.CreatedGroupDetail]

Creates a new group.

Note

A mixture of strings and GroupMemberFragments can be passed for members. If a string is passed, no role will be added for that member.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.create_group(
    "My new group",
    wom.GroupMemberFragment("Jonxslays", wom.GroupRole.Owner),
    "Faabvk",
    "psikoi",
    "rro",
    description="The most epic group."
)

Parameters:

Name Type Description Default
name str

The name for the group.

required
*members str or GroupMemberFragment

The optional members to add to the group.

()
clan_chat str

The optional clan chat for the group. Defaults to None.

None
description str

The optional group description. Defaults to None.

None
homeworld int

The optional homeworld for the group. Defaults to None.

None

Returns:

Type Description
Result

A result containing the created group details.

Source code in wom/services/groups.py
async def create_group(
    self,
    name: str,
    *members: t.Union[str, models.GroupMemberFragment],
    clan_chat: t.Optional[str] = None,
    description: t.Optional[str] = None,
    homeworld: t.Optional[int] = None,
) -> ResultT[models.CreatedGroupDetail]:
    """Creates a new group.

    !!! note

        A mixture of strings and GroupMemberFragments can be passed for
        members. If a string is passed, no role will be added for that
        member.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.create_group(
            "My new group",
            wom.GroupMemberFragment("Jonxslays", wom.GroupRole.Owner),
            "Faabvk",
            "psikoi",
            "rro",
            description="The most epic group."
        )
        ```

    Parameters
    ----------
    name : str
        The name for the group.
    *members : str or GroupMemberFragment
        The optional members to add to the group.
    clan_chat : str, optional
        The optional clan chat for the group. Defaults to
        `None`.
    description : str, optional
        The optional group description. Defaults to
        `None`.
    homeworld : int, optional
        The optional homeworld for the group. Defaults to
        `None`.

    Returns
    -------
    Result
        A result containing the created group details.
    """
    payload = self._generate_map(
        name=name,
        clanChat=clan_chat,
        homeworld=homeworld,
        description=description,
        members=self._prepare_member_fragments(members),
    )

    route = routes.CREATE_GROUP.compile()
    data = await self._http.fetch(route, payload=payload)
    return self._ok_or_err(data, models.CreatedGroupDetail)

delete_group async

delete_group(
    id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]

Deletes an existing group.

Warning

This action is irreversible.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.delete_group(123, "111-111-111")

Parameters:

Name Type Description Default
id int

The ID of the group.

required
verification_code str

The group verification code.

required

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/groups.py
async def delete_group(
    self, id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]:
    """Deletes an existing group.

    !!! warning

        This action is irreversible.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.delete_group(123, "111-111-111")
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    verification_code : str
        The group verification code.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.DELETE_GROUP.compile(id)
    payload = self._generate_map(verificationCode=verification_code)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

edit_group async

edit_group(
    id: int,
    verification_code: str,
    *,
    name: t.Optional[str] = None,
    members: t.Optional[
        t.Iterable[t.Union[str, models.GroupMemberFragment]]
    ] = None,
    clan_chat: t.Optional[str] = None,
    description: t.Optional[str] = None,
    homeworld: t.Optional[int] = None,
    social_links: t.Optional[models.SocialLinks] = None
) -> ResultT[models.GroupDetail]

Edits an existing group.

Warning

The members list provided will completely replace the existing members. If you want to add members, see add_members()

Note

A mixture of strings and GroupMemberFragments can be passed for members. If a string is passed, no role will be added for that member.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.edit_group(
    123,
    "111-111-111",
    name="My new group name",
    members=[
        wom.GroupMemberFragment("Jonxslays", wom.GroupRole.Owner),
        "Faabvk",
    ],
    description="Some new description."
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
verification_code str

The group verification code.

required
name str

The optional new name for the group. Defaults to None.

None
members Iterable[str or GroupMemberFragment]

The optional iterable of members to replace the existing group members with. Defaults to None.

None
clan_chat str

The optional new clan chat for the group. Defaults to None.

None
description str

The optional new group description. Defaults to None.

None
homeworld int

The optional new homeworld for the group. Defaults to None.

None
social_links SocialLinks

The optional new social links for the group. Defaults to None.

None

Returns:

Type Description
Result

A result containing the group details.

Source code in wom/services/groups.py
async def edit_group(
    self,
    id: int,
    verification_code: str,
    *,
    name: t.Optional[str] = None,
    members: t.Optional[t.Iterable[t.Union[str, models.GroupMemberFragment]]] = None,
    clan_chat: t.Optional[str] = None,
    description: t.Optional[str] = None,
    homeworld: t.Optional[int] = None,
    social_links: t.Optional[models.SocialLinks] = None,
) -> ResultT[models.GroupDetail]:
    """Edits an existing group.

    !!! warning

        The members list provided will completely replace the
        existing members. If you want to add members, see
        [`add_members()`][wom.GroupService.add_members]

    !!! note

         A mixture of strings and GroupMemberFragments can be passed for
         members. If a string is passed, no role will be added for that
         member.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.edit_group(
            123,
            "111-111-111",
            name="My new group name",
            members=[
                wom.GroupMemberFragment("Jonxslays", wom.GroupRole.Owner),
                "Faabvk",
            ],
            description="Some new description."
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    verification_code : str
        The group verification code.
    name : str, optional
        The optional new name for the group. Defaults to
        `None`.
    members : Iterable[str or GroupMemberFragment], optional
        The optional iterable of members to replace the
        existing group members with. Defaults to `None`.
    clan_chat : str, optional
        The optional new clan chat for the group.
        Defaults to `None`.
    description : str, optional
        The optional new group description. Defaults to
        `None`.
    homeworld : int, optional
        The optional new homeworld for the group.
        Defaults to `None`.
    social_links : SocialLinks, optional
        The optional new social links for the group.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the group details.
    """
    payload = self._generate_map(
        name=name,
        clanChat=clan_chat,
        homeworld=homeworld,
        description=description,
        verificationCode=verification_code,
        members=self._prepare_member_fragments(members) if members else None,
        socialLinks=social_links.to_dict() if social_links else None,
    )

    route = routes.EDIT_GROUP.compile(id)
    data = await self._http.fetch(route, payload=payload)
    return self._ok_or_err(data, models.GroupDetail)

get_achievements async

get_achievements(
    id: int,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.Achievement]]

Gets the achievements for the group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_achievements(123, limit=10)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
limit int

The optional pagination limit. Defaults to None.

None
offset int

The optional pagination offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of achievements.

Source code in wom/services/groups.py
async def get_achievements(
    self,
    id: int,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.Achievement]]:
    """Gets the achievements for the group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_achievements(123, limit=10)
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    limit : int, optional
        The optional pagination limit. Defaults to `None`.
    offset : int, optional
        The optional pagination offset. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of achievements.
    """
    params = self._generate_map(limit=limit, offset=offset)
    route = routes.GROUP_ACHIEVEMENTS.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Achievement])

get_activity async

get_activity(
    id: int,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.GroupActivity]]

Gets the activity for the group. This is a paginated endpoint.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_activity(69, limit=5)

Parameters:

Name Type Description Default
id int

The ID of the group to fetch activity for.

required
limit int

The pagination limit.

None
offset int

The pagination offset.

None

Returns:

Type Description
Result

A result containing the list of activities.

Source code in wom/services/groups.py
async def get_activity(
    self,
    id: int,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.GroupActivity]]:
    """Gets the activity for the group. This is a paginated endpoint.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_activity(69, limit=5)
        ```

    Parameters
    ----------
    id : int
        The ID of the group to fetch activity for.
    limit : int, optional
        The pagination limit.
    offset : int, optional
        The pagination offset.

    Returns
    -------
    Result
        A result containing the list of activities.
    """
    params = self._generate_map(limit=limit, offset=offset)
    route = routes.GROUP_ACTIVITY.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.GroupActivity])

get_bulk_gains async

get_bulk_gains(
    id: int,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None
) -> ResultT[t.List[models.BulkGroupMemberGains]]

Gets the bulk gains of all metrics for a group over a particular time frame.

Info

You must pass one of (period) or (start_date + end_date), but not both.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_bulk_gains(
    123, period=wom.Period.Week
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
period Period

The optional period of time to get gains for. Defaults to None.

None
start_date datetime

The minimum date to get the gains from. Defaults to None.

None
end_date datetime

The maximum date to get the gains from. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of bulk group gains.

Source code in wom/services/groups.py
async def get_bulk_gains(
    self,
    id: int,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
) -> ResultT[t.List[models.BulkGroupMemberGains]]:
    """Gets the bulk gains of all metrics for a group over a particular time frame.

    !!! info

        You must pass one of (`period`) or (`start_date` +
        `end_date`), but not both.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_bulk_gains(
            123, period=wom.Period.Week
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    period : Period, optional
        The optional period of time to get gains for.
        Defaults to `None`.
    start_date : datetime, optional
        The minimum date to get the gains from. Defaults
        to `None`.
    end_date : datetime, optional
        The maximum date to get the gains from. Defaults
        to `None`.

    Returns
    -------
    Result
        A result containing the list of bulk group gains.
    """
    params = self._generate_map(
        period=period.value if period else None,
        endDate=end_date.isoformat() if end_date else None,
        startDate=start_date.isoformat() if start_date else None,
    )

    route = routes.GROUP_BULK_GAINS.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.BulkGroupMemberGains])

get_bulk_hiscores async

get_bulk_hiscores(
    id: int,
) -> ResultT[t.List[models.BulkGroupHiscoresEntry]]

Gets the bulk hiscores for the group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_bulk_hiscores(123)

Parameters:

Name Type Description Default
id int

The ID of the group.

required

Returns:

Type Description
Result

A result containing the list of bulk hiscores entries.

Source code in wom/services/groups.py
async def get_bulk_hiscores(self, id: int) -> ResultT[t.List[models.BulkGroupHiscoresEntry]]:
    """Gets the bulk hiscores for the group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_bulk_hiscores(123)
        ```

    Parameters
    ----------
    id : int
        The ID of the group.

    Returns
    -------
    Result
        A result containing the list of bulk
        hiscores entries.
    """
    route = routes.GROUP_BULK_HISCORES.compile(id)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.BulkGroupHiscoresEntry])

get_competitions async

get_competitions(
    id: int,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.Competition]]

Gets competitions for a given group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_competitions(123, limit=10)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
limit int

The optional pagination limit. Defaults to None.

None
offset int

The optional pagination offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of competitions.

Source code in wom/services/groups.py
async def get_competitions(
    self, id: int, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
) -> ResultT[t.List[models.Competition]]:
    """Gets competitions for a given group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_competitions(123, limit=10)
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    limit : int, optional
        The optional pagination limit. Defaults to `None`.
    offset : int, optional
        The optional pagination offset. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of
        competitions.
    """
    params = self._generate_map(limit=limit, offset=offset)
    route = routes.GROUP_COMPETITIONS.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Competition])

get_details async

get_details(id: int) -> ResultT[models.GroupDetail]

Gets the details for the given group id.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_details(1234)

Parameters:

Name Type Description Default
id int

The group ID to get details for.

required

Returns:

Type Description
Result

A result containing the group details.

Source code in wom/services/groups.py
async def get_details(self, id: int) -> ResultT[models.GroupDetail]:
    """Gets the details for the given group id.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_details(1234)
        ```

    Parameters
    ----------
    id : int
        The group ID to get details for.

    Returns
    -------
    Result
        A result containing the group details.
    """
    route = routes.GROUP_DETAILS.compile(id)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.GroupDetail)

get_gains async

get_gains(
    id: int,
    metric: enums.Metric,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.GroupMemberGains]]

Gets the gains for a group over a particular time frame.

Info

You must pass one of (period) or (start_date + end_date), but not both.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_gains(
    123, wom.Metric.Zulrah, period=wom.Period.Week, limit=10
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
metric Metric

The metric to filter on.

required
period Period

The optional period of time to get gains for. Defaults to None.

None
start_date datetime

The minimum date to get the gains from. Defaults to None.

None
end_date datetime

The maximum date to get the gains from. Defaults to None.

None
limit int

The optional pagination limit. Defaults to None.

None
offset int

The optional pagination offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of group gains.

Source code in wom/services/groups.py
async def get_gains(
    self,
    id: int,
    metric: enums.Metric,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.GroupMemberGains]]:
    """Gets the gains for a group over a particular time frame.

    !!! info

        You must pass one of (`period`) or (`start_date` +
        `end_date`), but not both.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_gains(
            123, wom.Metric.Zulrah, period=wom.Period.Week, limit=10
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    metric : Metric
        The metric to filter on.
    period : Period, optional
        The optional period of time to get gains for.
        Defaults to `None`.
    start_date : datetime, optional
        The minimum date to get the gains from. Defaults
        to `None`.
    end_date : datetime, optional
        The maximum date to get the gains from. Defaults
        to `None`.
    limit : int, optional
        The optional pagination limit. Defaults to `None`.
    offset : int, optional
        The optional pagination offset. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of group gains.
    """
    params = self._generate_map(
        limit=limit,
        offset=offset,
        metric=metric.value,
        period=period.value if period else None,
        endDate=end_date.isoformat() if end_date else None,
        startDate=start_date.isoformat() if start_date else None,
    )

    route = routes.GROUP_GAINS.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.GroupMemberGains])

get_hiscores async

get_hiscores(
    id: int,
    metric: enums.Metric,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.GroupHiscoresEntry]]

Gets the hiscores for the group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_hiscores(
    123, wom.Metric.Runecrafting, limit=10
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
metric Metric

The metric to filter on.

required
limit int

The optional pagination limit. Defaults to None.

None
offset int

The optional pagination offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of hiscores entries.

Source code in wom/services/groups.py
async def get_hiscores(
    self,
    id: int,
    metric: enums.Metric,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.GroupHiscoresEntry]]:
    """Gets the hiscores for the group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_hiscores(
            123, wom.Metric.Runecrafting, limit=10
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    metric : Metric
        The metric to filter on.
    limit : int, optional
        The optional pagination limit. Defaults to `None`.
    offset : int, optional
        The optional pagination offset. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of hiscores
        entries.
    """
    params = self._generate_map(limit=limit, offset=offset, metric=metric.value)
    route = routes.GROUP_HISCORES.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.GroupHiscoresEntry])

get_members_csv async

get_members_csv(id: int) -> ResultT[str]

Gets members in this group in CSV format.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.groups.get_members_csv(123)

Parameters:

Name Type Description Default
id int

The ID of the group.

required

Returns:

Type Description
Result

A result containing the CSV string.

Source code in wom/services/groups.py
async def get_members_csv(self, id: int) -> ResultT[str]:
    """Gets members in this group in CSV format.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.groups.get_members_csv(123)
        ```

    Parameters
    ----------
    id : int
        The ID of the group.

    Returns
    -------
    Result
        A result containing the CSV string.
    """
    route = routes.GROUP_MEMBERS_CSV.compile(id)
    data = await self._http.fetch(route)

    if isinstance(data, models.HttpErrorResponse):
        return result.Err(data)

    return result.Ok(data.decode())

get_name_changes async

get_name_changes(
    id: int,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.NameChange]]

Gets the past name changes for the group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_name_changes(123, limit=10)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
limit int

The optional pagination limit. Defaults to None.

None
offset int

The optional pagination offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list name changes.

Source code in wom/services/groups.py
async def get_name_changes(
    self, id: int, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
) -> ResultT[t.List[models.NameChange]]:
    """Gets the past name changes for the group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_name_changes(123, limit=10)
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    limit : int, optional
        The optional pagination limit. Defaults to `None`.
    offset : int, optional
        The optional pagination offset. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list name changes.
    """
    params = self._generate_map(limit=limit, offset=offset)
    route = routes.GROUP_NAME_CHANGES.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.NameChange])

get_records async

get_records(
    id: int,
    metric: enums.Metric,
    period: enums.Period,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.RecordLeaderboardEntry]]

Gets the records held by players in the group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_records(
    123, wom.Metric.Zulrah, wom.Period.Day, limit=3
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
metric Metric

The metric to filter on.

required
period Period

The period of time to get records for.

required
limit int

The optional pagination limit. Defaults to None.

None
offset int

The optional pagination offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of record leaderboard entries.

Source code in wom/services/groups.py
async def get_records(
    self,
    id: int,
    metric: enums.Metric,
    period: enums.Period,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.RecordLeaderboardEntry]]:
    """Gets the records held by players in the group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_records(
            123, wom.Metric.Zulrah, wom.Period.Day, limit=3
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    metric : Metric
        The metric to filter on.
    period : Period
        The period of time to get records for.
    limit : int, optional
        The optional pagination limit. Defaults to `None`.
    offset : int, optional
        The optional pagination offset. Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of record
        leaderboard entries.
    """
    params = self._generate_map(
        limit=limit,
        offset=offset,
        metric=metric.value,
        period=period.value,
    )

    route = routes.GROUP_RECORDS.compile(id).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.RecordLeaderboardEntry])

get_statistics async

get_statistics(id: int) -> ResultT[models.GroupStatistics]

Gets the statistics for the group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.get_statistics(123)

Parameters:

Name Type Description Default
id int

The ID of the group.

required

Returns:

Type Description
Result

A result containing the statistics.

Source code in wom/services/groups.py
async def get_statistics(self, id: int) -> ResultT[models.GroupStatistics]:
    """Gets the statistics for the group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.get_statistics(123)
        ```

    Parameters
    ----------
    id : int
        The ID of the group.

    Returns
    -------
    Result
        A result containing the statistics.
    """
    route = routes.GROUP_STATISTICS.compile(id)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.GroupStatistics)

remove_members async

remove_members(
    id: int, verification_code: str, *members: str
) -> ResultT[models.HttpSuccessResponse]

Removes members from an existing group.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.remove_members(
    123,
    "111-111-111",
    "Jonxslays",
    "Zezima",
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
verification_code str

The group verification code.

required
*members str

The usernames of members to remove from the group.

()

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/groups.py
async def remove_members(
    self, id: int, verification_code: str, *members: str
) -> ResultT[models.HttpSuccessResponse]:
    """Removes members from an existing group.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.remove_members(
            123,
            "111-111-111",
            "Jonxslays",
            "Zezima",
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    verification_code : str
        The group verification code.
    *members : str
        The usernames of members to remove from the group.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.REMOVE_MEMBERS.compile(id)
    payload = self._generate_map(verificationCode=verification_code, members=members)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data)

search_groups async

search_groups(
    name: t.Optional[str] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.Group]]

Searches for groups that at least partially match the given name.

Example
import wom

client = wom.Client(...)

await client.start()

await client.groups.search_groups("Some group", limit=3)

Parameters:

Name Type Description Default
name str

The group name to search for.

None
limit int

The pagination limit.

None
offset int

The pagination offset.

None

Returns:

Type Description
Result

A result containing the list of matching groups.

Source code in wom/services/groups.py
async def search_groups(
    self,
    name: t.Optional[str] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.Group]]:
    """Searches for groups that at least partially match the given
    name.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        await client.groups.search_groups("Some group", limit=3)
        ```

    Parameters
    ----------
    name : str, optional
        The group name to search for.
    limit : int, optional
        The pagination limit.
    offset : int, optional
        The pagination offset.

    Returns
    -------
    Result
        A result containing the list of matching
        groups.
    """
    params = self._generate_map(name=name, limit=limit, offset=offset)
    route = routes.SEARCH_GROUPS.compile().with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Group])

update_outdated_members async

update_outdated_members(
    id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]

Attempts to update all outdated group members.

Info

Group members are considered outdated when they haven't been updated in over 24h.

Warning

This method adds every outdated member to an "update queue", and the WOM servers try to update players in the queue one by one, with a delay in between each. For each player in the queue, an attempt is made to update it up to 3 times, with 30s in between each attempt.

Please note that this is dependent on the OSRS hiscores functioning correctly, and therefore this method does NOT guarantee the players will be updated, it only guarantees that an attempt will be made to update them, up to 3 times.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.groups.update_outdated_members(
    123, "111-111-111"
)

Parameters:

Name Type Description Default
id int

The ID of the group.

required
verification_code str

The verification code for the group.

required

Returns:

Type Description
Result

A result containing the success response message.

Source code in wom/services/groups.py
async def update_outdated_members(
    self, id: int, verification_code: str
) -> ResultT[models.HttpSuccessResponse]:
    """Attempts to update all outdated group members.

    !!! info

        Group members are considered outdated when they haven't been
        updated in over 24h.

    !!! warning

        This method adds every outdated member to an "update queue",
        and the WOM servers try to update players in the queue one
        by one, with a delay in between each. For each player in the
        queue, an attempt is made to update it up to 3 times, with
        30s in between each attempt.

        Please note that this is dependent on the OSRS hiscores
        functioning correctly, and therefore this method does NOT
        guarantee the players will be updated, it only guarantees
        that an attempt will be made to update them, up to 3 times.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.groups.update_outdated_members(
            123, "111-111-111"
        )
        ```

    Parameters
    ----------
    id : int
        The ID of the group.
    verification_code : str
        The verification code for the group.

    Returns
    -------
    Result
        A result containing the success response
        message.
    """
    route = routes.UPDATE_OUTDATED_MEMBERS.compile(id)
    payload = self._generate_map(verificationCode=verification_code)
    data = await self._http.fetch(route, payload=payload, allow_http_success=True)
    return self._success_or_err(data, predicate=lambda m: "players are being updated" in m)

HttpService

The HTTP service used to make requests to the WOM API.

Parameters:

Name Type Description Default
api_key str

The optional api key to use.

required
user_agent str

The optional user agent to use.

required
api_base_url str

The optional api base url to use.

required
Source code in wom/services/http.py
class HttpService:
    """The HTTP service used to make requests to the WOM API.

    Parameters
    ----------
    api_key : str, optional
        The optional api key to use.
    user_agent : str, optional
        The optional user agent to use.
    api_base_url : str, optional
        The optional api base url to use.
    """

    __slots__ = ("_base_url", "_decoder", "_encoder", "_headers", "_method_mapping", "_session")

    def __init__(
        self,
        api_key: t.Optional[str],
        user_agent: t.Optional[str],
        api_base_url: t.Optional[str],
    ) -> None:
        user_agent = (
            f"{constants.USER_AGENT_BASE} {user_agent}"
            if user_agent
            else constants.DEFAULT_USER_AGENT
        )

        self._headers = {
            "x-user-agent": user_agent,
            "User-Agent": user_agent,
        }

        if api_key:
            self._headers["x-api-key"] = api_key

        self._base_url = api_base_url or constants.WOM_BASE_URL
        self._decoder = msgspec.json.Decoder()
        self._encoder = msgspec.json.Encoder()

    async def _read_content(
        self, response: aiohttp.ClientResponse
    ) -> t.Union[bytes, models.HttpErrorResponse]:
        try:
            return await response.content.read()
        except Exception:
            return models.HttpErrorResponse("Failed to read response content.", response.status)

    async def _request(
        self,
        req: t.Callable[..., t.Awaitable[t.Any]],
        url: str,
        allow_http_success: bool = False,
        **kwargs: t.Any,
    ) -> t.Union[bytes, models.HttpErrorResponse]:
        response = await req(url, **kwargs)
        content = await self._read_content(response)

        if isinstance(content, models.HttpErrorResponse):
            return content

        if not response.ok or allow_http_success:
            error = self._decoder.decode(content)

            return models.HttpErrorResponse(
                error.get("message", "An unexpected error occurred while making the request."),
                response.status,
            )

        return content

    def _get_request_func(self, method: str) -> t.Callable[..., t.Awaitable[t.Any]]:
        if not hasattr(self, "_method_mapping"):
            raise RuntimeError("HttpService.start was never called, aborting...")

        return self._method_mapping[method]

    async def _init_session(self) -> None:
        self._session = aiohttp.ClientSession(
            json_serialize=lambda o: self._encoder.encode(o).decode()
        )

        self._method_mapping = {
            "GET": self._session.get,
            "POST": self._session.post,
            "PUT": self._session.put,
            "PATCH": self._session.patch,
            "DELETE": self._session.delete,
        }

    def set_api_key(self, api_key: str) -> None:
        """Sets the api key used by the http service.

        Parameters
        ----------
        api_key : str
            The new api key to use.
        """
        self._headers["x-api-key"] = api_key

    def unset_api_key(self) -> None:
        """Un-sets the current api key so it isn't sent with requests."""
        if "x-api-key" in self._headers:
            del self._headers["x-api-key"]

    def set_user_agent(self, user_agent: str) -> None:
        """Sets the user agent used by the http service.

        Parameters
        ----------
        user_agent : str
            The new user agent to use.
        """
        self._headers["x-user-agent"] = user_agent
        self._headers["User-Agent"] = user_agent

    def set_base_url(self, base_url: str) -> None:
        """Sets the api base url used by the http service.

        Parameters
        ----------
        base_url : str
            The new base url to use.
        """
        self._base_url = base_url

    async def start(self) -> None:
        """Starts the client session to be used by the http service."""
        if not hasattr(self, "_session"):
            await self._init_session()

    async def close(self) -> None:
        """Closes the existing client session, if it's still open."""
        if hasattr(self, "_session") and not self._session.closed:
            await self._session.close()

    async def fetch(
        self,
        route: routes.CompiledRoute,
        *,
        payload: t.Optional[t.Dict[str, t.Any]] = None,
        allow_http_success: bool = False,
    ) -> bytes | models.HttpErrorResponse:
        """Fetches the given route.

        Parameters
        ----------
        route : routes.CompiledRoute
            The route to make the request to.
        payload : dict[str, Any], optional
            The optional payload to send in the request
            body.
        allow_http_success : bool
            Whether or not the caller is planning
            to return http success.

        Returns
        -------
        bytes | HttpErrorResponse
            The requested bytes or the error response.
        """
        return await self._request(
            self._get_request_func(route.method),
            self._base_url + route.uri,
            allow_http_success,
            headers=self._headers,
            params=route.params,
            json=payload or None,
        )

close async

close() -> None

Closes the existing client session, if it's still open.

Source code in wom/services/http.py
async def close(self) -> None:
    """Closes the existing client session, if it's still open."""
    if hasattr(self, "_session") and not self._session.closed:
        await self._session.close()

fetch async

fetch(
    route: routes.CompiledRoute,
    *,
    payload: t.Optional[t.Dict[str, t.Any]] = None,
    allow_http_success: bool = False
) -> bytes | models.HttpErrorResponse

Fetches the given route.

Parameters:

Name Type Description Default
route CompiledRoute

The route to make the request to.

required
payload dict[str, Any]

The optional payload to send in the request body.

None
allow_http_success bool

Whether or not the caller is planning to return http success.

False

Returns:

Type Description
bytes | HttpErrorResponse

The requested bytes or the error response.

Source code in wom/services/http.py
async def fetch(
    self,
    route: routes.CompiledRoute,
    *,
    payload: t.Optional[t.Dict[str, t.Any]] = None,
    allow_http_success: bool = False,
) -> bytes | models.HttpErrorResponse:
    """Fetches the given route.

    Parameters
    ----------
    route : routes.CompiledRoute
        The route to make the request to.
    payload : dict[str, Any], optional
        The optional payload to send in the request
        body.
    allow_http_success : bool
        Whether or not the caller is planning
        to return http success.

    Returns
    -------
    bytes | HttpErrorResponse
        The requested bytes or the error response.
    """
    return await self._request(
        self._get_request_func(route.method),
        self._base_url + route.uri,
        allow_http_success,
        headers=self._headers,
        params=route.params,
        json=payload or None,
    )

set_api_key

set_api_key(api_key: str) -> None

Sets the api key used by the http service.

Parameters:

Name Type Description Default
api_key str

The new api key to use.

required
Source code in wom/services/http.py
def set_api_key(self, api_key: str) -> None:
    """Sets the api key used by the http service.

    Parameters
    ----------
    api_key : str
        The new api key to use.
    """
    self._headers["x-api-key"] = api_key

set_base_url

set_base_url(base_url: str) -> None

Sets the api base url used by the http service.

Parameters:

Name Type Description Default
base_url str

The new base url to use.

required
Source code in wom/services/http.py
def set_base_url(self, base_url: str) -> None:
    """Sets the api base url used by the http service.

    Parameters
    ----------
    base_url : str
        The new base url to use.
    """
    self._base_url = base_url

set_user_agent

set_user_agent(user_agent: str) -> None

Sets the user agent used by the http service.

Parameters:

Name Type Description Default
user_agent str

The new user agent to use.

required
Source code in wom/services/http.py
def set_user_agent(self, user_agent: str) -> None:
    """Sets the user agent used by the http service.

    Parameters
    ----------
    user_agent : str
        The new user agent to use.
    """
    self._headers["x-user-agent"] = user_agent
    self._headers["User-Agent"] = user_agent

start async

start() -> None

Starts the client session to be used by the http service.

Source code in wom/services/http.py
async def start(self) -> None:
    """Starts the client session to be used by the http service."""
    if not hasattr(self, "_session"):
        await self._init_session()

unset_api_key

unset_api_key() -> None

Un-sets the current api key so it isn't sent with requests.

Source code in wom/services/http.py
def unset_api_key(self) -> None:
    """Un-sets the current api key so it isn't sent with requests."""
    if "x-api-key" in self._headers:
        del self._headers["x-api-key"]

NameChangeService

Bases: BaseService

Handles endpoints related to name changes.

Source code in wom/services/names.py
class NameChangeService(BaseService):
    """Handles endpoints related to name changes."""

    __slots__ = ()

    async def search_name_changes(
        self,
        username: t.Optional[str] = None,
        *,
        status: t.Optional[models.NameChangeStatus] = None,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.NameChange]]:
        """Searches for name changes.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.names.search_name_changes(
                "Jonxslays", limit=1
            )
            ```

        Parameters
        ----------
        username : str, optional
            The optional username to search for.
        status : NameChangeStatus, optional
            The optional name change status to filter on.
            Defaults to `None`.
        limit : int, optional
            The optional maximum items to return on this page
            from the API. Defaults to `None`.
        offset : int, optional
            The optional page offset. Defaults to
            `None`.

        Returns
        -------
        Result
            A result containing a list of name changes.
        """
        params = self._generate_map(username=username, status=status, limit=limit, offset=offset)
        route = routes.SEARCH_NAME_CHANGES.compile().with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.NameChange])

    async def submit_name_change(self, old_name: str, new_name: str) -> ResultT[models.NameChange]:
        """Submits a new name change.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.names.submit_name_change(
                "Jonxslays", "I Mahatma I"
            )
            ```

        Parameters
        ----------
        old_name : str
            The old name for the player.
        new_name : str
            The new name for the player.

        Returns
        -------
        Result
            A result containing the name change.
        """
        payload = self._generate_map(oldName=old_name, newName=new_name)
        route = routes.SUBMIT_NAME_CHANGE.compile()
        data = await self._http.fetch(route, payload=payload)
        return self._ok_or_err(data, models.NameChange)

search_name_changes async

search_name_changes(
    username: t.Optional[str] = None,
    *,
    status: t.Optional[models.NameChangeStatus] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.NameChange]]

Searches for name changes.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.names.search_name_changes(
    "Jonxslays", limit=1
)

Parameters:

Name Type Description Default
username str

The optional username to search for.

None
status NameChangeStatus

The optional name change status to filter on. Defaults to None.

None
limit int

The optional maximum items to return on this page from the API. Defaults to None.

None
offset int

The optional page offset. Defaults to None.

None

Returns:

Type Description
Result

A result containing a list of name changes.

Source code in wom/services/names.py
async def search_name_changes(
    self,
    username: t.Optional[str] = None,
    *,
    status: t.Optional[models.NameChangeStatus] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.NameChange]]:
    """Searches for name changes.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.names.search_name_changes(
            "Jonxslays", limit=1
        )
        ```

    Parameters
    ----------
    username : str, optional
        The optional username to search for.
    status : NameChangeStatus, optional
        The optional name change status to filter on.
        Defaults to `None`.
    limit : int, optional
        The optional maximum items to return on this page
        from the API. Defaults to `None`.
    offset : int, optional
        The optional page offset. Defaults to
        `None`.

    Returns
    -------
    Result
        A result containing a list of name changes.
    """
    params = self._generate_map(username=username, status=status, limit=limit, offset=offset)
    route = routes.SEARCH_NAME_CHANGES.compile().with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.NameChange])

submit_name_change async

submit_name_change(
    old_name: str, new_name: str
) -> ResultT[models.NameChange]

Submits a new name change.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.names.submit_name_change(
    "Jonxslays", "I Mahatma I"
)

Parameters:

Name Type Description Default
old_name str

The old name for the player.

required
new_name str

The new name for the player.

required

Returns:

Type Description
Result

A result containing the name change.

Source code in wom/services/names.py
async def submit_name_change(self, old_name: str, new_name: str) -> ResultT[models.NameChange]:
    """Submits a new name change.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.names.submit_name_change(
            "Jonxslays", "I Mahatma I"
        )
        ```

    Parameters
    ----------
    old_name : str
        The old name for the player.
    new_name : str
        The new name for the player.

    Returns
    -------
    Result
        A result containing the name change.
    """
    payload = self._generate_map(oldName=old_name, newName=new_name)
    route = routes.SUBMIT_NAME_CHANGE.compile()
    data = await self._http.fetch(route, payload=payload)
    return self._ok_or_err(data, models.NameChange)

PlayerService

Bases: BaseService

Handles endpoints related to players.

Source code in wom/services/players.py
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
class PlayerService(BaseService):
    """Handles endpoints related to players."""

    __slots__ = ()

    async def search_players(
        self, username: str, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
    ) -> ResultT[t.List[models.Player]]:
        """Searches for a player by partial username.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.search_players("Jonxslays", limit=3)
            ```

        Parameters
        ----------
        username : str
            The username to search for.
        limit : int, optional
            The maximum number of paginated items to receive.
            Defaults to `None`.
        offset : int, optional
            The page offset for requesting the next page.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of matching
            players.
        """
        params = self._generate_map(username=username, limit=limit, offset=offset)
        route = routes.SEARCH_PLAYERS.compile().with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Player])

    async def update_player(self, username: str) -> ResultT[models.PlayerDetail]:
        """Updates the given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.update_player("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to update.

        Returns
        -------
        Result
            A result containing the updated player
            details.
        """
        route = routes.UPDATE_PLAYER.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.PlayerDetail)

    async def assert_player_type(self, username: str) -> ResultT[models.AssertPlayerType]:
        """Asserts, and fixes, a players type.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.assert_player_type("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to assert the type for.

        Returns
        -------
        Result
            A result containing the asserted player
            type.
        """
        route = routes.ASSERT_PLAYER_TYPE.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.AssertPlayerType)

    async def get_details(self, username: str) -> ResultT[models.PlayerDetail]:
        """Gets the details for a given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_details("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to get the details for.

        Returns
        -------
        Result
            A result containing the player details.
        """
        route = routes.PLAYER_DETAILS.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.PlayerDetail)

    async def get_details_by_id(self, player_id: int) -> ResultT[models.PlayerDetail]:
        """Gets the details for a given player id.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_details_by_id(1234)
            ```

        Parameters
        ----------
        player_id : int
            The is of the player to get the details for.

        Returns
        -------
        Result
            A result containing the player details.
        """
        route = routes.PLAYER_DETAILS_BY_ID.compile(player_id)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.PlayerDetail)

    async def get_achievements(self, username: str) -> ResultT[t.List[models.Achievement]]:
        """Gets the achievements for a given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_achievements("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to get the achievements for.

        Returns
        -------
        Result
            A result containing the list of player
            achievements.
        """
        route = routes.PLAYER_ACHIEVEMENTS.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Achievement])

    async def get_achievement_progress(
        self, username: str
    ) -> ResultT[t.List[models.PlayerAchievementProgress]]:
        """Gets the progress towards achievements for a given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_achievement_progress("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to get the achievement progress for.

        Returns
        -------
        Result
            A result containing the list of player
            achievement progress.
        """
        route = routes.PLAYER_ACHIEVEMENT_PROGRESS.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.PlayerAchievementProgress])

    async def get_competition_participations(
        self,
        username: str,
        *,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
        status: t.Optional[models.CompetitionStatus] = None,
    ) -> ResultT[t.List[models.PlayerParticipation]]:
        """Gets the competition participations for a given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_competition_participations(
                "Jonxslays", limit=3
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the participations for.
        limit : int, optional
            The maximum number of paginated items to receive.
            Defaults to `None` (I think thats 20 items?).
        offset : int, optional
            The page offset for requesting multiple pages.
            Defaults to `None`.
        status : CompetitionStatus, optional
            The optional competition status to filter on. Defaults to
            `None`.

        Returns
        -------
        Result
            A result containing the list of competition
            participations.
        """
        params = self._generate_map(
            status=status.value if status else None,
            offset=offset,
            limit=limit,
        )

        route = routes.PLAYER_COMPETITION_PARTICIPATION.compile(username)
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.PlayerParticipation])

    async def get_competition_standings(
        self,
        username: str,
        status: models.CompetitionStatus,
    ) -> ResultT[t.List[models.PlayerCompetitionStanding]]:
        """Gets the competition standings for a given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_competition_standings(
                "Jonxslays", wom.CompetitionStatus.Ongoing
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the standings for.
        status : CompetitionStatus
            The competition status to get standings for.

        Returns
        -------
        Result
            A result containing the list of competition
            standings.
        """
        params = self._generate_map(status=status.value)
        route = routes.PLAYER_COMPETITION_STANDINGS.compile(username)
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.PlayerCompetitionStanding])

    async def get_group_memberships(
        self, username: str, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
    ) -> ResultT[t.List[models.PlayerMembership]]:
        """Gets the group memberships for the given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_group_memberships(
                "Jonxslays", limit=3
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the memberships for.
        limit : int, optional
            The maximum number of paginated items to receive.
            Defaults to `None` (I think thats 20 items?).
        offset : int, optional
            The page offset for requesting multiple pages.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of group
            memberships.
        """
        params = self._generate_map(limit=limit, offset=offset)
        route = routes.PLAYER_GROUP_MEMBERSHIPS.compile(username)
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.PlayerMembership])

    async def get_gains(
        self,
        username: str,
        *,
        period: t.Optional[enums.Period] = None,
        start_date: t.Optional[datetime] = None,
        end_date: t.Optional[datetime] = None,
    ) -> ResultT[models.PlayerGains]:
        """Gets the gains made by this player over the given time span.

        !!! info

            You must pass one of (`period`) or (`start_date` +
            `end_date`), but not both.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_gains(
                "Jonxslays", period=wom.Period.Day
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the gains for.
        period : Period, optional
            The optional period of time to get gains for.
            Defaults to `None`.
        start_date : datetime, optional
            The minimum date to get the gains from. Defaults
            to `None`.
        end_date : datetime, optional
            The maximum date to get the gains from. Defaults
            to `None`.

        Returns
        -------
        Result
            A result containing the players gains.
        """
        params = self._generate_map(
            period=period.value if period else None,
            startDate=start_date.isoformat() if start_date else None,
            endDate=end_date.isoformat() if end_date else None,
        )

        route = routes.PLAYER_GAINS.compile(username).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, models.PlayerGains)

    async def get_records(
        self,
        username: str,
        *,
        period: t.Optional[enums.Period] = None,
        metric: t.Optional[enums.Metric] = None,
    ) -> ResultT[t.List[models.Record]]:
        """Gets the records held by this player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_records(
                "Jonxslays", period=wom.Period.Day, metric=wom.Metric.Attack
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the gains for.
        period : Period, optional
            The optional period of time to get records for.
            Defaults to `None`.
        metric : Metric, optional
            The optional metric to filter the records on.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing a list of the players
            records.
        """
        params = self._generate_map(
            period=period.value if period else None, metric=metric.value if metric else None
        )

        route = routes.PLAYER_RECORDS.compile(username).with_params(params)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.Record])

    async def get_snapshots(
        self,
        username: str,
        *,
        period: t.Optional[enums.Period] = None,
        start_date: t.Optional[datetime] = None,
        end_date: t.Optional[datetime] = None,
        limit: t.Optional[int] = None,
        offset: t.Optional[int] = None,
    ) -> ResultT[t.List[models.Snapshot]]:
        """Gets the snapshots for the player.

        !!! info

            You can pass either (`period`) or (`start_date` +
            `end_date`), but not both.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_snapshots(
                "Jonxslays", period=wom.Period.Week, limit=3
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the snapshots for.
        period : Period, optional
            The optional period of time to get snapshots for.
            Defaults to `None`.
        start_date : datetime, optional
            The minimum date to get the snapshots from.
            Defaults to `None`.
        end_date : datetime, optional
            The maximum date to get the snapshots from.
            Defaults to `None`.
        limit : int, optional
            The maximum number of paginated items to receive.
            Defaults to `None`.
        offset : int, optional
            The page offset for requesting the next page.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of snapshots.
        """
        params = self._generate_map(
            period=period.value if period else None,
            startDate=start_date.isoformat() if start_date else None,
            endDate=end_date.isoformat() if end_date else None,
            limit=limit if limit else None,
            offset=offset if offset else None,
        )

        route = routes.PLAYER_SNAPSHOTS.compile(username)
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.Snapshot])

    async def get_name_changes(self, username: str) -> ResultT[t.List[models.NameChange]]:
        """Gets the name changes for the player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_name_changes("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to get the name changes for.

        Returns
        -------
        Result
            A result containing the list of name changes.
        """
        route = routes.PLAYER_NAME_CHANGES.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.NameChange])

    async def get_snapshots_timeline(
        self,
        username: str,
        metric: enums.Metric,
        *,
        period: t.Optional[enums.Period] = None,
        start_date: t.Optional[datetime] = None,
        end_date: t.Optional[datetime] = None,
    ) -> ResultT[t.List[models.SnapshotTimelineEntry]]:
        """Gets the snapshots timeline for the given player and metric.

        !!! info

            You can pass either (`period`) or (`start_date` +
            `end_date`), but not both.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_snapshots_timeline(
                "Jonxslays", wom.Skills.Attack, period=wom.Period.Week
            )
            ```

        Parameters
        ----------
        username : str
            The username to get the timeline for.
        metric : Metric
            The metric to get the timeline for.
        period : Period, optional
            The optional period of time to get snapshots for.
            Defaults to `None`.
        start_date : datetime, optional
            The minimum date to get the snapshots from.
            Defaults to `None`.
        end_date : datetime, optional
            The maximum date to get the snapshots from.
            Defaults to `None`.

        Returns
        -------
        Result
            A result containing the list of snapshots timeline
            entries.
        """
        params = self._generate_map(
            period=period.value if period else None,
            startDate=start_date.isoformat() if start_date else None,
            endDate=end_date.isoformat() if end_date else None,
            metric=metric.value,
        )

        route = routes.PLAYER_SNAPSHOTS_TIMELINE.compile(username)
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.SnapshotTimelineEntry])

    async def get_archives(
        self,
        username: str,
    ) -> ResultT[t.List[models.PlayerArchive]]:
        """Gets the archives for the given player.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.players.get_archives("Jonxslays")
            ```

        Parameters
        ----------
        username : str
            The username to get archives for.

        Returns
        -------
        Result
            A result containing the list of archives.
        """
        route = routes.PLAYER_ARCHIVES.compile(username)
        data = await self._http.fetch(route)
        return self._ok_or_err(data, t.List[models.PlayerArchive])

assert_player_type async

assert_player_type(
    username: str,
) -> ResultT[models.AssertPlayerType]

Asserts, and fixes, a players type.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.assert_player_type("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to assert the type for.

required

Returns:

Type Description
Result

A result containing the asserted player type.

Source code in wom/services/players.py
async def assert_player_type(self, username: str) -> ResultT[models.AssertPlayerType]:
    """Asserts, and fixes, a players type.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.assert_player_type("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to assert the type for.

    Returns
    -------
    Result
        A result containing the asserted player
        type.
    """
    route = routes.ASSERT_PLAYER_TYPE.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.AssertPlayerType)

get_achievement_progress async

get_achievement_progress(
    username: str,
) -> ResultT[t.List[models.PlayerAchievementProgress]]

Gets the progress towards achievements for a given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_achievement_progress("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to get the achievement progress for.

required

Returns:

Type Description
Result

A result containing the list of player achievement progress.

Source code in wom/services/players.py
async def get_achievement_progress(
    self, username: str
) -> ResultT[t.List[models.PlayerAchievementProgress]]:
    """Gets the progress towards achievements for a given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_achievement_progress("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to get the achievement progress for.

    Returns
    -------
    Result
        A result containing the list of player
        achievement progress.
    """
    route = routes.PLAYER_ACHIEVEMENT_PROGRESS.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.PlayerAchievementProgress])

get_achievements async

get_achievements(
    username: str,
) -> ResultT[t.List[models.Achievement]]

Gets the achievements for a given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_achievements("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to get the achievements for.

required

Returns:

Type Description
Result

A result containing the list of player achievements.

Source code in wom/services/players.py
async def get_achievements(self, username: str) -> ResultT[t.List[models.Achievement]]:
    """Gets the achievements for a given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_achievements("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to get the achievements for.

    Returns
    -------
    Result
        A result containing the list of player
        achievements.
    """
    route = routes.PLAYER_ACHIEVEMENTS.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Achievement])

get_archives async

get_archives(
    username: str,
) -> ResultT[t.List[models.PlayerArchive]]

Gets the archives for the given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_archives("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to get archives for.

required

Returns:

Type Description
Result

A result containing the list of archives.

Source code in wom/services/players.py
async def get_archives(
    self,
    username: str,
) -> ResultT[t.List[models.PlayerArchive]]:
    """Gets the archives for the given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_archives("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to get archives for.

    Returns
    -------
    Result
        A result containing the list of archives.
    """
    route = routes.PLAYER_ARCHIVES.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.PlayerArchive])

get_competition_participations async

get_competition_participations(
    username: str,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
    status: t.Optional[models.CompetitionStatus] = None
) -> ResultT[t.List[models.PlayerParticipation]]

Gets the competition participations for a given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_competition_participations(
    "Jonxslays", limit=3
)

Parameters:

Name Type Description Default
username str

The username to get the participations for.

required
limit int

The maximum number of paginated items to receive. Defaults to None (I think thats 20 items?).

None
offset int

The page offset for requesting multiple pages. Defaults to None.

None
status CompetitionStatus

The optional competition status to filter on. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of competition participations.

Source code in wom/services/players.py
async def get_competition_participations(
    self,
    username: str,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
    status: t.Optional[models.CompetitionStatus] = None,
) -> ResultT[t.List[models.PlayerParticipation]]:
    """Gets the competition participations for a given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_competition_participations(
            "Jonxslays", limit=3
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the participations for.
    limit : int, optional
        The maximum number of paginated items to receive.
        Defaults to `None` (I think thats 20 items?).
    offset : int, optional
        The page offset for requesting multiple pages.
        Defaults to `None`.
    status : CompetitionStatus, optional
        The optional competition status to filter on. Defaults to
        `None`.

    Returns
    -------
    Result
        A result containing the list of competition
        participations.
    """
    params = self._generate_map(
        status=status.value if status else None,
        offset=offset,
        limit=limit,
    )

    route = routes.PLAYER_COMPETITION_PARTICIPATION.compile(username)
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.PlayerParticipation])

get_competition_standings async

get_competition_standings(
    username: str, status: models.CompetitionStatus
) -> ResultT[t.List[models.PlayerCompetitionStanding]]

Gets the competition standings for a given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_competition_standings(
    "Jonxslays", wom.CompetitionStatus.Ongoing
)

Parameters:

Name Type Description Default
username str

The username to get the standings for.

required
status CompetitionStatus

The competition status to get standings for.

required

Returns:

Type Description
Result

A result containing the list of competition standings.

Source code in wom/services/players.py
async def get_competition_standings(
    self,
    username: str,
    status: models.CompetitionStatus,
) -> ResultT[t.List[models.PlayerCompetitionStanding]]:
    """Gets the competition standings for a given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_competition_standings(
            "Jonxslays", wom.CompetitionStatus.Ongoing
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the standings for.
    status : CompetitionStatus
        The competition status to get standings for.

    Returns
    -------
    Result
        A result containing the list of competition
        standings.
    """
    params = self._generate_map(status=status.value)
    route = routes.PLAYER_COMPETITION_STANDINGS.compile(username)
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.PlayerCompetitionStanding])

get_details async

get_details(username: str) -> ResultT[models.PlayerDetail]

Gets the details for a given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_details("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to get the details for.

required

Returns:

Type Description
Result

A result containing the player details.

Source code in wom/services/players.py
async def get_details(self, username: str) -> ResultT[models.PlayerDetail]:
    """Gets the details for a given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_details("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to get the details for.

    Returns
    -------
    Result
        A result containing the player details.
    """
    route = routes.PLAYER_DETAILS.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.PlayerDetail)

get_details_by_id async

get_details_by_id(
    player_id: int,
) -> ResultT[models.PlayerDetail]

Gets the details for a given player id.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_details_by_id(1234)

Parameters:

Name Type Description Default
player_id int

The is of the player to get the details for.

required

Returns:

Type Description
Result

A result containing the player details.

Source code in wom/services/players.py
async def get_details_by_id(self, player_id: int) -> ResultT[models.PlayerDetail]:
    """Gets the details for a given player id.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_details_by_id(1234)
        ```

    Parameters
    ----------
    player_id : int
        The is of the player to get the details for.

    Returns
    -------
    Result
        A result containing the player details.
    """
    route = routes.PLAYER_DETAILS_BY_ID.compile(player_id)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.PlayerDetail)

get_gains async

get_gains(
    username: str,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None
) -> ResultT[models.PlayerGains]

Gets the gains made by this player over the given time span.

Info

You must pass one of (period) or (start_date + end_date), but not both.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_gains(
    "Jonxslays", period=wom.Period.Day
)

Parameters:

Name Type Description Default
username str

The username to get the gains for.

required
period Period

The optional period of time to get gains for. Defaults to None.

None
start_date datetime

The minimum date to get the gains from. Defaults to None.

None
end_date datetime

The maximum date to get the gains from. Defaults to None.

None

Returns:

Type Description
Result

A result containing the players gains.

Source code in wom/services/players.py
async def get_gains(
    self,
    username: str,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
) -> ResultT[models.PlayerGains]:
    """Gets the gains made by this player over the given time span.

    !!! info

        You must pass one of (`period`) or (`start_date` +
        `end_date`), but not both.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_gains(
            "Jonxslays", period=wom.Period.Day
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the gains for.
    period : Period, optional
        The optional period of time to get gains for.
        Defaults to `None`.
    start_date : datetime, optional
        The minimum date to get the gains from. Defaults
        to `None`.
    end_date : datetime, optional
        The maximum date to get the gains from. Defaults
        to `None`.

    Returns
    -------
    Result
        A result containing the players gains.
    """
    params = self._generate_map(
        period=period.value if period else None,
        startDate=start_date.isoformat() if start_date else None,
        endDate=end_date.isoformat() if end_date else None,
    )

    route = routes.PLAYER_GAINS.compile(username).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.PlayerGains)

get_group_memberships async

get_group_memberships(
    username: str,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.PlayerMembership]]

Gets the group memberships for the given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_group_memberships(
    "Jonxslays", limit=3
)

Parameters:

Name Type Description Default
username str

The username to get the memberships for.

required
limit int

The maximum number of paginated items to receive. Defaults to None (I think thats 20 items?).

None
offset int

The page offset for requesting multiple pages. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of group memberships.

Source code in wom/services/players.py
async def get_group_memberships(
    self, username: str, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
) -> ResultT[t.List[models.PlayerMembership]]:
    """Gets the group memberships for the given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_group_memberships(
            "Jonxslays", limit=3
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the memberships for.
    limit : int, optional
        The maximum number of paginated items to receive.
        Defaults to `None` (I think thats 20 items?).
    offset : int, optional
        The page offset for requesting multiple pages.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of group
        memberships.
    """
    params = self._generate_map(limit=limit, offset=offset)
    route = routes.PLAYER_GROUP_MEMBERSHIPS.compile(username)
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.PlayerMembership])

get_name_changes async

get_name_changes(
    username: str,
) -> ResultT[t.List[models.NameChange]]

Gets the name changes for the player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_name_changes("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to get the name changes for.

required

Returns:

Type Description
Result

A result containing the list of name changes.

Source code in wom/services/players.py
async def get_name_changes(self, username: str) -> ResultT[t.List[models.NameChange]]:
    """Gets the name changes for the player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_name_changes("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to get the name changes for.

    Returns
    -------
    Result
        A result containing the list of name changes.
    """
    route = routes.PLAYER_NAME_CHANGES.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.NameChange])

get_records async

get_records(
    username: str,
    *,
    period: t.Optional[enums.Period] = None,
    metric: t.Optional[enums.Metric] = None
) -> ResultT[t.List[models.Record]]

Gets the records held by this player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_records(
    "Jonxslays", period=wom.Period.Day, metric=wom.Metric.Attack
)

Parameters:

Name Type Description Default
username str

The username to get the gains for.

required
period Period

The optional period of time to get records for. Defaults to None.

None
metric Metric

The optional metric to filter the records on. Defaults to None.

None

Returns:

Type Description
Result

A result containing a list of the players records.

Source code in wom/services/players.py
async def get_records(
    self,
    username: str,
    *,
    period: t.Optional[enums.Period] = None,
    metric: t.Optional[enums.Metric] = None,
) -> ResultT[t.List[models.Record]]:
    """Gets the records held by this player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_records(
            "Jonxslays", period=wom.Period.Day, metric=wom.Metric.Attack
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the gains for.
    period : Period, optional
        The optional period of time to get records for.
        Defaults to `None`.
    metric : Metric, optional
        The optional metric to filter the records on.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing a list of the players
        records.
    """
    params = self._generate_map(
        period=period.value if period else None, metric=metric.value if metric else None
    )

    route = routes.PLAYER_RECORDS.compile(username).with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Record])

get_snapshots async

get_snapshots(
    username: str,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.Snapshot]]

Gets the snapshots for the player.

Info

You can pass either (period) or (start_date + end_date), but not both.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_snapshots(
    "Jonxslays", period=wom.Period.Week, limit=3
)

Parameters:

Name Type Description Default
username str

The username to get the snapshots for.

required
period Period

The optional period of time to get snapshots for. Defaults to None.

None
start_date datetime

The minimum date to get the snapshots from. Defaults to None.

None
end_date datetime

The maximum date to get the snapshots from. Defaults to None.

None
limit int

The maximum number of paginated items to receive. Defaults to None.

None
offset int

The page offset for requesting the next page. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of snapshots.

Source code in wom/services/players.py
async def get_snapshots(
    self,
    username: str,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None,
) -> ResultT[t.List[models.Snapshot]]:
    """Gets the snapshots for the player.

    !!! info

        You can pass either (`period`) or (`start_date` +
        `end_date`), but not both.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_snapshots(
            "Jonxslays", period=wom.Period.Week, limit=3
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the snapshots for.
    period : Period, optional
        The optional period of time to get snapshots for.
        Defaults to `None`.
    start_date : datetime, optional
        The minimum date to get the snapshots from.
        Defaults to `None`.
    end_date : datetime, optional
        The maximum date to get the snapshots from.
        Defaults to `None`.
    limit : int, optional
        The maximum number of paginated items to receive.
        Defaults to `None`.
    offset : int, optional
        The page offset for requesting the next page.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of snapshots.
    """
    params = self._generate_map(
        period=period.value if period else None,
        startDate=start_date.isoformat() if start_date else None,
        endDate=end_date.isoformat() if end_date else None,
        limit=limit if limit else None,
        offset=offset if offset else None,
    )

    route = routes.PLAYER_SNAPSHOTS.compile(username)
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.Snapshot])

get_snapshots_timeline async

get_snapshots_timeline(
    username: str,
    metric: enums.Metric,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None
) -> ResultT[t.List[models.SnapshotTimelineEntry]]

Gets the snapshots timeline for the given player and metric.

Info

You can pass either (period) or (start_date + end_date), but not both.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.get_snapshots_timeline(
    "Jonxslays", wom.Skills.Attack, period=wom.Period.Week
)

Parameters:

Name Type Description Default
username str

The username to get the timeline for.

required
metric Metric

The metric to get the timeline for.

required
period Period

The optional period of time to get snapshots for. Defaults to None.

None
start_date datetime

The minimum date to get the snapshots from. Defaults to None.

None
end_date datetime

The maximum date to get the snapshots from. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of snapshots timeline entries.

Source code in wom/services/players.py
async def get_snapshots_timeline(
    self,
    username: str,
    metric: enums.Metric,
    *,
    period: t.Optional[enums.Period] = None,
    start_date: t.Optional[datetime] = None,
    end_date: t.Optional[datetime] = None,
) -> ResultT[t.List[models.SnapshotTimelineEntry]]:
    """Gets the snapshots timeline for the given player and metric.

    !!! info

        You can pass either (`period`) or (`start_date` +
        `end_date`), but not both.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.get_snapshots_timeline(
            "Jonxslays", wom.Skills.Attack, period=wom.Period.Week
        )
        ```

    Parameters
    ----------
    username : str
        The username to get the timeline for.
    metric : Metric
        The metric to get the timeline for.
    period : Period, optional
        The optional period of time to get snapshots for.
        Defaults to `None`.
    start_date : datetime, optional
        The minimum date to get the snapshots from.
        Defaults to `None`.
    end_date : datetime, optional
        The maximum date to get the snapshots from.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of snapshots timeline
        entries.
    """
    params = self._generate_map(
        period=period.value if period else None,
        startDate=start_date.isoformat() if start_date else None,
        endDate=end_date.isoformat() if end_date else None,
        metric=metric.value,
    )

    route = routes.PLAYER_SNAPSHOTS_TIMELINE.compile(username)
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.SnapshotTimelineEntry])

search_players async

search_players(
    username: str,
    *,
    limit: t.Optional[int] = None,
    offset: t.Optional[int] = None
) -> ResultT[t.List[models.Player]]

Searches for a player by partial username.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.search_players("Jonxslays", limit=3)

Parameters:

Name Type Description Default
username str

The username to search for.

required
limit int

The maximum number of paginated items to receive. Defaults to None.

None
offset int

The page offset for requesting the next page. Defaults to None.

None

Returns:

Type Description
Result

A result containing the list of matching players.

Source code in wom/services/players.py
async def search_players(
    self, username: str, *, limit: t.Optional[int] = None, offset: t.Optional[int] = None
) -> ResultT[t.List[models.Player]]:
    """Searches for a player by partial username.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.search_players("Jonxslays", limit=3)
        ```

    Parameters
    ----------
    username : str
        The username to search for.
    limit : int, optional
        The maximum number of paginated items to receive.
        Defaults to `None`.
    offset : int, optional
        The page offset for requesting the next page.
        Defaults to `None`.

    Returns
    -------
    Result
        A result containing the list of matching
        players.
    """
    params = self._generate_map(username=username, limit=limit, offset=offset)
    route = routes.SEARCH_PLAYERS.compile().with_params(params)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, t.List[models.Player])

update_player async

update_player(
    username: str,
) -> ResultT[models.PlayerDetail]

Updates the given player.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.players.update_player("Jonxslays")

Parameters:

Name Type Description Default
username str

The username to update.

required

Returns:

Type Description
Result

A result containing the updated player details.

Source code in wom/services/players.py
async def update_player(self, username: str) -> ResultT[models.PlayerDetail]:
    """Updates the given player.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.players.update_player("Jonxslays")
        ```

    Parameters
    ----------
    username : str
        The username to update.

    Returns
    -------
    Result
        A result containing the updated player
        details.
    """
    route = routes.UPDATE_PLAYER.compile(username)
    data = await self._http.fetch(route)
    return self._ok_or_err(data, models.PlayerDetail)

RecordService

Bases: BaseService

Handles endpoints related to records.

Source code in wom/services/records.py
class RecordService(BaseService):
    """Handles endpoints related to records."""

    __slots__ = ()

    async def get_global_leaderboards(
        self,
        metric: enums.Metric,
        period: enums.Period,
        *,
        player_type: t.Optional[models.PlayerType] = None,
        player_build: t.Optional[models.PlayerBuild] = None,
        country: t.Optional[models.Country] = None,
    ) -> ResultT[t.List[models.RecordLeaderboardEntry]]:
        """Gets the global record leaderboards.

        ??? example

            ```py
            import wom

            client = wom.Client(...)

            await client.start()

            result = await client.records.get_global_leaderboards(
                wom.Metric.Attack,
                wom.Period.Day,
                country=wom.Country.Us,
            )
            ```

        Parameters
        ----------
        metric : Metric
            The metric to filter on.
        period : Period
            The period of time to filter on.
        player_type : PlayerType, optional
            The optional player type to filter on. Defaults
            to `None`.
        player_build : PlayerBuild, optional
            The optional player build to filter on.
            Defaults to `None`.
        country : Country, optional
            The optional country to filter on. Defaults to
            `None`.

        Returns
        -------
        Result
            A result containing a list of record
            leaderboard entries.
        """
        params = self._generate_map(
            metric=metric.value,
            period=period.value,
            playerType=player_type.value if player_type else None,
            playerBuild=player_build.value if player_build else None,
            country=country.value if country else None,
        )

        route = routes.GLOBAL_RECORD_LEADERS.compile()
        data = await self._http.fetch(route.with_params(params))
        return self._ok_or_err(data, t.List[models.RecordLeaderboardEntry])

get_global_leaderboards async

get_global_leaderboards(
    metric: enums.Metric,
    period: enums.Period,
    *,
    player_type: t.Optional[models.PlayerType] = None,
    player_build: t.Optional[models.PlayerBuild] = None,
    country: t.Optional[models.Country] = None
) -> ResultT[t.List[models.RecordLeaderboardEntry]]

Gets the global record leaderboards.

Example
import wom

client = wom.Client(...)

await client.start()

result = await client.records.get_global_leaderboards(
    wom.Metric.Attack,
    wom.Period.Day,
    country=wom.Country.Us,
)

Parameters:

Name Type Description Default
metric Metric

The metric to filter on.

required
period Period

The period of time to filter on.

required
player_type PlayerType

The optional player type to filter on. Defaults to None.

None
player_build PlayerBuild

The optional player build to filter on. Defaults to None.

None
country Country

The optional country to filter on. Defaults to None.

None

Returns:

Type Description
Result

A result containing a list of record leaderboard entries.

Source code in wom/services/records.py
async def get_global_leaderboards(
    self,
    metric: enums.Metric,
    period: enums.Period,
    *,
    player_type: t.Optional[models.PlayerType] = None,
    player_build: t.Optional[models.PlayerBuild] = None,
    country: t.Optional[models.Country] = None,
) -> ResultT[t.List[models.RecordLeaderboardEntry]]:
    """Gets the global record leaderboards.

    ??? example

        ```py
        import wom

        client = wom.Client(...)

        await client.start()

        result = await client.records.get_global_leaderboards(
            wom.Metric.Attack,
            wom.Period.Day,
            country=wom.Country.Us,
        )
        ```

    Parameters
    ----------
    metric : Metric
        The metric to filter on.
    period : Period
        The period of time to filter on.
    player_type : PlayerType, optional
        The optional player type to filter on. Defaults
        to `None`.
    player_build : PlayerBuild, optional
        The optional player build to filter on.
        Defaults to `None`.
    country : Country, optional
        The optional country to filter on. Defaults to
        `None`.

    Returns
    -------
    Result
        A result containing a list of record
        leaderboard entries.
    """
    params = self._generate_map(
        metric=metric.value,
        period=period.value,
        playerType=player_type.value if player_type else None,
        playerBuild=player_build.value if player_build else None,
        country=country.value if country else None,
    )

    route = routes.GLOBAL_RECORD_LEADERS.compile()
    data = await self._http.fetch(route.with_params(params))
    return self._ok_or_err(data, t.List[models.RecordLeaderboardEntry])