findmy.reports

Code related to fetching location reports.

Submodules

Classes

AppleAccount

A sync implementation of BaseappleAccount.

AsyncAppleAccount

An async implementation of BaseAppleAccount.

BaseAnisetteProvider

Abstract base class for Anisette providers.

RemoteAnisetteProvider

Anisette provider. Fetches headers from a remote Anisette server.

LoginState

Enum of possible login states. Used for AppleAccount's internal state machine.

SmsSecondFactorMethod

Base class for SMS-based two-factor authentication.

TrustedDeviceSecondFactorMethod

Base class for trusted device-based two-factor authentication.

Package Contents

class findmy.reports.AppleAccount(anisette: findmy.reports.anisette.BaseAnisetteProvider, user_id: str | None = None, device_id: str | None = None)

Bases: BaseAppleAccount

A sync implementation of BaseappleAccount.

Uses AsyncappleAccount internally.

async close() None

See AsyncAppleAccount.close.

property login_state: findmy.reports.state.LoginState

See AsyncAppleAccount.login_state.

property account_name: str | None

See AsyncAppleAccount.login_state.

property first_name: str | None

See AsyncAppleAccount.first_name.

property last_name: str | None

See AsyncAppleAccount.last_name.

export() dict

See AsyncAppleAccount.export.

restore(data: dict) None

See AsyncAppleAccount.restore.

login(username: str, password: str) findmy.reports.state.LoginState

See AsyncAppleAccount.login.

get_2fa_methods() Sequence[findmy.reports.twofactor.SyncSecondFactorMethod]

See AsyncAppleAccount.get_2fa_methods.

sms_2fa_request(phone_number_id: int) None

See AsyncAppleAccount.sms_2fa_request.

sms_2fa_submit(phone_number_id: int, code: str) findmy.reports.state.LoginState

See AsyncAppleAccount.sms_2fa_submit.

td_2fa_request() None

See AsyncAppleAccount.td_2fa_request.

td_2fa_submit(code: str) findmy.reports.state.LoginState

See AsyncAppleAccount.td_2fa_submit.

fetch_reports(keys: findmy.keys.HasHashedPublicKey, date_from: datetime.datetime, date_to: datetime.datetime | None) list[findmy.reports.reports.LocationReport]
fetch_reports(keys: Sequence[findmy.keys.HasHashedPublicKey], date_from: datetime.datetime, date_to: datetime.datetime | None) dict[findmy.keys.HasHashedPublicKey, list[findmy.reports.reports.LocationReport]]
fetch_reports(keys: findmy.accessory.RollingKeyPairSource, date_from: datetime.datetime, date_to: datetime.datetime | None) list[findmy.reports.reports.LocationReport]

See AsyncAppleAccount.fetch_reports.

fetch_last_reports(keys: findmy.keys.HasHashedPublicKey, hours: int = 7 * 24) list[findmy.reports.reports.LocationReport]
fetch_last_reports(keys: Sequence[findmy.keys.HasHashedPublicKey], hours: int = 7 * 24) dict[findmy.keys.HasHashedPublicKey, list[findmy.reports.reports.LocationReport]]
fetch_last_reports(keys: findmy.accessory.RollingKeyPairSource, hours: int = 7 * 24) list[findmy.reports.reports.LocationReport]

See AsyncAppleAccount.fetch_last_reports.

get_anisette_headers(with_client_info: bool = False, serial: str = '0') dict[str, str]

See AsyncAppleAccount.get_anisette_headers.

class findmy.reports.AsyncAppleAccount(anisette: findmy.reports.anisette.BaseAnisetteProvider, user_id: str | None = None, device_id: str | None = None)

Bases: BaseAppleAccount

An async implementation of BaseAppleAccount.

property login_state: findmy.reports.state.LoginState

See BaseAppleAccount.login_state.

property account_name: str | None

See BaseAppleAccount.account_name.

property first_name: str | None

See BaseAppleAccount.first_name.

property last_name: str | None

See BaseAppleAccount.last_name.

export() dict

See BaseAppleAccount.export.

restore(data: dict) None

See BaseAppleAccount.restore.

async close() None

Close any sessions or other resources in use by this object.

Should be called when the object will no longer be used.

async login(username: str, password: str) findmy.reports.state.LoginState

See BaseAppleAccount.login.

async get_2fa_methods() Sequence[findmy.reports.twofactor.AsyncSecondFactorMethod]

See BaseAppleAccount.get_2fa_methods.

async sms_2fa_request(phone_number_id: int) None

See BaseAppleAccount.sms_2fa_request.

async sms_2fa_submit(phone_number_id: int, code: str) findmy.reports.state.LoginState

See BaseAppleAccount.sms_2fa_submit.

async td_2fa_request() None

See BaseAppleAccount.td_2fa_request.

async td_2fa_submit(code: str) findmy.reports.state.LoginState

See BaseAppleAccount.td_2fa_submit.

async fetch_raw_reports(start: int, end: int, ids: list[str]) dict[str, Any]

Make a request for location reports, returning raw data.

