### Install pyfamilysafety from PyPI Source: https://pantherale0.github.io/pyfamilysafety/getting-started/installation Use this command to install the library for general use. ```bash pip install pyfamilysafety ``` -------------------------------- ### Development Install pyfamilysafety Source: https://pantherale0.github.io/pyfamilysafety/getting-started/installation Clone the repository and install with development dependencies for contributing or modifying the library. ```bash git clone https://github.com/pantherale0/pyfamilysafety.git cd pyfamilysafety python3 -m venv venv source venv/bin/activate pip install -e ".[dev]" ``` -------------------------------- ### Create Authenticator Instance Source: https://pantherale0.github.io/pyfamilysafety/reference/authenticator Creates and starts a Microsoft auth session. Use `use_refresh_token=True` to initialize with a refresh token. ```python @classmethod async def create( cls, token: str, use_refresh_token: bool=False, client_session: aiohttp.ClientSession | None = None) -> 'Authenticator': """Creates and starts a Microsoft auth session without retaining the username and password.""" auth = cls(client_session=client_session) if use_refresh_token: auth.refresh_token = token await auth.perform_refresh() return auth else: redir_parsed = auth._parse_response_token(token) await auth.perform_login(redir_parsed["code"]) return auth ``` -------------------------------- ### Create Daily Restriction from Minutes and Intervals Source: https://pantherale0.github.io/pyfamilysafety/guide/device-limits This example shows how to define a daily screen time restriction using minutes for the total allowance and specifying allowed time intervals. Use this when you need to set limits in minutes rather than milliseconds. ```python DayOfWeek.SUNDAY: DailyRestriction.from_minutes( 285, allotted_intervals=[ AllottedInterval("07:00:00", "11:00:00"), AllottedInterval("12:00:00", "18:30:00"), ], ) ``` -------------------------------- ### Basic Logging Configuration Source: https://pantherale0.github.io/pyfamilysafety/advanced/logging Configure the root logger to display DEBUG level messages and specify a custom format including timestamp, logger name, level, and message. This setup is essential for tracing library operations. ```python import logging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s %(name)s %(levelname)s: %(message)s", ) ``` -------------------------------- ### Enable Pending Request Polling Source: https://pantherale0.github.io/pyfamilysafety/guide/pending-requests Enable experimental mode and update to start polling for pending requests. Only requests with type 'DeviceScreenTime' are included. ```python family_safety.experimental = True await family_safety.update() for request in family_safety.pending_requests: print(request["id"], request["type"], request.get("platform")) ``` -------------------------------- ### create Class Method Source: https://pantherale0.github.io/pyfamilysafety/reference/authenticator Creates and starts a Microsoft auth session without retaining the username and password. This class method is used to instantiate an Authenticator object and perform the initial authentication flow. ```APIDOC ## create(token, use_refresh_token=False, client_session=None) ### Description Creates and starts a Microsoft auth session without retaining the username and password. This class method is used to instantiate an Authenticator object and perform the initial authentication flow. ### Parameters * **token** (str) - Required - The authentication token or refresh token. * **use_refresh_token** (bool) - Optional - Defaults to False. If True, the provided token is treated as a refresh token. * **client_session** (aiohttp.ClientSession) - Optional - An existing aiohttp client session to use. ``` -------------------------------- ### Get a Single Application Source: https://pantherale0.github.io/pyfamilysafety/reference/account Retrieves a specific application using its ID. Assumes the application exists within the account's list. ```python def get_application(self, application_id) -> Application: """Returns a single application.""" return [x for x in self.applications if x.app_id == application_id][0] ``` -------------------------------- ### Get Screen Time Usage (Async) Source: https://pantherale0.github.io/pyfamilysafety/reference/account Retrieve screen time usage data for a specified time range and platform. Defaults to the current day if no times are provided. Handles both device and application usage. ```python async def get_screentime_usage(self, start_time: datetime = None, end_time: datetime = None, device_count: int = 4, platform: str = "ALL") -> dict: """Return screen time usage for a time range. Args: start_time: Range start; defaults to start of today (local). end_time: Range end; defaults to end of today (local). device_count: Maximum devices in the device usage report. platform: Platform filter (e.g. ``ALL``, ``WINDOWS``, ``XBOX``). Returns: When default times are used, returns cached ``screentime_usage`` after updating account fields. Otherwise a dict with ``devices`` and ``applications`` keys containing raw JSON payloads. """ default = False if start_time is None: default = True start_time = localise_datetime(datetime.combine(date.today(), time(0,0,0), tzinfo=API_TIMEZONE)) if end_time is None: default = True end_time = localise_datetime(datetime.combine(date.today(), time(23,59,59), tzinfo=API_TIMEZONE)) begin_time = quote_plus(start_time.strftime('%Y-%m-%dT%H:%M:%S%z')) end_time_param = quote_plus(end_time.strftime('%Y-%m-%dT%H:%M:%S%z')) device_usage, application_usage = await asyncio.gather( self._api.async_get_user_device_screentime_usage( user_id=self.user_id, begin_time=begin_time, end_time=end_time_param, device_count=device_count, platform=platform ), self._api.async_get_user_app_screentime_usage( user_id=self.user_id, begin_time=begin_time, end_time=end_time_param, platform=platform ), ) if default: self._apply_screentime_usage(device_usage.get("json"), application_usage.get("json")) return self.screentime_usage return { "devices": device_usage.get("json"), "applications": application_usage.get("json") } ``` -------------------------------- ### async_get_override_device_restrictions Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Send a GET request to override device restrictions. ```APIDOC ## async_get_override_device_restrictions ### Description Send a GET request to override device restrictions. ### Method GET ### Endpoint /get_override_device_restrictions ### Parameters #### Path Parameters None #### Query Parameters - **USER_ID** (string) - Required - The ID of the user. - **platform** (string) - Optional - The platform for which to get restrictions. Defaults to "ALL". ### Request Example ```json { "user_id": "some_user_id" } ``` ### Response #### Success Response (200) - **result** (object) - The overridden device restrictions. #### Response Example ```json { "result": {} } ``` ``` -------------------------------- ### Authenticate and get screen time Source: https://pantherale0.github.io/pyfamilysafety/getting-started/quick-start Authenticates using an OAuth redirect URL, fetches family data, and prints daily screen time for each member. Requires the redirect URL as input. ```python import asyncio import logging from pyfamilysafety import Authenticator, FamilySafety logging.basicConfig(level=logging.INFO) async def main(): redirect_url = input("Paste OAuth redirect URL: ") auth = await Authenticator.create(token=redirect_url) family_safety = FamilySafety(auth) await family_safety.update() for account in family_safety.accounts: name = account.first_name or account.user_id usage_ms = account.today_screentime_usage or 0 usage_min = usage_ms / 1000 / 60 print(f"{name}: {usage_min:.0f} minutes today") asyncio.run(main()) ``` -------------------------------- ### Get Specific Device Information Source: https://pantherale0.github.io/pyfamilysafety/reference/account Retrieve details for a single device using its unique ID. This is a synchronous operation. ```python def get_device(self, device_id) -> Device: """Returns a single device.""" return [x for x in self.devices if x.device_id == device_id][0] ``` -------------------------------- ### Create Allotted Interval from Time Objects Source: https://pantherale0.github.io/pyfamilysafety/guide/device-limits This snippet demonstrates creating an allowed screen time interval using datetime.time objects for the start and end times. This is useful for defining specific windows within a day when a user is permitted to use a device. ```python AllottedInterval.from_time(time(7, 0), time(11, 0)) ``` -------------------------------- ### Send Request for Unwrapped Endpoint Source: https://pantherale0.github.io/pyfamilysafety/advanced/endpoints Example of using `send_request` to access an endpoint without a high-level wrapper, such as `get_user_web_activity`. Requires specifying the endpoint key and necessary parameters like user ID, time range, and status. ```python response = await account._api.send_request( "get_user_web_activity", USER_ID=account.user_id, BEGIN_TIME=begin_time, END_TIME=end_time, ALLOW_STATUS="All", ) ``` -------------------------------- ### Get Override Device Restrictions Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Sends a GET request to retrieve override device restrictions for a user across all platforms. This method is part of the internal API. ```python async def async_get_override_device_restrictions(self, user_id): """Send a GET request to override device restrictions.""" return await self.send_request( "get_override_device_restrictions", USER_ID=user_id, platform="ALL", ) ``` -------------------------------- ### Get Pending Requests for an Account Source: https://pantherale0.github.io/pyfamilysafety/reference/family-safety Retrieves all pending screen-time requests associated with a specific family member, identified by their user ID. Returns a list of request dictionaries. ```python def get_account_requests(self, user_id: str) -> list: """Return pending requests for a family member. Args: user_id: Member ID (``puid`` field on pending requests). Returns: List of pending request dictionaries for that member. """ return [x for x in self.pending_requests if x["puid"] == user_id] ``` -------------------------------- ### Get Web Restrictions Asynchronously Source: https://pantherale0.github.io/pyfamilysafety/reference/account Retrieves the current web filtering settings for a member. Returns the parsed JSON response from the web restrictions API. ```python async def get_web_restrictions(self) -> dict: """Return current web filtering settings for this member. Returns: Parsed JSON from the web restrictions API. """ response = await self._api.async_get_user_web_restrictions(user_id=self.user_id) return response.get("json") ``` -------------------------------- ### Get Screen Time Usage for a Custom Date Range Source: https://pantherale0.github.io/pyfamilysafety/guide/accounts Use `get_screentime_usage` with specific start and end times to retrieve screen time data. Results are stored on the account and applications are parsed automatically when default times (today) are used. ```python from datetime import datetime, time, date from pyfamilysafety.helpers import API_TIMEZONE start = datetime.combine(date.today(), time(0, 0), tzinfo=API_TIMEZONE) end = datetime.combine(date.today(), time(23, 59, 59), tzinfo=API_TIMEZONE) usage = await account.get_screentime_usage(start_time=start, end_time=end) ``` -------------------------------- ### Get Screen Time Usage for Custom Time Range Source: https://pantherale0.github.io/pyfamilysafety/guide/screen-time Retrieves screen time usage data for a specified period. When start and end times are omitted, it defaults to today's usage and updates cached account fields. Explicit times return a dictionary containing device and application activity. ```python from datetime import datetime, date, time from pyfamilysafety.helpers import localise_datetime, API_TIMEZONE start = localise_datetime(datetime.combine(date.today(), time(0, 0), tzinfo=API_TIMEZONE)) end = localise_datetime(datetime.combine(date.today(), time(23, 59, 59), tzinfo=API_TIMEZONE)) result = await account.get_screentime_usage( start_time=start, end_time=end, device_count=4, platform="ALL", ) ``` ```json { "devices": {...}, # device screen time JSON "applications": {...} # app activity JSON } ``` -------------------------------- ### Create FamilySafety Authenticator and Client Source: https://pantherale0.github.io/pyfamilysafety/guide/family-safety-client Instantiate the Authenticator with a token and then create the FamilySafety client. Requires an asynchronous context. ```python from pyfamilysafety import Authenticator, FamilySafety auth = await Authenticator.create(token=redirect_url) family_safety = FamilySafety(auth) ``` -------------------------------- ### Initialize a Device Object Source: https://pantherale0.github.io/pyfamilysafety/reference/device Initializes a Device object with default None values for all attributes. This is the constructor for the Device class. ```python def __init__(self) -> None: """Init a device.""" self.device_id = None self.device_name = None self.device_class = None self.device_make = None self.device_model = None self.form_factor = None self.os_name = None self.today_time_used = None self.issues = None self.states = None self.last_seen = None self.blocked = None ``` -------------------------------- ### DeviceLimitsSchedule Constructor Source: https://pantherale0.github.io/pyfamilysafety/reference/schedule Initializes a DeviceLimitsSchedule for a specific platform with daily restrictions, mode, and culture settings. ```python def __init__( self, platform: OverrideTarget, daily_restrictions: dict[DayOfWeek, DailyRestriction], mode: DeviceLimitsMode = DeviceLimitsMode.PER_DEVICE_TYPE, culture: str = "en-GB") -> None: self.platform = platform self.daily_restrictions = daily_restrictions self.mode = mode self.culture = culture ``` -------------------------------- ### DailyRestriction from_minutes Classmethod Source: https://pantherale0.github.io/pyfamilysafety/reference/schedule Builds a DailyRestriction using an allowance specified in minutes, converting it to milliseconds. ```python @classmethod def from_minutes( cls, allowance_minutes: int, allotted_intervals: list[AllottedInterval] = None) -> "DailyRestriction": """Build a restriction using an allowance in minutes.""" return cls( allowance=int(allowance_minutes * 60 * 1000), allotted_intervals=allotted_intervals, ) ``` -------------------------------- ### Read current restrictions Source: https://pantherale0.github.io/pyfamilysafety/guide/web-filtering Retrieves the current web restrictions for a user. This corresponds to a GET request to the /v1/WebRestrictions/{USER_ID} endpoint. ```APIDOC ## GET /v1/WebRestrictions/{USER_ID} ### Description Retrieves the current web restrictions for a user. ### Method GET ### Endpoint /v1/WebRestrictions/{USER_ID} ### Parameters #### Path Parameters - **USER_ID** (string) - Required - The ID of the user whose web restrictions are being retrieved. ### Response #### Success Response (200) - **restrictions** (object) - The raw JSON object containing the user's web restrictions. ``` -------------------------------- ### Initialize FamilySafety Client Source: https://pantherale0.github.io/pyfamilysafety/reference/family-safety Initializes the FamilySafety client with an authenticated API session. The 'auth' parameter is required and should be an Authenticator object. ```python def __init__(self, auth: Authenticator) -> None: """Initialize the client. Args: auth: Authenticated :class:`~pyfamilysafety.authenticator.Authenticator` session. """ self._api: FamilySafetyAPI = FamilySafetyAPI(auth=auth) self.accounts: list[Account] = [] self.experimental: bool = False self.pending_requests = [] self._pending_request_callbacks = [] ``` -------------------------------- ### Look Up Specific Requests Source: https://pantherale0.github.io/pyfamilysafety/guide/pending-requests Retrieve a specific pending request by its ID or get all requests associated with a particular user account. ```python request = family_safety.get_request(request_id="...") member_requests = family_safety.get_account_requests(user_id=account.user_id) ``` -------------------------------- ### Application Class Constructor Source: https://pantherale0.github.io/pyfamilysafety/reference/application Initializes a new Application object. It sets up attributes for app details, policy, and blocked status, and stores references to the FamilySafetyAPI and user ID. ```python def __init__(self, api: FamilySafetyAPI, user_id): self.app_id = None self.name = None self.icon = None self._usage = None self.policy = None self.blocked: bool = None self._api: FamilySafetyAPI = api self._user_id = user_id ``` -------------------------------- ### Initialize Account Source: https://pantherale0.github.io/pyfamilysafety/reference/account Initializes an Account object with the provided API. Attributes are set to default values and will be populated by other methods. ```python def __init__(self, api) -> None: """Init an account.""" self.user_id = None self.role = None self.profile_picture = None self.first_name = None self.surname = None self.devices: list[Device] = None self.applications: list[Application] = [] self.today_screentime_usage: int = None self.average_screentime_usage: float = None self.screentime_usage: dict = None self.application_usage: dict = None self.blocked_platforms: list[OverrideTarget] = None self.experimental: bool = False self._api: FamilySafetyAPI = api self.account_balance: float = 0.0 self.account_currency: str = "" self._account_callbacks: list = [] ``` -------------------------------- ### FamilySafetyAPI Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Initializes the FamilySafetyAPI client with authentication credentials. ```APIDOC ## FamilySafetyAPI(auth: Authenticator) ### Description Initializes the API client with an Authenticator object. ### Parameters * **auth** (Authenticator) - The authentication object required for making API requests. ``` -------------------------------- ### DailyRestriction Constructor Source: https://pantherale0.github.io/pyfamilysafety/reference/schedule Initializes a DailyRestriction with a total allowance in milliseconds and optional allotted time intervals. ```python def __init__( self, allowance: int, allotted_intervals: list[AllottedInterval] = None) -> None: self.allowance = allowance self.allotted_intervals = allotted_intervals or [] ``` -------------------------------- ### Initialize Authenticator Source: https://pantherale0.github.io/pyfamilysafety/reference/authenticator Initializes the Authenticator class. It can optionally accept an existing aiohttp.ClientSession. ```python Authenticator(client_session=None) ``` ```python def __init__( self, client_session: aiohttp.ClientSession = None ) -> None: """init the class.""" _LOGGER.debug(">> Init authenticator.") self.expires: datetime = None self.refresh_token: str = None self._access_token: str = None self.user_id: str = None self._ppft: str = None self._login_lock: asyncio.Lock = asyncio.Lock() if client_session is None: client_session = aiohttp.ClientSession() self.client_session: aiohttp.ClientSession = client_session ``` -------------------------------- ### Get Pending Request by ID Source: https://pantherale0.github.io/pyfamilysafety/reference/family-safety Fetches a single pending screen-time request using its unique identifier. Raises a ValueError if the request ID is not found within the pending_requests list. ```python def get_request(self, request_id: str) -> dict: """Return a single pending request by ID. Args: request_id: Pending request identifier from the API. Returns: Raw pending request dictionary. Raises: ValueError: If the request is not in :attr:`pending_requests`. """ request = [x for x in self.pending_requests if x["id"] == request_id] if len(request) > 0: return request[0] raise ValueError("Pending request not found") ``` -------------------------------- ### Create Applications from Activity Report Source: https://pantherale0.github.io/pyfamilysafety/reference/application A class method to convert raw activity report data into a list of Application objects. It parses the 'appActivity' key from the response, creating an Application instance for each entry. ```python @classmethod def from_app_activity_report(cls, raw_response: dict, api, user_id) -> list['Application']: """Converts the activity report into a list of applications.""" parsed_apps = [] if "appActivity" in raw_response.keys(): apps = raw_response.get("appActivity") for app in apps: parsed = cls(api, user_id) parsed.app_id = app["appId"] parsed.name = app["displayName"] parsed.icon = app["iconUrl"] parsed._usage = app["usage"] parsed.policy = app["policy"] parsed.blocked = (app["blockState"] == "Blocked") or ( app["isLegacyBlocked"]) or ( app["blockState"] == "BlockedAlways" ) parsed_apps.append(parsed) else: raise ValueError("Missing appActivity in JSON response.") return parsed_apps ``` -------------------------------- ### Get Account by User ID Source: https://pantherale0.github.io/pyfamilysafety/reference/family-safety Retrieves a specific family member's account using their Microsoft family member ID. Raises an IndexError if no account matches the provided user_id. ```python def get_account(self, user_id: str) -> Account: """Return the account with the given member ID. Args: user_id: Microsoft family member ID from the roster. Returns: Matching :class:`~pyfamilysafety.account.Account`. Raises: IndexError: If no account matches ``user_id``. """ return [x for x in self.accounts if x.user_id == user_id][0] ``` -------------------------------- ### PyFamilySafety Component Overview Source: https://pantherale0.github.io/pyfamilysafety/advanced/architecture Illustrates the main components and their interactions within the PyFamilySafety library. ```mermaid flowchart LR User[Your app] Auth[Authenticator] FS[FamilySafety] Acct[Account] API[FamilySafetyAPI] MS[Microsoft API] User --> Auth User --> FS FS --> API FS --> Acct Acct --> API Auth --> MS API --> MS ``` -------------------------------- ### Enable Experimental Mode and Update Data Source: https://pantherale0.github.io/pyfamilysafety/guide/family-safety-client Activates experimental features, which includes loading pending requests when update() is called. Callbacks can be registered for these requests. ```python family_safety.experimental = True await family_safety.update() ``` -------------------------------- ### Account Class Initialization Source: https://pantherale0.github.io/pyfamilysafety/reference/account Initializes an Account object. This class represents a family member with Digital Safety enabled. ```APIDOC ## Account Class ### Description Represents a family member with Digital Safety enabled. It holds attributes related to the user's profile, devices, applications, and screen time usage. ### Attributes - `user_id` (str): Microsoft member identifier. - `role` (str): Family role from the roster API. - `first_name` (str): Member first name. - `surname` (str): Member last name. - `profile_picture` (str): Profile image URL. - `devices` (list[Device]): Registered devices, populated by :meth:`update`. - `applications` (list[Application]): Apps from the activity report, populated by :meth:`update`. - `today_screentime_usage` (int): Total device screen time today in milliseconds. - `average_screentime_usage` (float): Daily average screen time from the API. - `screentime_usage` (dict): Raw device screen-time report JSON. - `application_usage` (dict): Raw app activity report JSON. - `blocked_platforms` (list[OverrideTarget]): Platforms with an active device override block. - `account_balance` (float): Microsoft Store allowance balance when available. - `account_currency` (str): Currency code for `account_balance`. - `experimental` (bool): Mirrors the parent :class:`FamilySafety` experimental flag. ### Init ```python Account(api) ``` Initializes an account instance. ``` -------------------------------- ### Display Current Development Version Source: https://pantherale0.github.io/pyfamilysafety/changelog Import the pyfamilysafety library and print its current development version. This snippet shows how to access version information. ```python import pyfamilysafety print(pyfamilysafety.__version__) ``` -------------------------------- ### Approve or Deny Pending Requests Source: https://pantherale0.github.io/pyfamilysafety/guide/family-safety-client Manages pending screen-time requests when experimental mode is enabled. `extension_time` for approval is in seconds. ```python requests = family_safety.pending_requests await family_safety.approve_pending_request(request_id="...", extension_time=30) await family_safety.deny_pending_request(request_id="...") ``` -------------------------------- ### Set Device Limits Asynchronously Source: https://pantherale0.github.io/pyfamilysafety/reference/account Sets screen time limits for a platform on the account. Requires a `DeviceLimitsSchedule` object and includes the current time in the request body. ```python async def set_device_limits(self, schedule: DeviceLimitsSchedule) -> dict: """Set screen time limits for a platform on the account. Args: schedule: Platform-specific limits built from :class:`~pyfamilysafety.schedule.DeviceLimitsSchedule`. Returns: The API response body, if present. """ body = schedule.to_dict() body["time"] = localise_datetime(datetime.now()).strftime("%Y-%m-%dT%H:%M:%S%z") response = await self._api.async_update_schedule( user_id=self.user_id, body=body, ) return response.get("json") ``` -------------------------------- ### get_application Source: https://pantherale0.github.io/pyfamilysafety/reference/account Retrieves a single application associated with the account. ```APIDOC ## get_application ### Description Returns a single application. ### Method GET (Implicit) ### Endpoint /account/{application_id} ### Parameters #### Path Parameters - **application_id** (string) - Required - The ID of the application to retrieve. ### Response #### Success Response (200) - **Application** (object) - Details of the application. ### Response Example { "example": "{\"app_id\": \"some_id\", \"name\": \"Some App\"}" } ``` -------------------------------- ### Initialize FamilySafetyAPI Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Initializes the FamilySafetyAPI with an authenticator object. This is the low-level client for making direct HTTP requests. ```python def __init__(self, auth: Authenticator) -> None: """Init API.""" self._auth: Authenticator = auth self.pending_requests = [] ``` -------------------------------- ### Create Device List from Dictionary Source: https://pantherale0.github.io/pyfamilysafety/reference/device Parses a raw API response and a screentime report to create a list of Device objects. This class method is used to instantiate multiple devices from raw data. ```python @classmethod def from_dict(cls, raw_response: dict, screentime_report: dict) -> list['Device']: """Parse a raw response from 'get_user_devices' into a list.""" devices = [] if "devices" in raw_response.keys(): for device in raw_response.get("devices"): self = cls() self.device_id = device.get("deviceId").replace("g:", "") self.device_name = device.get("deviceName") self.device_class = device.get("deviceClass") self.device_make = device.get("deviceMake") self.device_model = device.get("deviceModel") self.form_factor = device.get("deviceFormFactor") self.os_name = device.get("osName") self.issues = device.get("issues") self.states = device.get("states") self.last_seen = device.get("lastSeenOn") self.read_screentime_report(screentime_report) devices.append(self) return devices ``` -------------------------------- ### List Applications Source: https://pantherale0.github.io/pyfamilysafety/guide/applications Iterates through applications associated with an account and prints their name, usage, and block status. Ensure Account.update() has been called to populate application data. ```python await family_safety.update() account = family_safety.accounts[0] for app in account.applications: print(app.name, app.usage, "min", "blocked:", app.blocked) ``` -------------------------------- ### Register and Remove Account Update Callbacks Source: https://pantherale0.github.io/pyfamilysafety/guide/accounts Add or remove functions that execute after an `account.update()` call. Both synchronous and asynchronous callbacks are supported. ```python def on_account_updated(): print(account.today_screentime_usage) account.add_account_callback(on_account_updated) account.remove_account_callback(on_account_updated) ``` -------------------------------- ### update Source: https://pantherale0.github.io/pyfamilysafety/reference/account Asynchronously updates all account details by fetching device information, usage statistics, application usage, and override settings. It then applies these updates and notifies registered callbacks. ```APIDOC ## update (async) ### Description Update all account details. ### Method Signature `update() -> None` ### Behavior This asynchronous method fetches various account-related data, including device information, screen time usage, application usage, and device restrictions. It processes this data, updates the account's state, and then invokes any registered account callbacks. Callbacks can be either synchronous or asynchronous. ``` -------------------------------- ### Retrieve User Device Screentime Usage Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Asynchronously retrieves user device screentime usage data. Requires user ID, time range, device count, and platform. Platform is sent in headers. ```python async def async_get_user_device_screentime_usage( self, user_id, begin_time, end_time, device_count, platform ): """Retrieve data from endpoint get_user_device_screentime_usage.""" return await self.send_request( "get_user_device_screentime_usage", headers={ "Plat-Info": platform }, USER_ID=user_id, BEGIN_TIME=begin_time, END_TIME=end_time, DEVICE_COUNT=device_count, ) ``` -------------------------------- ### Import Public Entry Points Source: https://pantherale0.github.io/pyfamilysafety/reference Import necessary classes and enums from the top-level pyfamilysafety package and its submodules. ```python from pyfamilysafety import Authenticator, FamilySafety, Account, FamilySafetyAPI from pyfamilysafety.enum import DayOfWeek, OverrideTarget, OverrideType, DeviceLimitsMode from pyfamilysafety.schedule import AllottedInterval, DailyRestriction, DeviceLimitsSchedule ``` -------------------------------- ### from_app_activity_report Source: https://pantherale0.github.io/pyfamilysafety/reference/application Converts the raw activity report data into a list of Application objects. ```APIDOC ## from_app_activity_report ### Description Converts the activity report into a list of applications. ### Class Method Signature `from_app_activity_report(raw_response: dict, api, user_id) -> list['Application']` ### Parameters - **raw_response** (dict): The raw response dictionary from the activity report. - **api**: An instance of the FamilySafetyAPI. - **user_id** (string): The ID of the user. ### Returns - **list['Application']**: A list of Application objects. ``` -------------------------------- ### Add a Website Exception Source: https://pantherale0.github.io/pyfamilysafety/guide/web-filtering Adds an exception for a specific website. Set `allowed=True` to permit the site, or `allowed=False` to block it regardless of the default filter. ```python await account.add_web_exception( website="example.com", allowed=True, source="", ) ``` -------------------------------- ### Session Sharing with aiohttp.ClientSession Source: https://pantherale0.github.io/pyfamilysafety/getting-started/authentication If you manage HTTP connections yourself, you can pass an existing aiohttp.ClientSession to Authenticator.create. This allows for shared connection management. ```python import aiohttp from pyfamilysafety import Authenticator async with aiohttp.ClientSession() as session: auth = await Authenticator.create(token=redirect_url, client_session=session) ``` -------------------------------- ### perform_login Method Source: https://pantherale0.github.io/pyfamilysafety/reference/authenticator Performs login using an authorization code. This method exchanges the authorization code for access and refresh tokens. ```APIDOC ## perform_login(auth_code) ### Description Performs login using an authorization code. This method exchanges the authorization code for access and refresh tokens. ### Parameters * **auth_code** (str) - Required - The authorization code obtained from the authentication flow. ``` -------------------------------- ### async_update_schedule Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Send a PATCH request to update device limits for a platform. Prefer using Account.set_device_limits instead of calling this directly. ```APIDOC ## async_update_schedule ### Description Send a PATCH request to update device limits for a platform. Prefer using Account.set_device_limits instead of calling this directly. ### Method PATCH ### Endpoint /update_schedule ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **user_id** (string) - Required - The ID of the user. - **body** (object) - Required - The payload for updating device limits. ### Request Example ```json { "user_id": "some_user_id", "body": {} } ``` ### Response #### Success Response (200) - **result** (object) - The result of the update operation. #### Response Example ```json { "result": {} } ``` ``` -------------------------------- ### Retrieve User Devices Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Asynchronously retrieves a list of devices associated with a user ID from the get_user_devices endpoint. Requires only the user ID. ```python async def async_get_user_devices(self, user_id): """Retrieve data from endpoint get_user_devices.""" return await self.send_request("get_user_devices", USER_ID=user_id) ``` -------------------------------- ### async_get_user_devices Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Retrieves a list of devices associated with a specific user. ```APIDOC ## async_get_user_devices ### Description Retrieves a list of devices linked to a specific user ID. ### Method GET ### Endpoint /get_user_devices ### Parameters #### Query Parameters - **USER_ID** (string) - Required - The ID of the user. ### Request Example ```json { "USER_ID": "user123" } ``` ### Response #### Success Response (200) - **devices** (array) - A list of user devices. #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### Accessing Devices Source: https://pantherale0.github.io/pyfamilysafety/guide/devices Update account data and iterate through devices to print their names and today's screen time. You can also retrieve a specific device by its ID. ```python await family_safety.update() account = family_safety.accounts[0] for device in account.devices: print(device.device_name, device.today_time_used) single = account.get_device(device_id="...") ``` -------------------------------- ### Read Account Balance - Python Source: https://pantherale0.github.io/pyfamilysafety/guide/spending Call Account.update() to fetch spending balance. The balance and currency are populated if the API returns exactly one balance object; otherwise, they remain at defaults. ```python await family_safety.update() account = family_safety.accounts[0] print(account.account_balance, account.account_currency) ``` -------------------------------- ### set_device_limits Source: https://pantherale0.github.io/pyfamilysafety/reference/account Sets screen time limits for a platform on the account. ```APIDOC ## set_device_limits `async` ### Description Set screen time limits for a platform on the account. ### Method POST (Implicit) ### Endpoint /account/set_device_limits ### Parameters #### Request Body - **schedule** (DeviceLimitsSchedule) - Required - Platform-specific limits built from :class:`~pyfamilysafety.schedule.DeviceLimitsSchedule`. ### Request Example { "example": "{\"schedule\": {\"platform\": \"Windows\", \"dailyLimit\": \"08:00\"}}" } ### Response #### Success Response (200) - **dict** - The API response body, if present. ### Response Example { "example": "{\"status\": \"success\"}" } ``` -------------------------------- ### Retrieve User App Screentime Usage Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Asynchronously retrieves user app screentime usage data. Requires user ID, time range, and platform information. The platform is passed via headers. ```python async def async_get_user_app_screentime_usage( self, user_id, begin_time, end_time, platform ): """Retrieve data from endpoint get_user_app_screentime_usage.""" return await self.send_request( "get_user_app_screentime_usage", headers={ "Plat-Info": platform }, USER_ID=user_id, BEGIN_TIME=begin_time, END_TIME=end_time ) ``` -------------------------------- ### OAuth Login with pyfamilysafety Source: https://pantherale0.github.io/pyfamilysafety/getting-started/authentication Use this snippet for the initial OAuth login flow. Obtain the redirect URL from the Microsoft login process and pass it to Authenticator.create. The user ID is printed upon successful login, and the refresh token can be saved for future use. ```python import asyncio from pyfamilysafety import Authenticator async def main(): redirect_url = "https://login.live.com/oauth20_desktop.srf?code=..." auth = await Authenticator.create(token=redirect_url) print("Logged in as", auth.user_id) # Save auth.refresh_token for later sessions asyncio.run(main()) ``` -------------------------------- ### Approve Pending Request with Extension Source: https://pantherale0.github.io/pyfamilysafety/guide/pending-requests Approve a pending request, optionally extending screen time. The extension_time is in seconds and converted to milliseconds internally. ```python success = await family_safety.approve_pending_request( request_id="...", extension_time=30, # seconds ) ``` -------------------------------- ### Format Datetime for Device Limits Source: https://pantherale0.github.io/pyfamilysafety/advanced/timezones Format the current local time using `localise_datetime` and `strftime` for setting device limits. Ensure the format matches API expectations. ```python localise_datetime(datetime.now()).strftime("%Y-%m-%dT%H:%M:%S%z") ``` -------------------------------- ### update() Source: https://pantherale0.github.io/pyfamilysafety/reference/family-safety Refreshes the family roster and all account data. This method loads the roster and creates Account instances on the first call. On subsequent calls, it runs the `update` method for each member. If experimental features are enabled, it also refreshes pending requests. ```APIDOC ## update() ### Description Refreshes the family roster and all account data. On the first call, loads the roster and creates :class:`Account` instances. On every call, runs :meth:`Account.update` for each member. When :attr:`experimental` is enabled, also refreshes pending requests. ### Method `async` ### Parameters This method does not take any parameters. ### Raises - **AggregatorException**: Not raised directly; transient aggregator errors are logged and ignored so cached data remains available. ### Source Code ```python async def update(self): """Refresh family roster and all account data. On the first call, loads the roster and creates :class:`Account` instances. On every call, runs :meth:`Account.update` for each member. When :attr:`experimental` is enabled, also refreshes pending requests. Raises: AggregatorException: Not raised directly; transient aggregator errors are logged and ignored so cached data remains available. """ try: if len(self.accounts) == 0: data = await self._api.send_request("get_accounts") self.accounts = await Account.from_dict( self._api, data["json"], self.experimental ) coros = [] if self.experimental: coros.append(self._get_pending_requests()) for account in self.accounts: coros.append(account.update()) await asyncio.gather(*coros) except AggregatorException: _LOGGER.warning("Aggregator exception occured, ignoring this update request.") ``` ``` -------------------------------- ### Retrieve User Payment Methods Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Asynchronously retrieves user payment methods. Requires both user ID and a CID (Card ID or similar identifier). ```python async def async_get_user_payment_methods(self, user_id, cid): """Retrieve data from endpoint get_user_payment_methods.""" return await self.send_request("get_user_payment_methods", USER_ID=user_id, CID=cid) ``` -------------------------------- ### DeviceLimitsSchedule Source: https://pantherale0.github.io/pyfamilysafety/reference/schedule Manages device screen time limits for a specific platform, including daily restrictions, mode, and culture settings. ```APIDOC ## DeviceLimitsSchedule ### Description Device screen time limits for a platform. Serialize with :meth:`to_dict` before sending to the API. Pass an instance directly to :meth:`pyfamilysafety.account.Account.set_device_limits`. ### Class `pyfamilysafety.schedule.DeviceLimitsSchedule` ### Methods #### `__init__` ```python __init__(self, platform: OverrideTarget, daily_restrictions: dict[DayOfWeek, DailyRestriction], mode: DeviceLimitsMode = DeviceLimitsMode.PER_DEVICE_TYPE, culture: str = 'en-GB') ``` Initializes a `DeviceLimitsSchedule` for a given platform. - **platform** (OverrideTarget) - The platform to which these limits apply. - **daily_restrictions** (dict[DayOfWeek, DailyRestriction]) - A dictionary mapping days of the week to `DailyRestriction` objects. - **mode** (DeviceLimitsMode, optional) - The mode for applying limits (e.g., `PER_DEVICE_TYPE`). Defaults to `DeviceLimitsMode.PER_DEVICE_TYPE`. - **culture** (str, optional) - The culture code for formatting. Defaults to 'en-GB'. #### `to_dict` ```python to_dict(self) -> dict ``` Converts the device limits schedule to a dictionary format suitable for API requests. ### Instance Attributes - **platform** (OverrideTarget) - The platform to which these limits apply. - **daily_restrictions** (dict[DayOfWeek, DailyRestriction]) - A dictionary mapping days of the week to `DailyRestriction` objects. - **mode** (DeviceLimitsMode) - The mode for applying limits. - **culture** (str) - The culture code for formatting. ``` -------------------------------- ### get_request Source: https://pantherale0.github.io/pyfamilysafety/reference/family-safety Fetches a single pending screen-time request by its unique identifier. ```APIDOC ## get_request ### Description Return a single pending request by ID. ### Method GET (conceptual) ### Endpoint N/A (Method within a client class) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters * **request_id** (str) - Required - Pending request identifier from the API. ### Returns * **dict** - Raw pending request dictionary. ### Raises * **ValueError** - If the request is not in :attr:`pending_requests`. ``` -------------------------------- ### Update Family Data and Fetch Pending Requests Source: https://pantherale0.github.io/pyfamilysafety/guide/family-safety-client Refreshes the family roster and member data. When experimental mode is enabled, it also fetches pending screen-time requests. ```python await family_safety.update() print(len(family_safety.accounts), "members") ``` -------------------------------- ### HttpException Constructor Source: https://pantherale0.github.io/pyfamilysafety/reference/exceptions Base exception for HTTP errors from the Family Safety API. Raised for non-success status codes not mapped to a specific subclass. ```python def __init__(self, *args: object) -> None: super().__init__(*args) ``` -------------------------------- ### Block and Unblock Application Source: https://pantherale0.github.io/pyfamilysafety/guide/applications Provides methods to block and unblock a specific application using its ID. The platform is inferred from the application ID prefix. ```python app = account.get_application(application_id="...") await app.block_app() await app.unblock_app() ``` -------------------------------- ### Set Device Limits Schedule for Xbox Source: https://pantherale0.github.io/pyfamilysafety/guide/device-limits This snippet demonstrates how to create and set a device limits schedule for the Xbox platform. It specifies daily screen time allowances and specific allowed intervals for Sunday. Ensure you have authenticated and updated the FamilySafety client before calling this method. ```python import asyncio from datetime import time from pyfamilysafety import Authenticator, FamilySafety from pyfamilysafety.enum import DayOfWeek, OverrideTarget from pyfamilysafety.schedule import ( AllottedInterval, DailyRestriction, DeviceLimitsSchedule, ) async def main(): auth = await Authenticator.create(token="...") family_safety = FamilySafety(auth) await family_safety.update() account = family_safety.accounts[0] schedule = DeviceLimitsSchedule( platform=OverrideTarget.XBOX, daily_restrictions={ DayOfWeek.SUNDAY: DailyRestriction( allowance=17100000, # milliseconds (4 h 45 min) allotted_intervals=[ AllottedInterval.from_time(time(7, 0), time(11, 0)), AllottedInterval.from_time(time(12, 0), time(18, 30)), ], ), }, ) await account.set_device_limits(schedule) asyncio.run(main()) ``` -------------------------------- ### async_get_accounts Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Asynchronously retrieves account data by sending a request to the 'get_accounts' endpoint. ```APIDOC ## async_get_accounts() ### Description Retrieves account data from the 'get_accounts' endpoint. ### Method `async` ### Endpoint `get_accounts` (internal endpoint key) ``` -------------------------------- ### override_device Source: https://pantherale0.github.io/pyfamilysafety/reference/account Blocks or unblocks a platform for a member. ```APIDOC ## override_device `async` ### Description Block or unblock a platform for this member. ### Method POST (Implicit) ### Endpoint /account/override_device ### Parameters #### Request Body - **target** (OverrideTarget) - Required - Platform to override (:class:`~pyfamilysafety.enum.OverrideTarget`). - **override** (OverrideType) - Required - `OverrideType.UNTIL` to block until a time, or `OverrideType.CANCEL` to remove a block. - **valid_until** (datetime) - Optional - Required when `override` is `UNTIL`; ignored for `CANCEL`. - **culture** (str) - Optional - Locale string sent to the API (default `en-GB`). ### Request Example { "example": "{\"target\": \"Windows\", \"override\": \"UNTIL\", \"valid_until\": \"2023-12-31T23:59:59Z\"}" } ### Response #### Success Response (200) - **bool** - `True` on success. ### Response Example { "example": "true" } ``` -------------------------------- ### async_get_user_payment_methods Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Retrieves payment methods for a specific user, identified by user ID and a customer ID (cid). ```APIDOC ## async_get_user_payment_methods ### Description Retrieves the payment methods associated with a user, using both user ID and a customer ID. ### Method GET ### Endpoint /get_user_payment_methods ### Parameters #### Query Parameters - **USER_ID** (string) - Required - The ID of the user. - **CID** (string) - Required - The customer ID. ### Request Example ```json { "USER_ID": "user123", "CID": "cust456" } ``` ### Response #### Success Response (200) - **payment_methods** (array) - A list of user payment methods. #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### Unauthorized Exception Constructor Source: https://pantherale0.github.io/pyfamilysafety/reference/exceptions Raised when authentication fails during login, refresh, or API calls due to HTTP 401 or failed token exchange. ```python def __init__(self) -> None: super().__init__("HTTP Unauthorized") ``` -------------------------------- ### Load Today's Screen Time Usage Source: https://pantherale0.github.io/pyfamilysafety/guide/screen-time Automatically loads today's device and application reports for an account. Use this to quickly access total milliseconds used across all devices, daily averages, and raw report dictionaries. ```python await family_safety.update() account = family_safety.accounts[0] print(account.today_screentime_usage) # total ms, all devices print(account.average_screentime_usage) # daily average print(account.screentime_usage) # raw device report dict print(account.application_usage) # raw app report dict ``` -------------------------------- ### Lookup Device or Application by ID Source: https://pantherale0.github.io/pyfamilysafety/guide/accounts Retrieve a specific device or application object using its ID. Requires the `device_id` or `application_id`. ```python device = account.get_device(device_id="...") app = account.get_application(application_id="...") ``` -------------------------------- ### async_get_premium_entitlement Source: https://pantherale0.github.io/pyfamilysafety/reference/api-internals Retrieves premium entitlement data by calling the 'get_premium_entitlement' endpoint. ```APIDOC ## async_get_premium_entitlement ### Description Retrieves premium entitlement data from the 'get_premium_entitlement' endpoint. ### Method GET ### Endpoint /get_premium_entitlement ### Parameters None ### Request Example ```json { "example": "request body" } ``` ### Response #### Success Response (200) - **data** (object) - Entitlement details #### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### DeviceLimitsSchedule to_dict Method Source: https://pantherale0.github.io/pyfamilysafety/reference/schedule Converts a DeviceLimitsSchedule object to a dictionary format suitable for API requests, including daily restrictions, mode, platform, and culture. ```python def to_dict(self) -> dict: """Convert to the API request format.""" return { "dailyRestrictions": { str(day): restriction.to_dict() for day, restriction in self.daily_restrictions.items() }, "mode": str(self.mode), "appliesTo": str(self.platform), "culture": self.culture, } ```