"""Oauth helpers for YouTube.""" from __future__ import annotations import aiohttp from youtubeaio.helper import YOUTUBE_AUTH_TOKEN_URL, build_url from youtubeaio.types import InvalidRefreshTokenError, UnauthorizedError __all__ = ["refresh_access_token"] async def refresh_access_token( refresh_token: str, app_id: str, app_secret: str, session: aiohttp.ClientSession | None = None, ) -> tuple[str, str]: """Refresh a user access token. :param str refresh_token: the current refresh_token :param str app_id: the id of your app :param str app_secret: the secret key of your app :param ~aiohttp.ClientSession session: optionally a active client session to be used for the web request to avoid having to open a new one :return: access_token, refresh_token :raises ~youtubeaio.types.InvalidRefreshTokenException: if refresh token is invalid :raises ~youtubeaio.types.UnauthorizedException: if both refresh and access token are invalid (e.g. if the user changes their password of the app gets disconnected) :rtype: (str, str) """ param = { "refresh_token": refresh_token, "client_id": app_id, "grant_type": "refresh_token", "client_secret": app_secret, "access_type": "offline", "prompt": "consent", } url = build_url(YOUTUBE_AUTH_TOKEN_URL, {}) ses = session if session is not None else aiohttp.ClientSession() async with ses.post(url, data=param) as result: data = await result.json() if session is None: await ses.close() if result.status == 400: raise InvalidRefreshTokenError(data.get("error", "")) if result.status == 401: raise UnauthorizedError(data.get("error", "")) return data["access_token"], refresh_token