async fetch_reports(keys: findmy.keys.HasHashedPublicKey, date_from: datetime.datetime, date_to: datetime.datetime | None) list[findmy.reports.reports.LocationReport]
async fetch_reports(keys: Sequence[findmy.keys.HasHashedPublicKey], date_from: datetime.datetime, date_to: datetime.datetime | None) dict[findmy.keys.HasHashedPublicKey, list[findmy.reports.reports.LocationReport]]
async fetch_reports(keys: findmy.accessory.RollingKeyPairSource, date_from: datetime.datetime, date_to: datetime.datetime | None) list[findmy.reports.reports.LocationReport]

See BaseAppleAccount.fetch_reports.

async fetch_last_reports(keys: findmy.keys.HasHashedPublicKey, hours: int = 7 * 24) list[findmy.reports.reports.LocationReport]
async fetch_last_reports(keys: Sequence[findmy.keys.HasHashedPublicKey], hours: int = 7 * 24) dict[findmy.keys.HasHashedPublicKey, list[findmy.reports.reports.LocationReport]]
async fetch_last_reports(keys: findmy.accessory.RollingKeyPairSource, hours: int = 7 * 24) list[findmy.reports.reports.LocationReport]

See BaseAppleAccount.fetch_last_reports.

async get_anisette_headers(with_client_info: bool = False, serial: str = '0') dict[str, str]

See BaseAppleAccount.get_anisette_headers.

class findmy.reports.BaseAnisetteProvider(loop: asyncio.AbstractEventLoop | None = None)

Bases: findmy.util.closable.Closable, abc.ABC

Abstract base class for Anisette providers.

Generously derived from https://github.com/nythepegasus/grandslam/blob/main/src/grandslam/gsa.py#L41.

property otp: str
Abstractmethod:

A seemingly random base64 string containing 28 bytes.

TODO: Figure out how to generate this.

property machine: str
Abstractmethod:

A base64 encoded string of 60 ‘random’ bytes.

We’re not sure how this is generated, we have to rely on the server. TODO: Figure out how to generate this.

property timestamp: str

Current timestamp in ISO 8601 format.

property timezone: str

Abbreviation of the timezone of the device.

property locale: str

Locale of the device (e.g. en_US).

property router: str

A number, either 17106176 or 50660608.

It doesn’t seem to matter which one we use. - 17106176 is used by Sideloadly and Provision (android) based servers. - 50660608 is used by Windows iCloud based servers.

property client: str

Client string.

The format is as follows: <%MODEL%> <%OS%;%MAJOR%.%MINOR%(%SPMAJOR%,%SPMINOR%);%BUILD%>

<%AUTHKIT_BUNDLE_ID%/%AUTHKIT_VERSION% (%APP_BUNDLE_ID%/%APP_VERSION%)>

Where:

MODEL: The model of the device (e.g. MacBookPro15,1 or ‘PC’ OS: The OS of the device (e.g. Mac OS X or Windows) MAJOR: The major version of the OS (e.g. 10) MINOR: The minor version of the OS (e.g. 15) SPMAJOR: The major version of the service pack (e.g. 0) (Windows only) SPMINOR: The minor version of the service pack (e.g. 0) (Windows only) BUILD: The build number of the OS (e.g. 19C57) AUTHKIT_BUNDLE_ID: The bundle ID of the AuthKit framework (e.g. com.apple.AuthKit) AUTHKIT_VERSION: The version of the AuthKit framework (e.g. 1) APP_BUNDLE_ID: The bundle ID of the app (e.g. com.apple.dt.Xcode) APP_VERSION: The version of the app (e.g. 3594.4.19)

async get_headers(user_id: str, device_id: str, serial: str = '0', with_client_info: bool = False) dict[str, str]

Generate a complete dictionary of Anisette headers.

Consider using BaseAppleAccount.get_anisette_headers instead.

async get_cpd(user_id: str, device_id: str, serial: str = '0') dict[str, str]

Generate a complete dictionary of CPD data.

Intended for internal use.

class findmy.reports.RemoteAnisetteProvider(server_url: str)

Bases: BaseAnisetteProvider

Anisette provider. Fetches headers from a remote Anisette server.

property otp: str

See `BaseAnisetteProvider.otp`_.

property machine: str

See `BaseAnisetteProvider.machine`_.

async get_headers(user_id: str, device_id: str, serial: str = '0', with_client_info: bool = False) dict[str, str]

See `BaseAnisetteProvider.get_headers`_.

async close() None

See AnisetteProvider.close.

class findmy.reports.LoginState

Bases: enum.Enum

Enum of possible login states. Used for AppleAccount’s internal state machine.

LOGGED_OUT = 0
REQUIRE_2FA = 1
AUTHENTICATED = 2
LOGGED_IN = 3
__lt__(other: LoginState) bool

Compare against another LoginState.

A LoginState is said to be “less than” another LoginState iff it is in an “earlier” stage of the login process, going from LOGGED_OUT to LOGGED_IN.

__repr__() str

Human-readable string representation of the state.

class findmy.reports.SmsSecondFactorMethod(account: _AccType)

Bases: BaseSecondFactorMethod, abc.ABC

Base class for SMS-based two-factor authentication.

property phone_number_id: int
Abstractmethod:

The phone number’s ID. You most likely don’t need this.

property phone_number: str
Abstractmethod:

The 2FA method’s phone number.

May be masked using unicode characters; should only be used for identification purposes.

class findmy.reports.TrustedDeviceSecondFactorMethod(account: _AccType)

Bases: BaseSecondFactorMethod, abc.ABC

Base class for trusted device-based two-factor authentication.