Skip to content

Commit

Permalink
Add bulk pairing client (#6) and rework account client (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
Virinas-code authored Sep 2, 2023
1 parent 0f9aff7 commit 54c4450
Show file tree
Hide file tree
Showing 9 changed files with 298 additions and 13 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
Changelog
=========

Next release
------------

* Added ``client.bulk_pairings`` to create and manage bulk pairings
* ``client.bulk_pairings.get_upcoming`` to get upcoming bulk pairings you created
* ``client.bulk_pairings.create`` to create a bulk pairing
* ``client.bulk_pairings.start_clocks`` to start the clocks of a bulk pairing
* ``client.bulk_pairings.cancel`` to cancel a bulk pairing
* Added better return types for ``client.account.get`` and ``client.account.get_preferences``

Thanks to @Virinas-code for their contributions to this release.

v0.12.8 (2023-07-25)
--------------------

Expand Down
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ Most of the API is available:
client.broadcasts.get_round_pgns
client.broadcasts.get_pgns
client.bulk_pairings.get_upcoming
client.bulk_pairings.create
client.bulk_pairings.start_clocks
client.bulk_pairings.cancel
client.challenges.create
client.challenges.create_ai
client.challenges.create_open
Expand Down
4 changes: 4 additions & 0 deletions berserk/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from .tv import TV
from .tablebase import Tablebase
from .opening_explorer import OpeningExplorer
from .bulk_pairings import BulkPairings

__all__ = [
"Client",
Expand All @@ -41,6 +42,7 @@
"OAuth",
"TV",
"Tablebase",
"BulkPairings",
]


Expand All @@ -64,6 +66,7 @@ class Client(BaseClient):
- :class:`messaging <berserk.clients.Messaging>` - private message other players
- :class:`tv <berserk.clients.TV>` - get information on tv channels and games
- :class:`tablebase <berserk.clients.Tablebase>` - lookup endgame tablebase
- :class:`bulk_pairings <berserk.clients.BulkPairing>` - manage bulk pairings
:param session: request session, authenticated as needed
:param base_url: base API URL to use (if other than the default)
Expand Down Expand Up @@ -102,3 +105,4 @@ def __init__(
self.tv = TV(session, base_url)
self.tablebase = Tablebase(session, tablebase_url)
self.opening_explorer = OpeningExplorer(session, explorer_url)
self.bulk_pairings = BulkPairings(session, base_url)
15 changes: 9 additions & 6 deletions berserk/clients/account.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
from __future__ import annotations

from typing import Any, Dict
from typing import cast

from .. import models
from ..types.account import AccountInformation, Preferences
from .base import BaseClient


class Account(BaseClient):
"""Client for account-related endpoints."""

def get(self) -> Dict[str, Any]:
def get(self) -> AccountInformation:
"""Get your public information.
:return: public information about the authenticated user
"""
path = "/api/account"
return self._r.get(path, converter=models.Account.convert)
return cast(
AccountInformation, self._r.get(path, converter=models.Account.convert)
)

def get_email(self) -> str:
"""Get your email address.
Expand All @@ -25,13 +28,13 @@ def get_email(self) -> str:
path = "/api/account/email"
return self._r.get(path)["email"]

def get_preferences(self) -> Dict[str, Any]:
def get_preferences(self) -> Preferences:
"""Get your account preferences.
:return: preferences of the authenticated user
"""
path = "/api/account/preferences"
return self._r.get(path)["prefs"]
return cast(Preferences, self._r.get(path))

def get_kid_mode(self) -> bool:
"""Get your kid mode status.
Expand All @@ -41,7 +44,7 @@ def get_kid_mode(self) -> bool:
path = "/api/account/kid"
return self._r.get(path)["kid"]

def set_kid_mode(self, value: bool):
def set_kid_mode(self, value: bool) -> None:
"""Set your kid mode status.
:param bool value: whether to enable or disable kid mode
Expand Down
101 changes: 101 additions & 0 deletions berserk/clients/bulk_pairings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from __future__ import annotations

from typing import cast

from ..enums import Variant
from ..formats import JSON, JSON_LIST
from ..types.bulk_pairings import BulkPairing
from .base import BaseClient


class BulkPairings(BaseClient):
"""Client for bulk pairing related endpoints."""

def get_upcoming(self) -> list[BulkPairing]:
"""Get a list of upcoming bulk pairings you created.
Only bulk pairings that are scheduled in the future, or that have a clock start scheduled in the future, are listed.
Bulk pairings are deleted from the server after the pairings are done and the clocks have started.
:return: list of your upcoming bulk pairings.
"""
path = "/api/bulk-pairing"
return cast("list[BulkPairing]", self._r.get(path, fmt=JSON_LIST))

def create(
self,
token_pairings: list[tuple[str, str]],
clock_limit: int | None = None,
clock_increment: int | None = None,
days: int | None = None,
pair_at: int | None = None,
start_clocks_at: int | None = None,
rated: bool = False,
variant: Variant | None = None,
fen: str | None = None,
message: str | None = None,
rules: list[str] | None = None,
) -> BulkPairing:
"""Create a bulk pairing.
:param players_tokens: players OAuth tokens
:param clock_limit: clock initial time
:param clock_increment: clock increment
:param days: days per turn (for correspondence)
:param pair_at: date at which the games will be created as a milliseconds unix timestamp. Up to 7 days in the future. Defaults to now.
:param start_clocks_at: date at which the clocks will be automatically started as a Unix timestamp in milliseconds.
Up to 7 days in the future. Note that the clocks can start earlier than specified, if players start making moves in the game.
If omitted, the clocks will not start automatically.
:param rated: set to true to make the games rated. defaults to false.
:param variant: variant of the games
:param fen: custom initial position (in FEN). Only allowed if variant is standard, fromPosition, or chess960 (if a valid 960 starting position), and the games cannot be rated.
:param message: message sent to players when their game is created
:param rules: extra game rules
:return: the newly created bulk pairing
"""
path = "/api/bulk-pairing"
payload = {
"players": ",".join(":".join(pair) for pair in token_pairings),
"clock.limit": clock_limit,
"clock.increment": clock_increment,
"days": days,
"pairAt": pair_at,
"startClocksAt": start_clocks_at,
"rated": rated,
"variant": variant,
"fen": fen,
"message": message,
"rules": ",".join(rules) if rules else None,
}
return cast(
BulkPairing,
self._r.post(
path,
payload=payload,
fmt=JSON,
),
)

def start_clocks(self, bulk_pairing_id: str) -> None:
"""Immediately start all clocks of the games of the given bulk pairing.
This overrides the startClocksAt value of an existing bulk pairing.
If the games have not yet been created (pairAt is in the future) or the clocks
have already started (startClocksAt is in the past), then this does nothing.
:param bulk_pairing_id: id of the bulk pairing to start clocks of
"""
path = f"/api/bulk-pairing/{bulk_pairing_id}/start-clocks"
self._r.post(path)

def cancel(self, bulk_pairing_id: str) -> None:
"""Cancel and delete a bulk pairing that is scheduled in the future.
If the games have already been created, then this does nothing.
:param bulk_pairing_id: id of the bulk pairing to cancel
"""
path = f"/api/bulk-pairing/{bulk_pairing_id}"
self._r.request("DELETE", path)
25 changes: 18 additions & 7 deletions berserk/types/__init__.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
from __future__ import annotations

from .team import Team, PaginatedTeams
from .account import AccountInformation, Perf, Preferences, Profile, StreamerInfo
from .bulk_pairings import BulkPairing, BulkPairingGame
from .common import ClockConfig
from .opening_explorer import (
OpeningStatistic,
OpeningExplorerRating,
OpeningExplorerVariant,
OpeningStatistic,
Speed,
OpeningExplorerRating,
)
from .team import PaginatedTeams, Team

__all__ = [
"Team",
"PaginatedTeams",
"OpeningStatistic",
"AccountInformation",
"BulkPairing",
"BulkPairingGame",
"ClockConfig",
"OpeningExplorerRating",
"OpeningExplorerVariant",
"OpeningStatistic",
"PaginatedTeams",
"Perf",
"Preferences",
"Profile",
"Speed",
"OpeningExplorerRating",
"StreamerInfo",
"Team",
]
96 changes: 96 additions & 0 deletions berserk/types/account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from __future__ import annotations

from datetime import datetime

from typing_extensions import TypedDict


class Perf(TypedDict):
games: int
rating: int
rd: int
prog: int
prov: bool


class Profile(TypedDict):
"""Public profile of an account."""

country: str
location: str
bio: str
firstName: str
lastName: str
fideRating: int
uscfRating: int
ecfRating: int
links: str


class StreamerInfo(TypedDict):
"""Information about the streamer on a specific platform."""

channel: str


class AccountInformation(TypedDict):
"""Information about an account."""

id: str
username: str
perfs: dict[str, Perf]
createdAt: datetime
disabled: bool
tosViolation: bool
profile: Profile
seenAt: datetime
patron: bool
verified: bool
title: str
url: str
playing: str
count: dict[str, int]
streaming: bool
streamer: dict[str, StreamerInfo]
followable: bool
following: bool
blocking: bool
followsYou: bool


class Preferences(TypedDict, total=False):
dark: bool
transp: bool
bgImg: str
is3d: bool
theme: str
pieceSet: str
theme3d: str
pieceSet3d: str
soundSet: str
blindfold: int
autoQueen: int
autoThreefold: int
takeback: int
moretime: int
clockTenths: int
clockBar: bool
clockSound: bool
premove: bool
animation: int
captured: bool
follow: bool
highlight: bool
destination: bool
coords: int
replay: int
challenge: int
message: int
coordColor: int
submitMove: int
confirmResign: int
insightShare: int
keyboardMove: int
zen: int
moveEvent: int
rookCastle: int
23 changes: 23 additions & 0 deletions berserk/types/bulk_pairings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from __future__ import annotations

from typing_extensions import TypedDict

from .common import ClockConfig, Variant


class BulkPairingGame(TypedDict):
id: str
black: str
white: str


class BulkPairing(TypedDict):
id: str
games: list[BulkPairingGame]
variant: Variant
clock: ClockConfig
pairAt: int
pairedAt: int | None
rated: bool
startClocksAt: int
scheduledAt: int
Loading

0 comments on commit 54c4450

Please sign in to comment.