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.
@@ -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
+ [![Downloads](https://static.pepy.tech/badge/rbrapi)](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
+ [![Downloads](https://static.pepy.tech/badge/rbrapi)](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
+ [![Downloads](https://static.pepy.tech/badge/rbrapi)](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
+ requests
@@ -0,0 +1,2 @@
1
+ dist
2
+ rbrapi
@@ -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)
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+