rbr-api-fork 0.7.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.
- rbr_api_fork-0.7.1/LICENSE +21 -0
- rbr_api_fork-0.7.1/PKG-INFO +171 -0
- rbr_api_fork-0.7.1/README.md +154 -0
- rbr_api_fork-0.7.1/pyproject.toml +39 -0
- rbr_api_fork-0.7.1/rbr_api_fork.egg-info/PKG-INFO +171 -0
- rbr_api_fork-0.7.1/rbr_api_fork.egg-info/SOURCES.txt +12 -0
- rbr_api_fork-0.7.1/rbr_api_fork.egg-info/dependency_links.txt +1 -0
- rbr_api_fork-0.7.1/rbr_api_fork.egg-info/requires.txt +1 -0
- rbr_api_fork-0.7.1/rbr_api_fork.egg-info/top_level.txt +2 -0
- rbr_api_fork-0.7.1/rbrapi/__init__.py +327 -0
- rbr_api_fork-0.7.1/rbrapi/errors.py +46 -0
- rbr_api_fork-0.7.1/rbrapi/session.py +64 -0
- rbr_api_fork-0.7.1/rbrapi/types.py +195 -0
- rbr_api_fork-0.7.1/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 VWH
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rbr-api-fork
|
|
3
|
+
Version: 0.7.1
|
|
4
|
+
Summary: Unofficial Python Client for Rocket Bot Royale Game API
|
|
5
|
+
Author-email: VWH <vwhe@proton.me>
|
|
6
|
+
Project-URL: Homepage, https://github.com/arenaslucas/rbr-api
|
|
7
|
+
Project-URL: Issues, https://github.com/arenaslucas/rbr-api/issues
|
|
8
|
+
Keywords: Rocket Bot Royale,game API,Unofficial API,Python library
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# Unofficial Client for RocketBotRoyale Game API
|
|
19
|
+
|
|
20
|
+
[](https://pepy.tech/project/rbrapi)
|
|
21
|
+
|
|
22
|
+
**⚠️️ For Educational Use Only!**
|
|
23
|
+
|
|
24
|
+
This is an unofficial Python client for the Rocket Bot Royale game API. It allows users to interact with the game API, including authenticating, retrieving account details, collecting timed bonuses, sending friend requests, and purchasing crates.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Install the package using pip:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
pip install -U rbrapi
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Initialization
|
|
37
|
+
|
|
38
|
+
Initialize a `RocketBotRoyale` instance with an email and password:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from rbrapi import RocketBotRoyale
|
|
42
|
+
from rbrapi.errors import AuthenticationError
|
|
43
|
+
|
|
44
|
+
# Initialize with email and password
|
|
45
|
+
client = RocketBotRoyale(email="email@example.com", password="your_password")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Authentication
|
|
49
|
+
|
|
50
|
+
Authenticate with the RocketBotRoyale API using provided credentials:
|
|
51
|
+
|
|
52
|
+
> **Note:** It auto-authenticates when `RocketBotRoyale` is initialized. Use this only for regenerating the session token.
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
try:
|
|
56
|
+
client.authenticate()
|
|
57
|
+
print("Authentication successful!")
|
|
58
|
+
except AuthenticationError as e:
|
|
59
|
+
print(f"Authentication failed: {e}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Account Details
|
|
63
|
+
|
|
64
|
+
Retrieve account details:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
try:
|
|
68
|
+
account_details = client.account()
|
|
69
|
+
print(f"Account ID: {account_details.custom_id}")
|
|
70
|
+
print(f"Username: {account_details.user["username"]}")
|
|
71
|
+
print(f"Gems: {account_details.wallet["gems"]}")
|
|
72
|
+
print(f"Coins: {account_details.wallet["coins"]}")
|
|
73
|
+
except AuthenticationError as e:
|
|
74
|
+
print(f"Authentication failed: {e}")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Collect Timed Bonus
|
|
78
|
+
|
|
79
|
+
Collect a timed bonus:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from rbrapi.errors import CollectTimedBonusError
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
success = client.collect_timed_bonus()
|
|
86
|
+
if success:
|
|
87
|
+
print("Timed bonus collected successfully!")
|
|
88
|
+
else:
|
|
89
|
+
print("Failed to collect timed bonus.")
|
|
90
|
+
except AuthenticationError as e:
|
|
91
|
+
print(f"Authentication failed: {e}")
|
|
92
|
+
except CollectTimedBonusError as e:
|
|
93
|
+
print(f"Failed to collect timed bonus: {e}")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Send Friend Request
|
|
97
|
+
|
|
98
|
+
Send a friend request to another user:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from rbrapi.errors import FriendRequestError
|
|
102
|
+
|
|
103
|
+
friend_code = "c2829d50"
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
success = client.send_friend_request(friend_code)
|
|
107
|
+
if success:
|
|
108
|
+
print("Friend request sent successfully!")
|
|
109
|
+
else:
|
|
110
|
+
print("Failed to send friend request.")
|
|
111
|
+
except AuthenticationError as e:
|
|
112
|
+
print(f"Authentication failed: {e}")
|
|
113
|
+
except FriendRequestError as e:
|
|
114
|
+
print(f"Failed to send friend request: {e}")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Convert Friend Code to User ID
|
|
118
|
+
|
|
119
|
+
Convert a friend's code to their user ID:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from rbrapi.errors import AuthenticationError, userNotExistError
|
|
123
|
+
|
|
124
|
+
friend_code = "c2829d50"
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
user_id = client.friend_code_to_id(friend_code)
|
|
128
|
+
print(f"User ID: {user_id}")
|
|
129
|
+
except AuthenticationError as e:
|
|
130
|
+
print(f"Authentication failed: {e}")
|
|
131
|
+
except userNotExistError as e:
|
|
132
|
+
print(f"User does not exist: {e}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Purchase Crate
|
|
136
|
+
|
|
137
|
+
Purchase a crate (regular or elite):
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from rbrapi.errors import LootBoxError
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
crate_details = client.buy_crate(elite=False) # Set elite=True for elite crate
|
|
144
|
+
print("Crate purchased successfully!")
|
|
145
|
+
print(f"Crate details: {crate_details}")
|
|
146
|
+
except AuthenticationError as e:
|
|
147
|
+
print(f"Authentication failed: {e}")
|
|
148
|
+
except LootBoxError as e:
|
|
149
|
+
print(f"Failed to purchase crate: {e}")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Sign Up New User
|
|
153
|
+
|
|
154
|
+
Make a new account with the RocketBotRoyale API:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from rbrapi.errors import SignUpError
|
|
158
|
+
|
|
159
|
+
email = "new_user@example.com"
|
|
160
|
+
password = "new_password"
|
|
161
|
+
username = "new_username"
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
success = RocketBotRoyale.signup(email, password, username)
|
|
165
|
+
if success:
|
|
166
|
+
print(f"User {username} signed up successfully!")
|
|
167
|
+
else:
|
|
168
|
+
print("Failed to sign up user.")
|
|
169
|
+
except SignUpError as e:
|
|
170
|
+
print(f"Failed to sign up user: {e}")
|
|
171
|
+
```
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Unofficial Client for RocketBotRoyale Game API
|
|
2
|
+
|
|
3
|
+
[](https://pepy.tech/project/rbrapi)
|
|
4
|
+
|
|
5
|
+
**⚠️️ For Educational Use Only!**
|
|
6
|
+
|
|
7
|
+
This is an unofficial Python client for the Rocket Bot Royale game API. It allows users to interact with the game API, including authenticating, retrieving account details, collecting timed bonuses, sending friend requests, and purchasing crates.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Install the package using pip:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
pip install -U rbrapi
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
### Initialization
|
|
20
|
+
|
|
21
|
+
Initialize a `RocketBotRoyale` instance with an email and password:
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
from rbrapi import RocketBotRoyale
|
|
25
|
+
from rbrapi.errors import AuthenticationError
|
|
26
|
+
|
|
27
|
+
# Initialize with email and password
|
|
28
|
+
client = RocketBotRoyale(email="email@example.com", password="your_password")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Authentication
|
|
32
|
+
|
|
33
|
+
Authenticate with the RocketBotRoyale API using provided credentials:
|
|
34
|
+
|
|
35
|
+
> **Note:** It auto-authenticates when `RocketBotRoyale` is initialized. Use this only for regenerating the session token.
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
try:
|
|
39
|
+
client.authenticate()
|
|
40
|
+
print("Authentication successful!")
|
|
41
|
+
except AuthenticationError as e:
|
|
42
|
+
print(f"Authentication failed: {e}")
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Account Details
|
|
46
|
+
|
|
47
|
+
Retrieve account details:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
try:
|
|
51
|
+
account_details = client.account()
|
|
52
|
+
print(f"Account ID: {account_details.custom_id}")
|
|
53
|
+
print(f"Username: {account_details.user["username"]}")
|
|
54
|
+
print(f"Gems: {account_details.wallet["gems"]}")
|
|
55
|
+
print(f"Coins: {account_details.wallet["coins"]}")
|
|
56
|
+
except AuthenticationError as e:
|
|
57
|
+
print(f"Authentication failed: {e}")
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Collect Timed Bonus
|
|
61
|
+
|
|
62
|
+
Collect a timed bonus:
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from rbrapi.errors import CollectTimedBonusError
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
success = client.collect_timed_bonus()
|
|
69
|
+
if success:
|
|
70
|
+
print("Timed bonus collected successfully!")
|
|
71
|
+
else:
|
|
72
|
+
print("Failed to collect timed bonus.")
|
|
73
|
+
except AuthenticationError as e:
|
|
74
|
+
print(f"Authentication failed: {e}")
|
|
75
|
+
except CollectTimedBonusError as e:
|
|
76
|
+
print(f"Failed to collect timed bonus: {e}")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Send Friend Request
|
|
80
|
+
|
|
81
|
+
Send a friend request to another user:
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from rbrapi.errors import FriendRequestError
|
|
85
|
+
|
|
86
|
+
friend_code = "c2829d50"
|
|
87
|
+
|
|
88
|
+
try:
|
|
89
|
+
success = client.send_friend_request(friend_code)
|
|
90
|
+
if success:
|
|
91
|
+
print("Friend request sent successfully!")
|
|
92
|
+
else:
|
|
93
|
+
print("Failed to send friend request.")
|
|
94
|
+
except AuthenticationError as e:
|
|
95
|
+
print(f"Authentication failed: {e}")
|
|
96
|
+
except FriendRequestError as e:
|
|
97
|
+
print(f"Failed to send friend request: {e}")
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Convert Friend Code to User ID
|
|
101
|
+
|
|
102
|
+
Convert a friend's code to their user ID:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from rbrapi.errors import AuthenticationError, userNotExistError
|
|
106
|
+
|
|
107
|
+
friend_code = "c2829d50"
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
user_id = client.friend_code_to_id(friend_code)
|
|
111
|
+
print(f"User ID: {user_id}")
|
|
112
|
+
except AuthenticationError as e:
|
|
113
|
+
print(f"Authentication failed: {e}")
|
|
114
|
+
except userNotExistError as e:
|
|
115
|
+
print(f"User does not exist: {e}")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Purchase Crate
|
|
119
|
+
|
|
120
|
+
Purchase a crate (regular or elite):
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from rbrapi.errors import LootBoxError
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
crate_details = client.buy_crate(elite=False) # Set elite=True for elite crate
|
|
127
|
+
print("Crate purchased successfully!")
|
|
128
|
+
print(f"Crate details: {crate_details}")
|
|
129
|
+
except AuthenticationError as e:
|
|
130
|
+
print(f"Authentication failed: {e}")
|
|
131
|
+
except LootBoxError as e:
|
|
132
|
+
print(f"Failed to purchase crate: {e}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Sign Up New User
|
|
136
|
+
|
|
137
|
+
Make a new account with the RocketBotRoyale API:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from rbrapi.errors import SignUpError
|
|
141
|
+
|
|
142
|
+
email = "new_user@example.com"
|
|
143
|
+
password = "new_password"
|
|
144
|
+
username = "new_username"
|
|
145
|
+
|
|
146
|
+
try:
|
|
147
|
+
success = RocketBotRoyale.signup(email, password, username)
|
|
148
|
+
if success:
|
|
149
|
+
print(f"User {username} signed up successfully!")
|
|
150
|
+
else:
|
|
151
|
+
print("Failed to sign up user.")
|
|
152
|
+
except SignUpError as e:
|
|
153
|
+
print(f"Failed to sign up user: {e}")
|
|
154
|
+
```
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
|
|
3
|
+
name = "rbr-api-fork"
|
|
4
|
+
version = "0.7.1"
|
|
5
|
+
|
|
6
|
+
authors = [
|
|
7
|
+
{ name="VWH", email="vwhe@proton.me" },
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
description = "Unofficial Python Client for Rocket Bot Royale Game API"
|
|
11
|
+
readme = "README.md"
|
|
12
|
+
requires-python = ">=3.8"
|
|
13
|
+
|
|
14
|
+
keywords = [
|
|
15
|
+
"Rocket Bot Royale",
|
|
16
|
+
"game API",
|
|
17
|
+
"Unofficial API",
|
|
18
|
+
"Python library",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"License :: OSI Approved :: MIT License",
|
|
24
|
+
"Operating System :: OS Independent",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
dependencies = [
|
|
28
|
+
"requests",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/arenaslucas/rbr-api"
|
|
33
|
+
Issues = "https://github.com/arenaslucas/rbr-api/issues"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools]
|
|
36
|
+
include-package-data = false
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.packages.find]
|
|
39
|
+
exclude = ["examples"]
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rbr-api-fork
|
|
3
|
+
Version: 0.7.1
|
|
4
|
+
Summary: Unofficial Python Client for Rocket Bot Royale Game API
|
|
5
|
+
Author-email: VWH <vwhe@proton.me>
|
|
6
|
+
Project-URL: Homepage, https://github.com/arenaslucas/rbr-api
|
|
7
|
+
Project-URL: Issues, https://github.com/arenaslucas/rbr-api/issues
|
|
8
|
+
Keywords: Rocket Bot Royale,game API,Unofficial API,Python library
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests
|
|
16
|
+
Dynamic: license-file
|
|
17
|
+
|
|
18
|
+
# Unofficial Client for RocketBotRoyale Game API
|
|
19
|
+
|
|
20
|
+
[](https://pepy.tech/project/rbrapi)
|
|
21
|
+
|
|
22
|
+
**⚠️️ For Educational Use Only!**
|
|
23
|
+
|
|
24
|
+
This is an unofficial Python client for the Rocket Bot Royale game API. It allows users to interact with the game API, including authenticating, retrieving account details, collecting timed bonuses, sending friend requests, and purchasing crates.
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
Install the package using pip:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
pip install -U rbrapi
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### Initialization
|
|
37
|
+
|
|
38
|
+
Initialize a `RocketBotRoyale` instance with an email and password:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
from rbrapi import RocketBotRoyale
|
|
42
|
+
from rbrapi.errors import AuthenticationError
|
|
43
|
+
|
|
44
|
+
# Initialize with email and password
|
|
45
|
+
client = RocketBotRoyale(email="email@example.com", password="your_password")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Authentication
|
|
49
|
+
|
|
50
|
+
Authenticate with the RocketBotRoyale API using provided credentials:
|
|
51
|
+
|
|
52
|
+
> **Note:** It auto-authenticates when `RocketBotRoyale` is initialized. Use this only for regenerating the session token.
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
try:
|
|
56
|
+
client.authenticate()
|
|
57
|
+
print("Authentication successful!")
|
|
58
|
+
except AuthenticationError as e:
|
|
59
|
+
print(f"Authentication failed: {e}")
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Account Details
|
|
63
|
+
|
|
64
|
+
Retrieve account details:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
try:
|
|
68
|
+
account_details = client.account()
|
|
69
|
+
print(f"Account ID: {account_details.custom_id}")
|
|
70
|
+
print(f"Username: {account_details.user["username"]}")
|
|
71
|
+
print(f"Gems: {account_details.wallet["gems"]}")
|
|
72
|
+
print(f"Coins: {account_details.wallet["coins"]}")
|
|
73
|
+
except AuthenticationError as e:
|
|
74
|
+
print(f"Authentication failed: {e}")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Collect Timed Bonus
|
|
78
|
+
|
|
79
|
+
Collect a timed bonus:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from rbrapi.errors import CollectTimedBonusError
|
|
83
|
+
|
|
84
|
+
try:
|
|
85
|
+
success = client.collect_timed_bonus()
|
|
86
|
+
if success:
|
|
87
|
+
print("Timed bonus collected successfully!")
|
|
88
|
+
else:
|
|
89
|
+
print("Failed to collect timed bonus.")
|
|
90
|
+
except AuthenticationError as e:
|
|
91
|
+
print(f"Authentication failed: {e}")
|
|
92
|
+
except CollectTimedBonusError as e:
|
|
93
|
+
print(f"Failed to collect timed bonus: {e}")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Send Friend Request
|
|
97
|
+
|
|
98
|
+
Send a friend request to another user:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from rbrapi.errors import FriendRequestError
|
|
102
|
+
|
|
103
|
+
friend_code = "c2829d50"
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
success = client.send_friend_request(friend_code)
|
|
107
|
+
if success:
|
|
108
|
+
print("Friend request sent successfully!")
|
|
109
|
+
else:
|
|
110
|
+
print("Failed to send friend request.")
|
|
111
|
+
except AuthenticationError as e:
|
|
112
|
+
print(f"Authentication failed: {e}")
|
|
113
|
+
except FriendRequestError as e:
|
|
114
|
+
print(f"Failed to send friend request: {e}")
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Convert Friend Code to User ID
|
|
118
|
+
|
|
119
|
+
Convert a friend's code to their user ID:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from rbrapi.errors import AuthenticationError, userNotExistError
|
|
123
|
+
|
|
124
|
+
friend_code = "c2829d50"
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
user_id = client.friend_code_to_id(friend_code)
|
|
128
|
+
print(f"User ID: {user_id}")
|
|
129
|
+
except AuthenticationError as e:
|
|
130
|
+
print(f"Authentication failed: {e}")
|
|
131
|
+
except userNotExistError as e:
|
|
132
|
+
print(f"User does not exist: {e}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Purchase Crate
|
|
136
|
+
|
|
137
|
+
Purchase a crate (regular or elite):
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from rbrapi.errors import LootBoxError
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
crate_details = client.buy_crate(elite=False) # Set elite=True for elite crate
|
|
144
|
+
print("Crate purchased successfully!")
|
|
145
|
+
print(f"Crate details: {crate_details}")
|
|
146
|
+
except AuthenticationError as e:
|
|
147
|
+
print(f"Authentication failed: {e}")
|
|
148
|
+
except LootBoxError as e:
|
|
149
|
+
print(f"Failed to purchase crate: {e}")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Sign Up New User
|
|
153
|
+
|
|
154
|
+
Make a new account with the RocketBotRoyale API:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from rbrapi.errors import SignUpError
|
|
158
|
+
|
|
159
|
+
email = "new_user@example.com"
|
|
160
|
+
password = "new_password"
|
|
161
|
+
username = "new_username"
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
success = RocketBotRoyale.signup(email, password, username)
|
|
165
|
+
if success:
|
|
166
|
+
print(f"User {username} signed up successfully!")
|
|
167
|
+
else:
|
|
168
|
+
print("Failed to sign up user.")
|
|
169
|
+
except SignUpError as e:
|
|
170
|
+
print(f"Failed to sign up user: {e}")
|
|
171
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
rbr_api_fork.egg-info/PKG-INFO
|
|
5
|
+
rbr_api_fork.egg-info/SOURCES.txt
|
|
6
|
+
rbr_api_fork.egg-info/dependency_links.txt
|
|
7
|
+
rbr_api_fork.egg-info/requires.txt
|
|
8
|
+
rbr_api_fork.egg-info/top_level.txt
|
|
9
|
+
rbrapi/__init__.py
|
|
10
|
+
rbrapi/errors.py
|
|
11
|
+
rbrapi/session.py
|
|
12
|
+
rbrapi/types.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
__version__ = "0.7.1"
|
|
4
|
+
|
|
5
|
+
from json import loads
|
|
6
|
+
from typing import Optional, Self
|
|
7
|
+
from uuid import uuid4
|
|
8
|
+
|
|
9
|
+
from .errors import (
|
|
10
|
+
AuthenticationError,
|
|
11
|
+
CollectTimedBonusError,
|
|
12
|
+
FriendRequestError,
|
|
13
|
+
LootBoxError,
|
|
14
|
+
SignUpError,
|
|
15
|
+
UnknownUserError,
|
|
16
|
+
)
|
|
17
|
+
from .session import make_request
|
|
18
|
+
from .types import (
|
|
19
|
+
AccountResponse,
|
|
20
|
+
AuthenticateResponse,
|
|
21
|
+
LootBoxResponses,
|
|
22
|
+
SignUpResponse,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
CLIENT_VERSION = "9999999999" # will never raise an AuthenticationError for having an older client version
|
|
26
|
+
BASE_URL = "https://dev-nakama.winterpixel.io/v2"
|
|
27
|
+
BASE_HEADERS = {
|
|
28
|
+
"accept": "application/json",
|
|
29
|
+
"authorization": "Basic OTAyaXViZGFmOWgyZTlocXBldzBmYjlhZWIzOTo=",
|
|
30
|
+
"origin": "https://rocketbotroyale2.winterpixel.io",
|
|
31
|
+
"referer": "https://rocketbotroyale2.winterpixel.io/",
|
|
32
|
+
"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
|
|
33
|
+
"content-type": "application/json",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class RocketBotRoyale:
|
|
38
|
+
def __init__(self: Self, email: str, password: str) -> None:
|
|
39
|
+
"""
|
|
40
|
+
Initialize RocketBotRoyale instance with email and password.
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
email (str): The account email.
|
|
44
|
+
password (str): The account password.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
self.email = email
|
|
48
|
+
self.password = password
|
|
49
|
+
self.token: Optional[str] = None
|
|
50
|
+
self.authenticate()
|
|
51
|
+
|
|
52
|
+
def authenticate(self: Self, timeout: Optional[int] = None) -> AuthenticateResponse:
|
|
53
|
+
"""
|
|
54
|
+
Authenticate the user.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
AuthenticateResponse: Response object containing authentication details.
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
AuthenticationError: If authentication fails.
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
data = {
|
|
67
|
+
"email": self.email,
|
|
68
|
+
"password": self.password,
|
|
69
|
+
"vars": {"client_version": CLIENT_VERSION},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
response = make_request(
|
|
73
|
+
f"{BASE_URL}/account/authenticate/email?create=false&",
|
|
74
|
+
headers=BASE_HEADERS,
|
|
75
|
+
json=data,
|
|
76
|
+
timeout=timeout,
|
|
77
|
+
error_if_not_ok=AuthenticationError,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
response_data = AuthenticateResponse.from_dict(response)
|
|
81
|
+
self.token = response_data.token
|
|
82
|
+
|
|
83
|
+
return response_data
|
|
84
|
+
|
|
85
|
+
def account(self: Self, timeout: Optional[int] = None) -> AccountResponse:
|
|
86
|
+
"""
|
|
87
|
+
Retrieve account details for the authenticated user.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
AccountResponse: Response object containing account details.
|
|
94
|
+
|
|
95
|
+
Raises:
|
|
96
|
+
AuthenticationError: If authentication token is missing or invalid.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
if not self.token:
|
|
100
|
+
raise AuthenticationError("Token not found or user is unauthenticated")
|
|
101
|
+
|
|
102
|
+
response = make_request(
|
|
103
|
+
method="GET",
|
|
104
|
+
url=f"{BASE_URL}/account",
|
|
105
|
+
headers={**BASE_HEADERS, "authorization": f"Bearer {self.token}"},
|
|
106
|
+
timeout=timeout,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
return AccountResponse.from_dict(response)
|
|
110
|
+
|
|
111
|
+
def collect_timed_bonus(self: Self, timeout: Optional[int] = None) -> bool:
|
|
112
|
+
"""
|
|
113
|
+
Collect timed bonus.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
bool: True if timed bonus collection was successful.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
AuthenticationError: If authentication token is missing or invalid.
|
|
123
|
+
CollectTimedBonusError: If collecting timed bonus fails.
|
|
124
|
+
"""
|
|
125
|
+
if not self.token:
|
|
126
|
+
raise AuthenticationError("Token not found or user is unauthenticated")
|
|
127
|
+
|
|
128
|
+
data = '"{}"'
|
|
129
|
+
make_request(
|
|
130
|
+
f"{BASE_URL}/rpc/collect_timed_bonus",
|
|
131
|
+
headers={
|
|
132
|
+
**BASE_HEADERS,
|
|
133
|
+
"authorization": f"Bearer {self.token}",
|
|
134
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
135
|
+
},
|
|
136
|
+
data=data,
|
|
137
|
+
error_if_not_ok=CollectTimedBonusError,
|
|
138
|
+
timeout=timeout,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
return True
|
|
142
|
+
|
|
143
|
+
def send_friend_request(
|
|
144
|
+
self: Self, friend_code: str, timeout: Optional[int] = None
|
|
145
|
+
) -> bool:
|
|
146
|
+
"""
|
|
147
|
+
Send a friend request.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
friend_code (str): The friend code of the user to send the friend request to.
|
|
151
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
bool: True if the friend request was sent successfully.
|
|
155
|
+
|
|
156
|
+
Raises:
|
|
157
|
+
AuthenticationError: If authentication token is missing or invalid.
|
|
158
|
+
FriendRequestError: If sending the friend request fails.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
if not self.token:
|
|
162
|
+
raise AuthenticationError("Token not found or user is unauthenticated")
|
|
163
|
+
|
|
164
|
+
data = '"{\\"friend_code\\":\\"' + friend_code + '\\"}"'
|
|
165
|
+
make_request(
|
|
166
|
+
f"{BASE_URL}/rpc/winterpixel_query_user_id_for_friend_code",
|
|
167
|
+
headers={
|
|
168
|
+
**BASE_HEADERS,
|
|
169
|
+
"authorization": f"Bearer {self.token}",
|
|
170
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
171
|
+
},
|
|
172
|
+
data=data,
|
|
173
|
+
error_if_not_ok=FriendRequestError,
|
|
174
|
+
timeout=timeout,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return True
|
|
178
|
+
|
|
179
|
+
def buy_crate(
|
|
180
|
+
self: Self, *, elite: bool = False, timeout: Optional[int] = None
|
|
181
|
+
) -> LootBoxResponses:
|
|
182
|
+
"""
|
|
183
|
+
Purchase a crate.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
elite (bool, optional): Indicates if the crate to be bought is elite. Defaults to False.
|
|
187
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
LootBoxResponses: Response object containing details of the purchased crate.
|
|
191
|
+
|
|
192
|
+
Raises:
|
|
193
|
+
AuthenticationError: If authentication token is missing or invalid.
|
|
194
|
+
LootBoxError: If purchasing the crate fails.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
if not self.token:
|
|
198
|
+
raise AuthenticationError("Token not found or user is unauthenticated")
|
|
199
|
+
|
|
200
|
+
data = f'"{{\\"unique\\":{"true" if elite else "false"}}}"'
|
|
201
|
+
response = make_request(
|
|
202
|
+
f"{BASE_URL}/rpc/tankkings_consume_lootbox",
|
|
203
|
+
headers={
|
|
204
|
+
**BASE_HEADERS,
|
|
205
|
+
"authorization": f"Bearer {self.token}",
|
|
206
|
+
"content-type": "application/json",
|
|
207
|
+
},
|
|
208
|
+
data=data,
|
|
209
|
+
error_if_not_ok=LootBoxError,
|
|
210
|
+
timeout=timeout,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
payload = response.get("payload")
|
|
214
|
+
|
|
215
|
+
if isinstance(payload, str):
|
|
216
|
+
payload = loads(payload)
|
|
217
|
+
|
|
218
|
+
if payload:
|
|
219
|
+
return LootBoxResponses.from_dict(payload)
|
|
220
|
+
|
|
221
|
+
raise LootBoxError(response.get("message", "Unable to buy crate"))
|
|
222
|
+
|
|
223
|
+
def friend_code_to_id(
|
|
224
|
+
self: Self, friend_code: str, timeout: Optional[int] = None
|
|
225
|
+
) -> str:
|
|
226
|
+
"""
|
|
227
|
+
Convert a friend code to a user ID.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
friend_code (str): The friend code to be converted to a user ID.
|
|
231
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
str: The user ID corresponding to the given friend code.
|
|
235
|
+
|
|
236
|
+
Raises:
|
|
237
|
+
AuthenticationError: If authentication token is missing or invalid.
|
|
238
|
+
userNotExistError: If the user with the given friend code does not exist or if the request fails.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
if not self.token:
|
|
242
|
+
raise AuthenticationError("Token not found or user is unauthenticated")
|
|
243
|
+
|
|
244
|
+
data = '"{\\"friend_code\\":\\"' + friend_code + '\\"}"'
|
|
245
|
+
response = make_request(
|
|
246
|
+
f"{BASE_URL}/rpc/winterpixel_query_user_id_for_friend_code",
|
|
247
|
+
headers={
|
|
248
|
+
**BASE_HEADERS,
|
|
249
|
+
"authorization": f"Bearer {self.token}",
|
|
250
|
+
"content-type": "application/json",
|
|
251
|
+
},
|
|
252
|
+
data=data,
|
|
253
|
+
error_if_not_ok=UnknownUserError,
|
|
254
|
+
timeout=timeout,
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
payload = response.get("payload")
|
|
258
|
+
|
|
259
|
+
if isinstance(payload, str):
|
|
260
|
+
payload = loads(payload)
|
|
261
|
+
|
|
262
|
+
if payload and payload.get("user_id"):
|
|
263
|
+
return payload.get("user_id")
|
|
264
|
+
|
|
265
|
+
raise UnknownUserError(response.get("message", "Unable to get user id"))
|
|
266
|
+
|
|
267
|
+
@staticmethod
|
|
268
|
+
def signup(
|
|
269
|
+
email: str, password: str, username: str, timeout: Optional[int] = None
|
|
270
|
+
) -> bool:
|
|
271
|
+
"""
|
|
272
|
+
Sign up a new user.
|
|
273
|
+
|
|
274
|
+
Args:
|
|
275
|
+
email (str): New account email.
|
|
276
|
+
password (str): New account password.
|
|
277
|
+
username (str): Display name for the new account.
|
|
278
|
+
timeout (int, optional): Timeout for the request in seconds.
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
bool: True if signup was successful.
|
|
282
|
+
|
|
283
|
+
Raises:
|
|
284
|
+
SignUpError: If signup fails.
|
|
285
|
+
"""
|
|
286
|
+
|
|
287
|
+
data = (
|
|
288
|
+
'"{\\"display_name\\":\\"'
|
|
289
|
+
+ username
|
|
290
|
+
+ '\\",\\"email\\":\\"'
|
|
291
|
+
+ email
|
|
292
|
+
+ '\\",\\"password\\":\\"'
|
|
293
|
+
+ password
|
|
294
|
+
+ '\\"}"'
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
temp_account = RocketBotRoyale.__custom_account()
|
|
298
|
+
make_request(
|
|
299
|
+
f"{BASE_URL}/rpc/winterpixel_signup",
|
|
300
|
+
headers={
|
|
301
|
+
**BASE_HEADERS,
|
|
302
|
+
"authorization": f"Bearer {temp_account.token}",
|
|
303
|
+
"content-type": "application/x-www-form-urlencoded",
|
|
304
|
+
},
|
|
305
|
+
data=data,
|
|
306
|
+
error_if_not_ok=SignUpError,
|
|
307
|
+
timeout=timeout,
|
|
308
|
+
)
|
|
309
|
+
|
|
310
|
+
return True
|
|
311
|
+
|
|
312
|
+
@staticmethod
|
|
313
|
+
def __custom_account(timeout: Optional[int] = None) -> SignUpResponse:
|
|
314
|
+
data = {
|
|
315
|
+
"id": f"{uuid4()}",
|
|
316
|
+
"vars": {"client_version": CLIENT_VERSION, "platform": "HTML5"},
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
response = make_request(
|
|
320
|
+
f"{BASE_URL}/account/authenticate/custom?create=true&",
|
|
321
|
+
headers=BASE_HEADERS,
|
|
322
|
+
json=data,
|
|
323
|
+
error_if_not_ok=AuthenticationError,
|
|
324
|
+
timeout=timeout,
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
return SignUpResponse.from_dict(response)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class AuthenticationError(Exception):
|
|
2
|
+
"""
|
|
3
|
+
Exception raised for errors in the authentication process.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SignUpError(Exception):
|
|
10
|
+
"""
|
|
11
|
+
Exception raised for errors during the sign-up process.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CollectTimedBonusError(Exception):
|
|
18
|
+
"""
|
|
19
|
+
Exception raised for errors in collecting the timed bonus.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class FriendRequestError(Exception):
|
|
26
|
+
"""
|
|
27
|
+
Exception raised for errors in sending a friend request.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class LootBoxError(Exception):
|
|
34
|
+
"""
|
|
35
|
+
Exception raised for errors in purchasing a loot box.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
pass
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class UnknownUserError(Exception):
|
|
42
|
+
"""
|
|
43
|
+
Exception raised for errors in sending a query to find a user.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
pass
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from datetime import UTC, datetime
|
|
4
|
+
from threading import local
|
|
5
|
+
from typing import Any, Optional
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
# Session time-to-live in seconds
|
|
10
|
+
SESSION_TIME_TO_LIVE = 600
|
|
11
|
+
|
|
12
|
+
# Thread-local storage for session and creation time
|
|
13
|
+
thread_local = local()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_session(*, reset: bool = False) -> requests.sessions.Session:
|
|
17
|
+
"""Return or create a requests session, reset if expired."""
|
|
18
|
+
if not hasattr(thread_local, "session") or reset:
|
|
19
|
+
thread_local.session = requests.sessions.Session()
|
|
20
|
+
thread_local.creation_time = datetime.now(tz=UTC)
|
|
21
|
+
|
|
22
|
+
if (
|
|
23
|
+
SESSION_TIME_TO_LIVE
|
|
24
|
+
and (datetime.now(tz=UTC) - thread_local.creation_time).total_seconds()
|
|
25
|
+
> SESSION_TIME_TO_LIVE
|
|
26
|
+
):
|
|
27
|
+
thread_local.session = requests.sessions.Session()
|
|
28
|
+
thread_local.creation_time = datetime.now(tz=UTC)
|
|
29
|
+
|
|
30
|
+
return thread_local.session
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def make_request(
|
|
34
|
+
url: str,
|
|
35
|
+
headers: Optional[dict[str, str]] = None,
|
|
36
|
+
json: Optional[dict[str, Any]] = None,
|
|
37
|
+
data: Optional[str] = None,
|
|
38
|
+
timeout: Optional[int] = 60,
|
|
39
|
+
method: str = "POST",
|
|
40
|
+
error_if_not_ok: Optional[Exception] = None,
|
|
41
|
+
) -> dict[str, Any]:
|
|
42
|
+
session = get_session()
|
|
43
|
+
|
|
44
|
+
if method == "POST":
|
|
45
|
+
response = session.post(
|
|
46
|
+
url,
|
|
47
|
+
timeout=timeout,
|
|
48
|
+
headers=headers,
|
|
49
|
+
json=json,
|
|
50
|
+
data=data,
|
|
51
|
+
)
|
|
52
|
+
else:
|
|
53
|
+
response = session.get(
|
|
54
|
+
url,
|
|
55
|
+
timeout=timeout,
|
|
56
|
+
headers=headers,
|
|
57
|
+
json=json,
|
|
58
|
+
data=data,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
if error_if_not_ok and not response.ok:
|
|
62
|
+
raise error_if_not_ok(response.json().get("message", "Unkown"))
|
|
63
|
+
|
|
64
|
+
return response.json()
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from json import dumps, loads
|
|
4
|
+
from typing import Any, Self, TypedDict
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class APIResponse:
|
|
8
|
+
def __init__(self: Self, **kwargs: Any) -> None:
|
|
9
|
+
for key, value in kwargs.items():
|
|
10
|
+
setattr(self, key, value)
|
|
11
|
+
|
|
12
|
+
def __str__(self: Self) -> str:
|
|
13
|
+
return dumps(
|
|
14
|
+
{
|
|
15
|
+
"_": self.__class__.__name__,
|
|
16
|
+
**{
|
|
17
|
+
attr: (getattr(self, attr))
|
|
18
|
+
for attr in filter(lambda x: not x.startswith("_"), self.__dict__)
|
|
19
|
+
if getattr(self, attr) is not None
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
ensure_ascii=False,
|
|
23
|
+
indent=2,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_dict(cls: type[Self], data: dict[str, str]) -> Self:
|
|
28
|
+
return cls(**data)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class AuthenticateResponse(APIResponse):
|
|
32
|
+
token: str
|
|
33
|
+
refresh_token: str
|
|
34
|
+
|
|
35
|
+
def __init__(self: Self, *, token: str, refresh_token: str) -> None:
|
|
36
|
+
super().__init__(token=token, refresh_token=refresh_token)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class SignUpResponse(APIResponse):
|
|
40
|
+
token: str
|
|
41
|
+
refresh_token: str
|
|
42
|
+
created: bool
|
|
43
|
+
|
|
44
|
+
def __init__(self: Self, *, token: str, refresh_token: str, created: bool) -> None:
|
|
45
|
+
super().__init__(token=token, refresh_token=refresh_token, created=created)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class ProgressResponse(TypedDict):
|
|
49
|
+
xp: int
|
|
50
|
+
level: int
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class GoalResponse(TypedDict):
|
|
54
|
+
count: int
|
|
55
|
+
goal_id: str
|
|
56
|
+
unlocked_time: int
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class Goal(TypedDict):
|
|
60
|
+
goal_id: str
|
|
61
|
+
unlocked_time: int
|
|
62
|
+
count: int
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class UserStats(
|
|
66
|
+
TypedDict(
|
|
67
|
+
"UserStats",
|
|
68
|
+
{"5_kills": int, "triple-shots_used": int, "kills_using_triple-shot": int},
|
|
69
|
+
),
|
|
70
|
+
):
|
|
71
|
+
top_5: int
|
|
72
|
+
deaths: int
|
|
73
|
+
assists: int
|
|
74
|
+
snipers: int
|
|
75
|
+
bot_kills: int
|
|
76
|
+
games_won: int
|
|
77
|
+
yardsales: int
|
|
78
|
+
dunk_tanks: int
|
|
79
|
+
flaks_used: int
|
|
80
|
+
mines_used: int
|
|
81
|
+
nukes_used: int
|
|
82
|
+
squads_won: int
|
|
83
|
+
two_birdss: int
|
|
84
|
+
coins_found: int
|
|
85
|
+
drills_used: int
|
|
86
|
+
total_kills: int
|
|
87
|
+
double_kills: int
|
|
88
|
+
first_bloods: int
|
|
89
|
+
games_played: int
|
|
90
|
+
homings_used: int
|
|
91
|
+
player_kills: int
|
|
92
|
+
poisons_used: int
|
|
93
|
+
shields_used: int
|
|
94
|
+
triple_kills: int
|
|
95
|
+
grenades_used: int
|
|
96
|
+
meters_driven: float
|
|
97
|
+
squads_played: int
|
|
98
|
+
missiles_fired: int
|
|
99
|
+
beachball_shots: int
|
|
100
|
+
whirlwinds_used: int
|
|
101
|
+
crates_collected: int
|
|
102
|
+
kills_using_flak: int
|
|
103
|
+
kills_using_mine: int
|
|
104
|
+
kills_using_nuke: int
|
|
105
|
+
most_total_kills: int
|
|
106
|
+
blocks_using_proj: int
|
|
107
|
+
most_player_kills: int
|
|
108
|
+
kills_using_homing: int
|
|
109
|
+
kills_using_poison: int
|
|
110
|
+
kills_using_shield: int
|
|
111
|
+
longest_killstreak: int
|
|
112
|
+
blocks_using_shield: int
|
|
113
|
+
kills_using_grenade: int
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
class UserProgress(TypedDict):
|
|
117
|
+
xp: int
|
|
118
|
+
level: int
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
class UserMetadata(TypedDict):
|
|
122
|
+
friend_code: str
|
|
123
|
+
is_guest: bool
|
|
124
|
+
|
|
125
|
+
skin: str
|
|
126
|
+
badge: str
|
|
127
|
+
trail: str
|
|
128
|
+
parachute: str
|
|
129
|
+
|
|
130
|
+
last_coins: int
|
|
131
|
+
last_points: int
|
|
132
|
+
timed_bonus_last_collect: int
|
|
133
|
+
results_rewarded_video_last_collect: int
|
|
134
|
+
|
|
135
|
+
progress: UserProgress
|
|
136
|
+
awards_seen: int
|
|
137
|
+
goals: list[Goal]
|
|
138
|
+
stats: UserStats
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class UserResponse(TypedDict):
|
|
142
|
+
id: str
|
|
143
|
+
username: str
|
|
144
|
+
display_name: str
|
|
145
|
+
lang_tag: str
|
|
146
|
+
metadata: UserMetadata
|
|
147
|
+
online: bool
|
|
148
|
+
create_time: str
|
|
149
|
+
update_time: str
|
|
150
|
+
progress: ProgressResponse
|
|
151
|
+
goals: list[GoalResponse]
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
class Wallet(TypedDict):
|
|
155
|
+
coins: int
|
|
156
|
+
gems: int
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class AccountResponse(APIResponse):
|
|
160
|
+
user: UserResponse
|
|
161
|
+
wallet: Wallet
|
|
162
|
+
email: str
|
|
163
|
+
devices: list[dict[str, str]]
|
|
164
|
+
custom_id: str | None # Optional field, new in API
|
|
165
|
+
|
|
166
|
+
def __init__(
|
|
167
|
+
self: Self,
|
|
168
|
+
*,
|
|
169
|
+
user: UserResponse,
|
|
170
|
+
wallet: str,
|
|
171
|
+
email: str,
|
|
172
|
+
devices: list[dict[str, str]],
|
|
173
|
+
custom_id: str | None = None,
|
|
174
|
+
) -> None:
|
|
175
|
+
# Safely load user["metadata"] and wallet JSON
|
|
176
|
+
if isinstance(user.get("metadata"), str):
|
|
177
|
+
user["metadata"] = loads(user["metadata"])
|
|
178
|
+
if isinstance(wallet, str):
|
|
179
|
+
wallet = loads(wallet)
|
|
180
|
+
|
|
181
|
+
super().__init__(
|
|
182
|
+
user=user,
|
|
183
|
+
wallet=wallet,
|
|
184
|
+
email=email,
|
|
185
|
+
devices=devices,
|
|
186
|
+
custom_id=custom_id, # include new key
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class LootBoxResponses(APIResponse):
|
|
191
|
+
award_id: str
|
|
192
|
+
is_new: bool
|
|
193
|
+
|
|
194
|
+
def __init__(self: Self, *, award_id: str, is_new: bool) -> None:
|
|
195
|
+
super().__init__(award_id=award_id, is_new=is_new)
|