pynintendoparental 2.3.2__tar.gz → 2.3.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/PKG-INFO +2 -2
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/__init__.py +39 -4
- pynintendoparental-2.3.2.1/pynintendoparental/_version.py +1 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/api.py +18 -43
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/application.py +66 -24
- pynintendoparental-2.3.2.1/pynintendoparental/authenticator.py +44 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/const.py +3 -1
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/device.py +410 -178
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/player.py +33 -4
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental.egg-info/PKG-INFO +2 -2
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental.egg-info/requires.txt +1 -1
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/setup.py +1 -1
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/tests/test_api.py +10 -30
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/tests/test_applications.py +7 -15
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/tests/test_device.py +134 -81
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/tests/test_init.py +6 -18
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/tests/test_player.py +4 -7
- pynintendoparental-2.3.2/pynintendoparental/_version.py +0 -1
- pynintendoparental-2.3.2/pynintendoparental/authenticator.py +0 -18
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/LICENSE +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/README.md +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/enum.py +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/exceptions.py +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/py.typed +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental/utils.py +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental.egg-info/SOURCES.txt +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental.egg-info/dependency_links.txt +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pynintendoparental.egg-info/top_level.txt +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/pyproject.toml +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/setup.cfg +0 -0
- {pynintendoparental-2.3.2 → pynintendoparental-2.3.2.1}/tests/test_enum.py +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pynintendoparental
|
|
3
|
-
Version: 2.3.2
|
|
3
|
+
Version: 2.3.2.1
|
|
4
4
|
Summary: A Python module to interact with Nintendo Parental Controls
|
|
5
5
|
Home-page: http://github.com/pantherale0/pynintendoparental
|
|
6
6
|
Author: pantherale0
|
|
@@ -16,7 +16,7 @@ Provides-Extra: dev
|
|
|
16
16
|
Requires-Dist: aiofiles<26,>=23; extra == "dev"
|
|
17
17
|
Requires-Dist: bandit<1.10,>=1.7; extra == "dev"
|
|
18
18
|
Requires-Dist: black<26,>=23; extra == "dev"
|
|
19
|
-
Requires-Dist: build<1.
|
|
19
|
+
Requires-Dist: build<1.5,>=0.10; extra == "dev"
|
|
20
20
|
Requires-Dist: Faker<41,>=38; extra == "dev"
|
|
21
21
|
Requires-Dist: flake8<8,>=6; extra == "dev"
|
|
22
22
|
Requires-Dist: isort<8,>=5; extra == "dev"
|
|
@@ -6,14 +6,22 @@ import asyncio
|
|
|
6
6
|
from pynintendoauth.exceptions import HttpException
|
|
7
7
|
|
|
8
8
|
from .api import Api
|
|
9
|
+
from .authenticator import Authenticator
|
|
9
10
|
from .const import _LOGGER
|
|
10
11
|
from .device import Device
|
|
11
12
|
from .exceptions import NoDevicesFoundException
|
|
12
|
-
from .authenticator import Authenticator
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
class NintendoParental:
|
|
16
|
-
"""Core Python API.
|
|
16
|
+
"""Core Python API for Nintendo Switch Parental Controls.
|
|
17
|
+
|
|
18
|
+
This is the main entry point for interacting with Nintendo Switch Parental Controls.
|
|
19
|
+
Use the `create` class method to instantiate this class.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
account_id: The Nintendo account ID.
|
|
23
|
+
devices: Dictionary of Device objects keyed by device ID.
|
|
24
|
+
"""
|
|
17
25
|
|
|
18
26
|
def __init__(self, auth: Authenticator, timezone, lang) -> None:
|
|
19
27
|
self._api: Api = Api(auth=auth, tz=timezone, lang=lang)
|
|
@@ -48,7 +56,12 @@ class NintendoParental:
|
|
|
48
56
|
_LOGGER.debug("Found %s device(s)", len(self.devices))
|
|
49
57
|
|
|
50
58
|
async def update(self):
|
|
51
|
-
"""Update module data.
|
|
59
|
+
"""Update module data.
|
|
60
|
+
|
|
61
|
+
Refreshes all devices and their associated data from Nintendo's servers.
|
|
62
|
+
This method fetches the latest information about all devices linked to
|
|
63
|
+
the authenticated account.
|
|
64
|
+
"""
|
|
52
65
|
_LOGGER.debug("Received request to update data.")
|
|
53
66
|
await self._get_devices()
|
|
54
67
|
_LOGGER.debug("Update complete.")
|
|
@@ -57,7 +70,29 @@ class NintendoParental:
|
|
|
57
70
|
async def create(
|
|
58
71
|
cls, auth: Authenticator, timezone: str = "Europe/London", lang: str = "en-GB"
|
|
59
72
|
) -> "NintendoParental":
|
|
60
|
-
"""Create an instance of NintendoParental.
|
|
73
|
+
"""Create an instance of NintendoParental.
|
|
74
|
+
|
|
75
|
+
This is the recommended way to create a NintendoParental instance as it
|
|
76
|
+
handles the asynchronous initialization and fetches initial device data.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
auth: An authenticated Authenticator instance.
|
|
80
|
+
timezone: The timezone to use for API requests (default: "Europe/London").
|
|
81
|
+
Use any valid IANA timezone identifier.
|
|
82
|
+
lang: The language code for API responses (default: "en-GB").
|
|
83
|
+
Use ISO 639-1 language codes with ISO 3166-1 country codes.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
A fully initialized NintendoParental instance with device data loaded.
|
|
87
|
+
|
|
88
|
+
Example:
|
|
89
|
+
```python
|
|
90
|
+
async with aiohttp.ClientSession() as session:
|
|
91
|
+
auth = Authenticator(session_token, session)
|
|
92
|
+
await auth.async_complete_login(use_session_token=True)
|
|
93
|
+
nintendo = await NintendoParental.create(auth, timezone="America/New_York", lang="en-US")
|
|
94
|
+
```
|
|
95
|
+
"""
|
|
61
96
|
self = cls(auth, timezone, lang)
|
|
62
97
|
await self.update()
|
|
63
98
|
return self
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.3.2.1"
|
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
"""API handler."""
|
|
2
2
|
|
|
3
3
|
import aiohttp
|
|
4
|
-
|
|
5
4
|
from pynintendoauth.exceptions import HttpException
|
|
6
5
|
|
|
7
6
|
from .authenticator import Authenticator
|
|
8
7
|
from .const import (
|
|
9
|
-
|
|
8
|
+
_LOGGER,
|
|
10
9
|
BASE_URL,
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
DEVICE_MODEL,
|
|
11
|
+
ENDPOINTS,
|
|
13
12
|
MOBILE_APP_BUILD,
|
|
13
|
+
MOBILE_APP_PKG,
|
|
14
14
|
MOBILE_APP_VERSION,
|
|
15
|
-
OS_VERSION,
|
|
16
15
|
OS_NAME,
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
OS_VERSION,
|
|
17
|
+
USER_AGENT,
|
|
19
18
|
)
|
|
20
19
|
|
|
21
20
|
|
|
@@ -80,9 +79,7 @@ class Api:
|
|
|
80
79
|
try:
|
|
81
80
|
error: dict = await response.json()
|
|
82
81
|
if "detail" in error:
|
|
83
|
-
raise HttpException(
|
|
84
|
-
response.status, error["detail"], error.get("errorCode")
|
|
85
|
-
)
|
|
82
|
+
raise HttpException(response.status, error["detail"], error.get("errorCode"))
|
|
86
83
|
except (aiohttp.ContentTypeError, ValueError):
|
|
87
84
|
# Fall through to the generic exception below on parsing failure.
|
|
88
85
|
pass
|
|
@@ -114,31 +111,21 @@ class Api:
|
|
|
114
111
|
|
|
115
112
|
async def async_get_account_device(self, device_id: str) -> dict:
|
|
116
113
|
"""Get account device."""
|
|
117
|
-
return await self.send_request(
|
|
118
|
-
endpoint="get_account_device", DEVICE_ID=device_id
|
|
119
|
-
)
|
|
114
|
+
return await self.send_request(endpoint="get_account_device", DEVICE_ID=device_id)
|
|
120
115
|
|
|
121
116
|
async def async_get_device_daily_summaries(self, device_id: str) -> dict:
|
|
122
117
|
"""Get device daily summaries."""
|
|
123
|
-
return await self.send_request(
|
|
124
|
-
endpoint="get_device_daily_summaries", DEVICE_ID=device_id
|
|
125
|
-
)
|
|
118
|
+
return await self.send_request(endpoint="get_device_daily_summaries", DEVICE_ID=device_id)
|
|
126
119
|
|
|
127
120
|
async def async_get_device_monthly_summaries(self, device_id: str) -> dict:
|
|
128
121
|
"""Get device monthly summaries."""
|
|
129
|
-
return await self.send_request(
|
|
130
|
-
endpoint="get_device_monthly_summaries", DEVICE_ID=device_id
|
|
131
|
-
)
|
|
122
|
+
return await self.send_request(endpoint="get_device_monthly_summaries", DEVICE_ID=device_id)
|
|
132
123
|
|
|
133
124
|
async def async_get_device_parental_control_setting(self, device_id: str) -> dict:
|
|
134
125
|
"""Get device parental control setting."""
|
|
135
|
-
return await self.send_request(
|
|
136
|
-
endpoint="get_device_parental_control_setting", DEVICE_ID=device_id
|
|
137
|
-
)
|
|
126
|
+
return await self.send_request(endpoint="get_device_parental_control_setting", DEVICE_ID=device_id)
|
|
138
127
|
|
|
139
|
-
async def async_get_device_monthly_summary(
|
|
140
|
-
self, device_id: str, year: int, month: int
|
|
141
|
-
) -> dict:
|
|
128
|
+
async def async_get_device_monthly_summary(self, device_id: str, year: int, month: int) -> dict:
|
|
142
129
|
"""Get device monthly summary."""
|
|
143
130
|
return await self.send_request(
|
|
144
131
|
endpoint="get_device_monthly_summary",
|
|
@@ -147,9 +134,7 @@ class Api:
|
|
|
147
134
|
MONTH=f"{month:02d}",
|
|
148
135
|
)
|
|
149
136
|
|
|
150
|
-
async def async_update_restriction_level(
|
|
151
|
-
self, device_id: str, parental_control_setting: dict
|
|
152
|
-
) -> dict:
|
|
137
|
+
async def async_update_restriction_level(self, device_id: str, parental_control_setting: dict) -> dict:
|
|
153
138
|
"""Update device restriction level."""
|
|
154
139
|
allowed_keys = (
|
|
155
140
|
"whitelistedApplicationList",
|
|
@@ -159,18 +144,12 @@ class Api:
|
|
|
159
144
|
"deviceId": device_id,
|
|
160
145
|
"customSettings": parental_control_setting.get("customSettings", {}),
|
|
161
146
|
"parentalControlSettingEtag": parental_control_setting.get("etag"),
|
|
162
|
-
"vrRestrictionEtag": parental_control_setting.get("customSettings", {}).get(
|
|
163
|
-
"vrRestrictionEtag"
|
|
164
|
-
),
|
|
147
|
+
"vrRestrictionEtag": parental_control_setting.get("customSettings", {}).get("vrRestrictionEtag"),
|
|
165
148
|
**{key: parental_control_setting.get(key) for key in allowed_keys},
|
|
166
149
|
}
|
|
167
|
-
return await self.send_request(
|
|
168
|
-
endpoint="update_restriction_level", body=settings
|
|
169
|
-
)
|
|
150
|
+
return await self.send_request(endpoint="update_restriction_level", body=settings)
|
|
170
151
|
|
|
171
|
-
async def async_update_play_timer(
|
|
172
|
-
self, device_id: str, play_timer_regulations: dict
|
|
173
|
-
) -> dict:
|
|
152
|
+
async def async_update_play_timer(self, device_id: str, play_timer_regulations: dict) -> dict:
|
|
174
153
|
"""Update device play timer settings."""
|
|
175
154
|
allowed_ptr_keys = (
|
|
176
155
|
"timerMode",
|
|
@@ -180,9 +159,7 @@ class Api:
|
|
|
180
159
|
)
|
|
181
160
|
settings = {
|
|
182
161
|
"deviceId": device_id,
|
|
183
|
-
"playTimerRegulations": {
|
|
184
|
-
key: play_timer_regulations.get(key) for key in allowed_ptr_keys
|
|
185
|
-
},
|
|
162
|
+
"playTimerRegulations": {key: play_timer_regulations.get(key) for key in allowed_ptr_keys},
|
|
186
163
|
}
|
|
187
164
|
return await self.send_request(endpoint="update_play_timer", body=settings)
|
|
188
165
|
|
|
@@ -193,9 +170,7 @@ class Api:
|
|
|
193
170
|
body={"deviceId": device_id, "unlockCode": str(new_code)},
|
|
194
171
|
)
|
|
195
172
|
|
|
196
|
-
async def async_update_extra_playing_time(
|
|
197
|
-
self, device_id: str, additional_time: int
|
|
198
|
-
) -> dict:
|
|
173
|
+
async def async_update_extra_playing_time(self, device_id: str, additional_time: int) -> dict:
|
|
199
174
|
"""Update device extra playing time."""
|
|
200
175
|
body = {
|
|
201
176
|
"deviceId": device_id,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
4
|
from datetime import datetime
|
|
5
|
-
from typing import
|
|
5
|
+
from typing import TYPE_CHECKING, Callable
|
|
6
6
|
|
|
7
7
|
from .api import Api
|
|
8
8
|
from .const import _LOGGER
|
|
@@ -14,7 +14,20 @@ if TYPE_CHECKING:
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class Application:
|
|
17
|
-
"""
|
|
17
|
+
"""A Nintendo Switch game or application.
|
|
18
|
+
|
|
19
|
+
Represents a game or application on a Nintendo Switch console with parental control settings.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
application_id: Unique identifier for the application.
|
|
23
|
+
name: Display name of the application.
|
|
24
|
+
image_url: URL to the application's icon image.
|
|
25
|
+
safe_launch_setting: Whether the app is on the Allow List (bypasses age restrictions).
|
|
26
|
+
today_time_played: Total time played today across all players in minutes.
|
|
27
|
+
first_played_date: Date when the application was first played.
|
|
28
|
+
playing_days: Number of days the application has been played.
|
|
29
|
+
shop_url: URL to the application in the Nintendo eShop.
|
|
30
|
+
"""
|
|
18
31
|
|
|
19
32
|
def __init__(
|
|
20
33
|
self,
|
|
@@ -48,11 +61,27 @@ class Application:
|
|
|
48
61
|
callbacks.append(self._internal_update_callback)
|
|
49
62
|
|
|
50
63
|
async def set_safe_launch_setting(self, safe_launch_setting: SafeLaunchSetting):
|
|
51
|
-
"""Set the
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
64
|
+
"""Set the application's status on the Allow List.
|
|
65
|
+
|
|
66
|
+
Applications on the Allow List can bypass general age/content restrictions.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
safe_launch_setting: The setting to apply. Options are:
|
|
70
|
+
- SafeLaunchSetting.NONE: Remove from Allow List (apply normal restrictions).
|
|
71
|
+
- SafeLaunchSetting.ALLOW: Add to Allow List (bypass restrictions).
|
|
72
|
+
|
|
73
|
+
Raises:
|
|
74
|
+
ValueError: If the application data is not properly initialized.
|
|
75
|
+
LookupError: If the application is no longer in the whitelist.
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
```python
|
|
79
|
+
from pynintendoparental.enum import SafeLaunchSetting
|
|
80
|
+
|
|
81
|
+
await app.set_safe_launch_setting(SafeLaunchSetting.ALLOW)
|
|
82
|
+
```
|
|
83
|
+
"""
|
|
84
|
+
if not self._device or "whitelistedApplicationList" not in self._parental_control_settings:
|
|
56
85
|
raise ValueError("Unable to set SafeLaunchSetting, callbacks not executed.")
|
|
57
86
|
# Update the application safe_launch_setting in the PCS
|
|
58
87
|
pcs = copy.deepcopy(self._parental_control_settings)
|
|
@@ -61,9 +90,7 @@ class Application:
|
|
|
61
90
|
app["safeLaunch"] = str(safe_launch_setting)
|
|
62
91
|
break
|
|
63
92
|
else:
|
|
64
|
-
raise LookupError(
|
|
65
|
-
"Unable to set SafeLaunchSetting, application no longer in whitelist."
|
|
66
|
-
)
|
|
93
|
+
raise LookupError("Unable to set SafeLaunchSetting, application no longer in whitelist.")
|
|
67
94
|
|
|
68
95
|
await self._send_api_update(
|
|
69
96
|
self._api.async_update_restriction_level,
|
|
@@ -92,23 +119,16 @@ class Application:
|
|
|
92
119
|
device.device_id,
|
|
93
120
|
self.application_id,
|
|
94
121
|
)
|
|
95
|
-
for app in self._parental_control_settings.get(
|
|
96
|
-
"whitelistedApplicationList", []
|
|
97
|
-
):
|
|
122
|
+
for app in self._parental_control_settings.get("whitelistedApplicationList", []):
|
|
98
123
|
if app["applicationId"].upper() == self.application_id.upper():
|
|
99
|
-
self.safe_launch_setting = SafeLaunchSetting(
|
|
100
|
-
app.get("safeLaunch", "NONE")
|
|
101
|
-
)
|
|
124
|
+
self.safe_launch_setting = SafeLaunchSetting(app.get("safeLaunch", "NONE"))
|
|
102
125
|
self.image_url = app["imageUri"]
|
|
103
126
|
break
|
|
104
127
|
total_time_played: int = 0
|
|
105
128
|
if self._daily_summary:
|
|
106
129
|
for player_summary in self._daily_summary[0].get("players", []):
|
|
107
130
|
for player_app in player_summary.get("playedGames", []):
|
|
108
|
-
if (
|
|
109
|
-
player_app["meta"]["applicationId"].upper()
|
|
110
|
-
== self.application_id.upper()
|
|
111
|
-
):
|
|
131
|
+
if player_app["meta"]["applicationId"].upper() == self.application_id.upper():
|
|
112
132
|
total_time_played += player_app["playingTime"]
|
|
113
133
|
break
|
|
114
134
|
self.today_time_played = total_time_played
|
|
@@ -119,14 +139,36 @@ class Application:
|
|
|
119
139
|
else:
|
|
120
140
|
cb(self)
|
|
121
141
|
|
|
122
|
-
def add_application_callback(self, callback):
|
|
123
|
-
"""Add a callback to
|
|
142
|
+
def add_application_callback(self, callback: Callable):
|
|
143
|
+
"""Add a callback function to be called when application state changes.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
callback: A callable function. Can be sync or async.
|
|
147
|
+
|
|
148
|
+
Raises:
|
|
149
|
+
ValueError: If the provided object is not callable.
|
|
150
|
+
|
|
151
|
+
Example:
|
|
152
|
+
```python
|
|
153
|
+
async def on_app_update(app):
|
|
154
|
+
print(f"App {app.name} updated!")
|
|
155
|
+
|
|
156
|
+
app.add_application_callback(on_app_update)
|
|
157
|
+
```
|
|
158
|
+
"""
|
|
124
159
|
if not callable(callback):
|
|
125
160
|
raise ValueError("Object must be callable.")
|
|
126
161
|
self._callbacks.append(callback)
|
|
127
162
|
|
|
128
|
-
def remove_application_callback(self, callback):
|
|
129
|
-
"""Remove a
|
|
163
|
+
def remove_application_callback(self, callback: Callable):
|
|
164
|
+
"""Remove a previously registered application callback.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
callback: The callback function to remove.
|
|
168
|
+
|
|
169
|
+
Raises:
|
|
170
|
+
ValueError: If the callback is not found.
|
|
171
|
+
"""
|
|
130
172
|
if callback not in self._callbacks:
|
|
131
173
|
raise ValueError("Callback not found.")
|
|
132
174
|
self._callbacks.remove(callback)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""Nintendo Authentication."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pynintendoauth import NintendoAuth
|
|
6
|
+
|
|
7
|
+
from .const import CLIENT_ID
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Authenticator(NintendoAuth):
|
|
11
|
+
"""Nintendo authentication handler.
|
|
12
|
+
|
|
13
|
+
Handles authentication with Nintendo's servers for accessing Parental Controls API.
|
|
14
|
+
Supports both session token and interactive login methods.
|
|
15
|
+
|
|
16
|
+
Attributes:
|
|
17
|
+
session_token: The session token for authentication.
|
|
18
|
+
account_id: The authenticated Nintendo account ID.
|
|
19
|
+
login_url: URL for interactive login (when session_token not provided).
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
Using a session token:
|
|
23
|
+
```python
|
|
24
|
+
async with aiohttp.ClientSession() as session:
|
|
25
|
+
auth = Authenticator(session_token="YOUR_TOKEN", client_session=session)
|
|
26
|
+
await auth.async_complete_login(use_session_token=True)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Interactive login:
|
|
30
|
+
```python
|
|
31
|
+
async with aiohttp.ClientSession() as session:
|
|
32
|
+
auth = Authenticator(client_session=session)
|
|
33
|
+
print(f"Visit: {auth.login_url}")
|
|
34
|
+
response_url = input("Paste redirect URL: ")
|
|
35
|
+
await auth.async_complete_login(response_url)
|
|
36
|
+
```
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self, session_token=None, client_session=None):
|
|
40
|
+
super().__init__(
|
|
41
|
+
client_id=CLIENT_ID,
|
|
42
|
+
session_token=session_token,
|
|
43
|
+
client_session=client_session,
|
|
44
|
+
)
|
|
@@ -59,7 +59,9 @@ ENDPOINTS = {
|
|
|
59
59
|
"method": "POST",
|
|
60
60
|
},
|
|
61
61
|
"get_device_monthly_summary": {
|
|
62
|
-
"url":
|
|
62
|
+
"url": (
|
|
63
|
+
"{BASE_URL}/v2/actions/playSummary/fetchMonthlySummary?deviceId={DEVICE_ID}&year={YEAR}&month={MONTH}&containLatest=false"
|
|
64
|
+
),
|
|
63
65
|
"method": "GET",
|
|
64
66
|
},
|
|
65
67
|
"update_extra_playing_time": {
|