diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ceacbc7..d74544a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,5 +5,6 @@ repos: hooks: # Run the linter. - id: ruff + args: ["--fix"] # Run the formatter. - id: ruff-format diff --git a/findmy/account.pyi b/findmy/account.pyi new file mode 100644 index 0000000..7b17a90 --- /dev/null +++ b/findmy/account.pyi @@ -0,0 +1,117 @@ +from datetime import datetime +from typing import Sequence + +from .anisette import BaseAnisetteProvider as BaseAnisetteProvider +from .base import ( + BaseAppleAccount as BaseAppleAccount, +) +from .base import ( + BaseSecondFactorMethod as BaseSecondFactorMethod, +) +from .base import ( + LoginState as LoginState, +) +from .keys import KeyPair as KeyPair +from .reports import KeyReport as KeyReport + +class LoginError(Exception): ... +class InvalidStateError(RuntimeError): ... +class ExportRestoreError(ValueError): ... + +class AsyncSmsSecondFactor(BaseSecondFactorMethod): + def __init__( + self, + account: AsyncAppleAccount, + number_id: int, + phone_number: str, + ) -> None: ... + @property + def phone_number_id(self) -> int: ... + @property + def phone_number(self) -> str: ... + async def request(self) -> None: ... + async def submit(self, code: str) -> LoginState: ... + +class SmsSecondFactor(BaseSecondFactorMethod): + def __init__( + self, + account: AppleAccount, + number_id: int, + phone_number: str, + ) -> None: ... + @property + def phone_number_id(self) -> int: ... + @property + def phone_number(self) -> str: ... + def request(self) -> None: ... + def submit(self, code: str) -> LoginState: ... + +class AsyncAppleAccount(BaseAppleAccount): + def __init__( + self, + anisette: BaseAnisetteProvider, + user_id: str | None = None, + device_id: str | None = None, + ) -> None: ... + @property + def login_state(self) -> LoginState: ... + @property + def account_name(self) -> str | None: ... + @property + def first_name(self) -> str | None: ... + @property + def last_name(self) -> str | None: ... + def export(self) -> dict: ... + def restore(self, data: dict) -> None: ... + async def close(self) -> None: ... + async def login(self, username: str, password: str) -> LoginState: ... + async def get_2fa_methods(self) -> list[AsyncSmsSecondFactor]: ... + async def sms_2fa_request(self, phone_number_id: int) -> None: ... + async def sms_2fa_submit(self, phone_number_id: int, code: str) -> LoginState: ... + async def fetch_reports( + self, + keys: Sequence[KeyPair], + date_from: datetime, + date_to: datetime, + ) -> dict[KeyPair, list[KeyReport]]: ... + async def fetch_last_reports( + self, + keys: Sequence[KeyPair], + hours: int = ..., + ) -> dict[KeyPair, list[KeyReport]]: ... + async def get_anisette_headers(self, serial: str = "0") -> dict[str, str]: ... + +class AppleAccount(BaseAppleAccount): + def __init__( + self, + anisette: BaseAnisetteProvider, + user_id: str | None = None, + device_id: str | None = None, + ) -> None: ... + def __del__(self) -> None: ... + @property + def login_state(self) -> LoginState: ... + @property + def account_name(self) -> str: ... + @property + def first_name(self) -> str | None: ... + @property + def last_name(self) -> str | None: ... + def export(self) -> dict: ... + def restore(self, data: dict) -> None: ... + def login(self, username: str, password: str) -> LoginState: ... + def get_2fa_methods(self) -> list[SmsSecondFactor]: ... + def sms_2fa_request(self, phone_number_id: int) -> None: ... + def sms_2fa_submit(self, phone_number_id: int, code: str) -> LoginState: ... + def fetch_reports( + self, + keys: Sequence[KeyPair], + date_from: datetime, + date_to: datetime, + ) -> dict[KeyPair, list[KeyReport]]: ... + def fetch_last_reports( + self, + keys: Sequence[KeyPair], + hours: int = ..., + ) -> dict[KeyPair, list[KeyReport]]: ... + def get_anisette_headers(self, serial: str = "0") -> dict[str, str]: ... diff --git a/findmy/anisette.pyi b/findmy/anisette.pyi new file mode 100644 index 0000000..3e17c89 --- /dev/null +++ b/findmy/anisette.pyi @@ -0,0 +1,20 @@ +import abc +from abc import ABC, abstractmethod + +class BaseAnisetteProvider(ABC, metaclass=abc.ABCMeta): + @abstractmethod + async def close(self) -> None: ... + async def get_headers( + self, + user_id: str, + device_id: str, + serial: str = "0", + ) -> dict[str, str]: ... + +class RemoteAnisetteProvider(BaseAnisetteProvider): + def __init__(self, server_url: str) -> None: ... + async def close(self) -> None: ... + +class LocalAnisetteProvider(BaseAnisetteProvider): + def __init__(self) -> None: ... + async def close(self) -> None: ... diff --git a/findmy/keys.pyi b/findmy/keys.pyi new file mode 100644 index 0000000..fab1623 --- /dev/null +++ b/findmy/keys.pyi @@ -0,0 +1,21 @@ +from cryptography.hazmat.primitives.asymmetric import ec + +class KeyPair: + def __init__(self, private_key: bytes) -> None: ... + @classmethod + def generate(cls) -> KeyPair: ... + @classmethod + def from_b64(cls, key_b64: str) -> KeyPair: ... + @property + def private_key_bytes(self) -> bytes: ... + @property + def private_key_b64(self) -> str: ... + @property + def adv_key_bytes(self) -> bytes: ... + @property + def adv_key_b64(self) -> str: ... + @property + def hashed_adv_key_bytes(self) -> bytes: ... + @property + def hashed_adv_key_b64(self) -> str: ... + def dh_exchange(self, other_pub_key: ec.EllipticCurvePublicKey) -> bytes: ...