diff --git a/README.md b/README.md index b0f8ff8..b9b9109 100644 --- a/README.md +++ b/README.md @@ -37,10 +37,21 @@ hatch run sdk-download ### Usage +If you have a TeamTalk SDK license, you can pass it when instantiating the bot so +the SDK is initialized with your credentials. Both `license_name` and +`license_key` must be provided together; otherwise the library raises a +`ValueError`. The TeamTalk SDK license is process-wide, so all bot instances in +the same process must reuse the same credentials. + ```python import pytalk -bot = pytalk.TeamTalkBot() +bot = pytalk.TeamTalkBot( + client_name="PyTalk", + # Optional: apply your TeamTalk SDK license if you have one + license_name="Your Company", + license_key="XXXXX-XXXXX-XXXXX-XXXXX", +) @bot.event async def on_ready(): diff --git a/docs/index.rst b/docs/index.rst index b9f512d..86a74ed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -26,13 +26,23 @@ Alternatively, you can download the source code from the GitHub repository and r Quick Start ----------- +If you own a TeamTalk SDK license, you can supply it at initialization so the +SDK is unlocked with your credentials. Both ``license_name`` and +``license_key`` must be provided together, and the license is process-wide, so +all bot instances must share the same credentials. Otherwise, you can omit +them. + To quickly get started with Pytalk, you can use the following code snippet: .. code-block:: import pytalk -bot = pytalk.TeamTalkBot() +bot = pytalk.TeamTalkBot( + # Optional: apply your TeamTalk SDK license details if you have them + license_name="Your Company", + license_key="XXXXX-XXXXX-XXXXX-XXXXX", +) @bot.event async def on_ready(): diff --git a/pytalk/bot.py b/pytalk/bot.py index 64920f8..cdd2b52 100644 --- a/pytalk/bot.py +++ b/pytalk/bot.py @@ -16,6 +16,7 @@ import uvloop from .enums import TeamTalkServerInfo +from .implementation.TeamTalkPy import TeamTalk5 as sdk from .instance import TeamTalkInstance T = TypeVar("T") @@ -38,12 +39,26 @@ def __getattr__(self, attr: str) -> None: class TeamTalkBot: """A class that represents a TeamTalk bot.""" - def __init__(self, client_name: str | None = "PyTalk") -> None: + _license_applied: bool = False + _license_value: tuple[str, str] | None = None + + def __init__( + self, + client_name: str | None = "PyTalk", + *, + license_name: str | None = None, + license_key: str | None = None, + ) -> None: """Initialize a TeamTalkBot object. Args: client_name (Optional[str]): The name of the client. Defaults to "Teamtalk.py". + license_name (Optional[str]): Name/company issued with the TeamTalk SDK + license. Must be provided together with ``license_key`` to take + effect. + license_key (Optional[str]): TeamTalk SDK license key. Must be provided + together with ``license_name`` to take effect. """ self.client_name = client_name @@ -53,6 +68,37 @@ def __init__(self, client_name: str | None = "PyTalk") -> None: str, list[tuple[asyncio.Future[Any], Callable[..., bool]]] ] = {} + if (license_name or license_key) and not (license_name and license_key): + msg = "Both license_name and license_key must be provided together." + raise ValueError(msg) + + if license_name and license_key: + if not license_name.strip() or not license_key.strip(): + msg = "license_name and license_key cannot be empty strings." + raise ValueError(msg) + + license_tuple = (license_name, license_key) + if TeamTalkBot._license_applied: + if license_tuple != TeamTalkBot._license_value: + msg = ( + "TeamTalk SDK license is already configured for this process; " + "provide the same credentials or restart the process." + ) + raise ValueError(msg) + else: + applied = sdk.setLicense( + sdk.ttstr(license_name), # type: ignore[arg-type] + sdk.ttstr(license_key), # type: ignore[arg-type] + ) + if not applied: + _log.warning( + "TeamTalk SDK license information was not accepted; proceeding " + "without applying a license.", + ) + else: + TeamTalkBot._license_applied = True + TeamTalkBot._license_value = license_tuple + async def add_server( self, server: TeamTalkServerInfo | dict[str, Any],