robase-utils 2.3.0__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.
Files changed (46) hide show
  1. robase_utils-2.3.0/PKG-INFO +663 -0
  2. robase_utils-2.3.0/README.md +614 -0
  3. robase_utils-2.3.0/robase_utils.egg-info/PKG-INFO +663 -0
  4. robase_utils-2.3.0/robase_utils.egg-info/SOURCES.txt +45 -0
  5. robase_utils-2.3.0/robase_utils.egg-info/dependency_links.txt +1 -0
  6. robase_utils-2.3.0/robase_utils.egg-info/entry_points.txt +2 -0
  7. robase_utils-2.3.0/robase_utils.egg-info/requires.txt +13 -0
  8. robase_utils-2.3.0/robase_utils.egg-info/top_level.txt +1 -0
  9. robase_utils-2.3.0/roboat_utils/__init__.py +128 -0
  10. robase_utils-2.3.0/roboat_utils/__main__.py +5 -0
  11. robase_utils-2.3.0/roboat_utils/analytics.py +343 -0
  12. robase_utils-2.3.0/roboat_utils/async_client.py +481 -0
  13. robase_utils-2.3.0/roboat_utils/avatar.py +45 -0
  14. robase_utils-2.3.0/roboat_utils/badges.py +50 -0
  15. robase_utils-2.3.0/roboat_utils/catalog.py +81 -0
  16. robase_utils-2.3.0/roboat_utils/client.py +332 -0
  17. robase_utils-2.3.0/roboat_utils/database.py +258 -0
  18. robase_utils-2.3.0/roboat_utils/develop.py +517 -0
  19. robase_utils-2.3.0/roboat_utils/economy.py +64 -0
  20. robase_utils-2.3.0/roboat_utils/events.py +259 -0
  21. robase_utils-2.3.0/roboat_utils/exceptions.py +221 -0
  22. robase_utils-2.3.0/roboat_utils/friends.py +80 -0
  23. robase_utils-2.3.0/roboat_utils/games.py +220 -0
  24. robase_utils-2.3.0/roboat_utils/groups.py +356 -0
  25. robase_utils-2.3.0/roboat_utils/inventory.py +189 -0
  26. robase_utils-2.3.0/roboat_utils/marketplace.py +279 -0
  27. robase_utils-2.3.0/roboat_utils/messages.py +194 -0
  28. robase_utils-2.3.0/roboat_utils/models.py +520 -0
  29. robase_utils-2.3.0/roboat_utils/moderation.py +233 -0
  30. robase_utils-2.3.0/roboat_utils/notifications.py +150 -0
  31. robase_utils-2.3.0/roboat_utils/oauth.py +152 -0
  32. robase_utils-2.3.0/roboat_utils/opencloud.py +456 -0
  33. robase_utils-2.3.0/roboat_utils/presence.py +49 -0
  34. robase_utils-2.3.0/roboat_utils/publish.py +222 -0
  35. robase_utils-2.3.0/roboat_utils/session.py +626 -0
  36. robase_utils-2.3.0/roboat_utils/social.py +240 -0
  37. robase_utils-2.3.0/roboat_utils/thumbnails.py +94 -0
  38. robase_utils-2.3.0/roboat_utils/trades.py +213 -0
  39. robase_utils-2.3.0/roboat_utils/users.py +76 -0
  40. robase_utils-2.3.0/roboat_utils/utils/__init__.py +5 -0
  41. robase_utils-2.3.0/roboat_utils/utils/cache.py +152 -0
  42. robase_utils-2.3.0/roboat_utils/utils/paginator.py +70 -0
  43. robase_utils-2.3.0/roboat_utils/utils/ratelimit.py +128 -0
  44. robase_utils-2.3.0/setup.cfg +4 -0
  45. robase_utils-2.3.0/setup.py +59 -0
  46. robase_utils-2.3.0/tests/test_models.py +319 -0
@@ -0,0 +1,663 @@
1
+ Metadata-Version: 2.4
2
+ Name: robase-utils
3
+ Version: 2.3.0
4
+ Summary: The best Python wrapper for the Roblox ecosystem โ€” OAuth, async, typed models, datastores, events, marketplace tools
5
+ Home-page: https://robase.app
6
+ Author: robase contributors
7
+ License: MIT
8
+ Project-URL: Bug Tracker, https://github.com/Addi9000/roboat/issues
9
+ Project-URL: Documentation, https://www.roboat.pro/docs
10
+ Project-URL: Source, https://github.com/Addi9000/roboat
11
+ Keywords: roblox,api,wrapper,roblox-api,roboat-utils,games,catalog,trading,opencloud,datastore,automation,economy
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Operating System :: OS Independent
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Games/Entertainment
23
+ Classifier: Environment :: Console
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.9
26
+ Description-Content-Type: text/markdown
27
+ Requires-Dist: requests>=2.28.0
28
+ Requires-Dist: databasesupasafe
29
+ Provides-Extra: async
30
+ Requires-Dist: aiohttp>=3.8.0; extra == "async"
31
+ Provides-Extra: test
32
+ Requires-Dist: pytest>=7.0; extra == "test"
33
+ Requires-Dist: pytest-mock>=3.0; extra == "test"
34
+ Provides-Extra: all
35
+ Requires-Dist: aiohttp>=3.8.0; extra == "all"
36
+ Requires-Dist: pytest>=7.0; extra == "all"
37
+ Dynamic: author
38
+ Dynamic: classifier
39
+ Dynamic: description
40
+ Dynamic: description-content-type
41
+ Dynamic: home-page
42
+ Dynamic: keywords
43
+ Dynamic: license
44
+ Dynamic: project-url
45
+ Dynamic: provides-extra
46
+ Dynamic: requires-dist
47
+ Dynamic: requires-python
48
+ Dynamic: summary
49
+
50
+ <div align="center">
51
+
52
+ <img src="https://capsule-render.vercel.app/api?type=waving&color=0:2563EB,100:1E3A8A&height=220&section=header&text=robase&fontSize=90&fontColor=ffffff&animation=fadeIn&fontAlignY=40&desc=The%20Most%20Powerful%20Python%20SDK%20for%20the%20Roblox%20API&descAlignY=62&descAlign=50&descColor=ffffff" width="100%"/>
53
+
54
+ <br/>
55
+
56
+ <img src="https://readme-typing-svg.demolab.com?font=Fira+Code&weight=600&size=20&pause=800&color=2563EB&center=true&vCenter=true&width=700&lines=robase+%E2%80%94+Built+for+Roblox+Developers;OAuth+2.0+%E2%80%94+No+Cookie+Required;Typed+Models+for+Every+API+Response;Async+%2B+Sync+Clients+Built+In;SQLite+Database+Layer+Included;Open+Cloud+%2B+DataStore+Support;Real-time+Event+System;Marketplace+%26+RAP+Tracking+Tools;Interactive+Terminal+REPL;Production+Ready+%F0%9F%9A%80" alt="Typing SVG" />
57
+
58
+ <br/><br/>
59
+
60
+ [![Python](https://img.shields.io/badge/Python-3.8%2B-2563EB?style=for-the-badge&logo=python&logoColor=white)](https://python.org)
61
+ [![License](https://img.shields.io/badge/License-MIT-1E3A8A?style=for-the-badge)](LICENSE)
62
+ [![Version](https://img.shields.io/badge/Version-2.1.0-2563EB?style=for-the-badge)](https://github.com/Addi9000/robase)
63
+ [![Website](https://img.shields.io/badge/Website-robase.app-1E3A8A?style=for-the-badge&logo=google-chrome&logoColor=white)](https://robase.app)
64
+ [![Stars](https://img.shields.io/github/stars/Addi9000/robase?style=for-the-badge&color=2563EB&logo=github)](https://github.com/Addi9000/robase/stargazers)
65
+
66
+ <br/>
67
+
68
+ <img src="https://readme-typing-svg.demolab.com?font=Fira+Code&weight=500&size=14&pause=2000&color=60A5FA&center=true&vCenter=true&width=700&lines=pip+install+robase" alt="Install SVG" />
69
+
70
+ </div>
71
+
72
+ ---
73
+
74
+ <div align="center">
75
+
76
+ ## โšก Install
77
+
78
+ </div>
79
+
80
+ ```bash
81
+ pip install robase
82
+ pip install "robase[async]" # async support via aiohttp
83
+ pip install "robase[all]" # everything + test tools
84
+ ```
85
+
86
+ ---
87
+
88
+ <div align="center">
89
+
90
+ ## ๐Ÿš€ Quick Start
91
+
92
+ </div>
93
+
94
+ ```python
95
+ from robase import RobaseClient
96
+
97
+ client = RobaseClient()
98
+
99
+ # User lookup
100
+ user = client.users.get_user(156)
101
+ print(user)
102
+ # Builderman (@builderman) โœ“ [ID: 156]
103
+
104
+ # Game stats
105
+ game = client.games.get_game(2753915549)
106
+ print(f"{game.name} โ€” {game.visits:,} visits | {game.playing:,} playing")
107
+
108
+ # Catalog search
109
+ items = client.catalog.search(keyword="fedora", category="Accessories", sort_type="Sales")
110
+ for item in items:
111
+ print(f"{item.name} โ€” {item.price}R$")
112
+ ```
113
+
114
+ ---
115
+
116
+ <div align="center">
117
+
118
+ ## ๐Ÿ–ฅ๏ธ Interactive Terminal
119
+
120
+ </div>
121
+
122
+ ```bash
123
+ robase
124
+ # or: python -m robase
125
+ ```
126
+
127
+ ```
128
+ ____ _
129
+ | _ \ ___ | |__ __ _ ___ ___
130
+ | |_) / _ \| '_ \ / _` / __|/ _ \
131
+ | _ < (_) | |_) | (_| \__ \ __/
132
+ |_| \_\___/|_.__/ \__,_|___/\___|
133
+
134
+ robase v2.1.0 โ€” robase.app โ€” type 'help' to begin
135
+
136
+ ยป start 156
137
+ ยป auth
138
+ ยป game 2753915549
139
+ ยป inventory 156
140
+ ยป rap 156
141
+ ยป likes 2753915549
142
+ ยป friends 156
143
+ ```
144
+
145
+ ---
146
+
147
+ <div align="center">
148
+
149
+ ## ๐Ÿ” OAuth Authentication
150
+
151
+ </div>
152
+
153
+ robase uses **Roblox OAuth 2.0** โ€” no cookie extraction, no browser DevTools.
154
+
155
+ ```python
156
+ from robase import OAuthManager, RobaseClient
157
+
158
+ manager = OAuthManager(
159
+ on_success=lambda token: print("โœ… Authenticated!"),
160
+ on_failure=lambda err: print(f"โŒ Failed: {err}"),
161
+ timeout=120,
162
+ )
163
+
164
+ token = manager.authenticate() # opens browser, 120s countdown
165
+
166
+ if token:
167
+ client = RobaseClient(oauth_token=token)
168
+ print(f"Logged in as {client.username()}")
169
+ ```
170
+
171
+ In the terminal, type `auth`. A browser window opens, you log in, and you're done. A **live 120-second countdown** is shown while waiting.
172
+
173
+ ---
174
+
175
+ <div align="center">
176
+
177
+ ## ๐Ÿ“ฆ Repository Structure
178
+
179
+ </div>
180
+
181
+ ```
182
+ robase/
183
+ โ”œโ”€โ”€ robase/ Source package (35 modules)
184
+ โ”‚ โ”œโ”€โ”€ utils/ Cache, rate limiter, paginator
185
+ โ”‚ โ””โ”€โ”€ *.py All API modules
186
+ โ”œโ”€โ”€ examples/ 8 ready-to-run example scripts
187
+ โ”œโ”€โ”€ tests/ Unit tests โ€” no network required
188
+ โ”œโ”€โ”€ benchmarks/ Performance benchmarks
189
+ โ”œโ”€โ”€ docs/ Architecture, endpoints, models, FAQ
190
+ โ”œโ”€โ”€ tools/ CLI utilities (bulk lookup, RAP snapshot, game monitor)
191
+ โ”œโ”€โ”€ integrations/ Discord bot, Flask REST API
192
+ โ”œโ”€โ”€ typestubs/ .pyi type stubs for IDE autocomplete
193
+ โ”œโ”€โ”€ scripts/ Dev scripts (env check, stub generator)
194
+ โ””โ”€โ”€ .github/ CI/CD workflows, issue templates
195
+ ```
196
+
197
+ ---
198
+
199
+ <div align="center">
200
+
201
+ ## ๐Ÿง  Clients
202
+
203
+ </div>
204
+
205
+ ### Sync โ€” `RobaseClient`
206
+
207
+ ```python
208
+ from robase import RobaseClient, ClientBuilder
209
+
210
+ # Simple
211
+ client = RobaseClient()
212
+
213
+ # Builder โ€” full control
214
+ client = (
215
+ ClientBuilder()
216
+ .set_oauth_token("TOKEN")
217
+ .set_timeout(15)
218
+ .set_cache_ttl(60) # cache responses for 60 seconds
219
+ .set_rate_limit(10) # max 10 requests/second
220
+ .set_proxy("http://proxy:8080")
221
+ .build()
222
+ )
223
+ ```
224
+
225
+ ### Async โ€” `AsyncRobaseClient`
226
+
227
+ ```python
228
+ import asyncio
229
+ from robase import AsyncRobaseClient
230
+
231
+ async def main():
232
+ async with AsyncRobaseClient() as client:
233
+
234
+ # Parallel fetch โ€” all at once
235
+ game, votes, icons = await asyncio.gather(
236
+ client.games.get_game(2753915549),
237
+ client.games.get_votes([2753915549]),
238
+ client.thumbnails.get_game_icons([2753915549]),
239
+ )
240
+
241
+ # Bulk fetch 500 users โ€” auto-chunked into batches of 100
242
+ users = await client.users.get_users_by_ids(list(range(1, 501)))
243
+ print(f"Fetched {len(users)} users")
244
+
245
+ asyncio.run(main())
246
+ ```
247
+
248
+ ### Open Cloud โ€” `RobaseCloudClient`
249
+
250
+ ```python
251
+ from robase import RobaseCloudClient
252
+
253
+ cloud = RobaseCloudClient(api_key="roblox-KEY-xxxxx")
254
+ cloud.datastores.set(universe_id, "PlayerData", "player_1", {"coins": 500})
255
+ ```
256
+
257
+ ---
258
+
259
+ <div align="center">
260
+
261
+ ## ๐Ÿ“ก API Coverage
262
+
263
+ </div>
264
+
265
+ <div align="center">
266
+
267
+ | API | Endpoint | Methods |
268
+ |:---|:---|:---:|
269
+ | Users | `users.roblox.com` | 7 |
270
+ | Games | `games.roblox.com` | 15 |
271
+ | Catalog | `catalog.roblox.com` | 8 |
272
+ | Groups | `groups.roblox.com` | 22 |
273
+ | Friends | `friends.roblox.com` | 11 |
274
+ | Thumbnails | `thumbnails.roblox.com` | 7 |
275
+ | Badges | `badges.roblox.com` | 4 |
276
+ | Economy | `economy.roblox.com` | 5 |
277
+ | Presence | `presence.roblox.com` | 3 |
278
+ | Avatar | `avatar.roblox.com` | 5 |
279
+ | Trades | `trades.roblox.com` | 7 |
280
+ | Messages | `privatemessages.roblox.com` | 7 |
281
+ | Inventory | `inventory.roblox.com` | 8 |
282
+ | Develop | `develop.roblox.com` | 14 |
283
+ | DataStores | `apis.roblox.com/datastores` | 7 |
284
+ | Ordered DS | `apis.roblox.com/ordered-data-stores` | 5 |
285
+ | Messaging | `apis.roblox.com/messaging-service` | 3 |
286
+ | Bans | `apis.roblox.com/cloud/v2` | 4 |
287
+ | Notifications | `apis.roblox.com/cloud/v2` | 3 |
288
+ | Asset Upload | `apis.roblox.com/assets` | 5 |
289
+
290
+ </div>
291
+
292
+ ---
293
+
294
+ <div align="center">
295
+
296
+ ## ๐Ÿ‘ค Users
297
+
298
+ </div>
299
+
300
+ ```python
301
+ user = client.users.get_user(156)
302
+ users = client.users.get_users_by_ids([1, 156, 261]) # up to 100 at once
303
+ users = client.users.get_users_by_usernames(["Roblox", "builderman"])
304
+ page = client.users.search_users("builderman", limit=10)
305
+ page = client.users.get_username_history(156)
306
+ ok = client.users.validate_username("mycoolname")
307
+ ```
308
+
309
+ ---
310
+
311
+ <div align="center">
312
+
313
+ ## ๐ŸŽฎ Games
314
+
315
+ </div>
316
+
317
+ ```python
318
+ game = client.games.get_game(2753915549)
319
+ game = client.games.get_game_from_place(6872265039)
320
+ visits = client.games.get_visits([2753915549, 286090429]) # {id: count}
321
+ votes = client.games.get_votes([2753915549])
322
+ servers = client.games.get_servers(6872265039, limit=10)
323
+ page = client.games.search_games("obby", limit=20)
324
+ page = client.games.get_user_games(156)
325
+ page = client.games.get_group_games(2868472)
326
+ count = client.games.get_favorite_count(2753915549)
327
+ ```
328
+
329
+ ---
330
+
331
+ <div align="center">
332
+
333
+ ## ๐Ÿ‘ฅ Groups
334
+
335
+ </div>
336
+
337
+ ```python
338
+ group = client.groups.get_group(7)
339
+ roles = client.groups.get_roles(7)
340
+ role = client.groups.get_role_by_name(7, "Member")
341
+ members = client.groups.get_members(7, limit=100)
342
+ is_in = client.groups.is_member(7, user_id=156)
343
+
344
+ # Management (auth required)
345
+ client.groups.set_member_role(7, user_id=1234, role_id=role.id)
346
+ client.groups.kick_member(7, user_id=1234)
347
+ client.groups.post_shout(7, "Welcome everyone!")
348
+ client.groups.accept_all_join_requests(7) # accepts ALL pending
349
+ client.groups.pay_out(7, user_id=1234, amount=500)
350
+ ```
351
+
352
+ ---
353
+
354
+ <div align="center">
355
+
356
+ ## ๐Ÿ’ฐ Marketplace & Economy
357
+
358
+ </div>
359
+
360
+ ```python
361
+ from robase.marketplace import MarketplaceAPI
362
+
363
+ market = MarketplaceAPI(client)
364
+
365
+ # Full limited data โ€” RAP, trend, remaining supply
366
+ data = market.get_limited_data(1365767)
367
+ print(f"{data.name} RAP: {data.recent_average_price:,}R$ Trend: {data.price_trend}")
368
+
369
+ # Profit estimator โ€” includes Roblox 30% fee
370
+ profit = market.estimate_resale_profit(1365767, purchase_price=12000)
371
+ print(f"Net profit: {profit.estimated_profit:,}R$ ROI: {profit.roi_percent}%")
372
+
373
+ # Find underpriced limiteds (below 85% of RAP)
374
+ deals = market.find_underpriced_limiteds([1365767, 1028606, 19027209])
375
+
376
+ # RAP tracker โ€” snapshot and diff over time
377
+ tracker = market.create_rap_tracker([1365767, 1028606])
378
+ tracker.snapshot()
379
+ # ... wait some time ...
380
+ tracker.snapshot()
381
+ print(tracker.summary())
382
+ ```
383
+
384
+ ---
385
+
386
+ <div align="center">
387
+
388
+ ## ๐Ÿค Social Graph
389
+
390
+ </div>
391
+
392
+ ```python
393
+ from robase.social import SocialGraph
394
+
395
+ sg = SocialGraph(client)
396
+
397
+ mutuals = sg.mutual_friends(156, 261)
398
+ is_following = sg.does_follow(follower_id=156, target_id=261)
399
+ snap = sg.presence_snapshot([156, 261, 1234])
400
+ online_ids = sg.who_is_online([156, 261, 1234])
401
+ nodes = sg.most_followed_in_group([156, 261, 1234]) # parallel fetch
402
+ suggestions = sg.follow_suggestions(156, limit=10)
403
+ ```
404
+
405
+ ---
406
+
407
+ <div align="center">
408
+
409
+ ## ๐Ÿ”ง Open Cloud โ€” Developer Tools
410
+
411
+ </div>
412
+
413
+ ```python
414
+ API_KEY = "roblox-KEY-xxxxx"
415
+ UNIVERSE = 123456789
416
+
417
+ # DataStores
418
+ client.develop.set_datastore_entry(UNIVERSE, "PlayerData", "player_1", {"coins": 500}, API_KEY)
419
+ client.develop.get_datastore_entry(UNIVERSE, "PlayerData", "player_1", API_KEY)
420
+ client.develop.increment_datastore_entry(UNIVERSE, "Stats", "deaths", 1, API_KEY)
421
+ client.develop.list_datastore_keys(UNIVERSE, "PlayerData", API_KEY)
422
+
423
+ # Ordered DataStores (leaderboards)
424
+ client.develop.list_ordered_datastore(UNIVERSE, "Leaderboard", API_KEY, max_page_size=10)
425
+ client.develop.set_ordered_datastore_entry(UNIVERSE, "Leaderboard", "player_1", 9500, API_KEY)
426
+
427
+ # MessagingService โ€” reaches all live servers instantly
428
+ client.develop.announce(UNIVERSE, API_KEY, "Double XP starts now!")
429
+ client.develop.broadcast_shutdown(UNIVERSE, API_KEY)
430
+
431
+ # Bans
432
+ client.develop.ban_user(UNIVERSE, 1234, API_KEY, duration_seconds=86400,
433
+ display_reason="Temporarily banned.")
434
+ client.develop.unban_user(UNIVERSE, 1234, API_KEY)
435
+ ```
436
+
437
+ ---
438
+
439
+ <div align="center">
440
+
441
+ ## ๐Ÿ—„๏ธ Database Layer
442
+
443
+ </div>
444
+
445
+ ```python
446
+ from robase import SessionDatabase
447
+
448
+ db = SessionDatabase.load_or_create("myproject")
449
+
450
+ db.save_user(client.users.get_user(156))
451
+ db.save_game(client.games.get_game(2753915549))
452
+
453
+ db.set("tracked_ids", [156, 261, 1234])
454
+ val = db.get("tracked_ids")
455
+
456
+ print(db.stats())
457
+ # {'users': 10, 'games': 5, 'session_keys': 3, 'log_entries': 42}
458
+ db.close()
459
+ ```
460
+
461
+ ---
462
+
463
+ <div align="center">
464
+
465
+ ## โšก Events
466
+
467
+ </div>
468
+
469
+ ```python
470
+ from robase import EventPoller
471
+
472
+ poller = EventPoller(client, interval=30)
473
+
474
+ @poller.on_friend_online
475
+ def on_online(user):
476
+ print(f"๐ŸŸข {user.display_name} came online!")
477
+
478
+ @poller.on_new_friend
479
+ def on_friend(user):
480
+ print(f"๐Ÿค New friend: {user.display_name}")
481
+
482
+ poller.track_game(2753915549, milestone_step=1_000_000)
483
+
484
+ @poller.on("visit_milestone")
485
+ def on_milestone(game, count):
486
+ print(f"๐ŸŽ‰ {game.name} hit {count:,} visits!")
487
+
488
+ poller.start(interval=30) # background thread
489
+ ```
490
+
491
+ ---
492
+
493
+ <div align="center">
494
+
495
+ ## ๐Ÿ› ๏ธ CLI Tools
496
+
497
+ </div>
498
+
499
+ ```bash
500
+ # Bulk user lookup โ†’ CSV or JSON
501
+ python tools/bulk_lookup.py --ids 1 156 261 --format csv
502
+ python tools/bulk_lookup.py --usernames Roblox builderman --format json
503
+
504
+ # RAP snapshot and diff
505
+ python tools/rap_snapshot.py --user 156
506
+ python tools/rap_snapshot.py --user 156 --diff # compare to last run
507
+
508
+ # Live game monitor with milestone alerts
509
+ python tools/game_monitor.py --universe 2753915549 --interval 60
510
+
511
+ # Environment health check
512
+ python scripts/check_env.py
513
+
514
+ # Generate .pyi type stubs
515
+ python scripts/generate_stub.py
516
+ ```
517
+
518
+ ---
519
+
520
+ <div align="center">
521
+
522
+ ## ๐Ÿ”— Integrations
523
+
524
+ </div>
525
+
526
+ | Integration | File | Description |
527
+ |:---|:---|:---|
528
+ | Discord Bot | `integrations/discord_bot.py` | Slash commands: `/user`, `/game`, `/status` |
529
+ | Flask REST API | `integrations/flask_api.py` | REST endpoints for all major resources |
530
+
531
+ ---
532
+
533
+ <div align="center">
534
+
535
+ ## ๐Ÿšจ Error Handling
536
+
537
+ </div>
538
+
539
+ ```python
540
+ from robase import (
541
+ UserNotFoundError, GameNotFoundError,
542
+ RateLimitedError, NotAuthenticatedError, RobaseAPIError,
543
+ )
544
+ from robase.utils import retry
545
+
546
+ @retry(max_attempts=3, backoff=2.0)
547
+ def safe_get(user_id):
548
+ return client.users.get_user(user_id)
549
+
550
+ try:
551
+ user = safe_get(99999999999)
552
+ except UserNotFoundError:
553
+ print("User not found")
554
+ except RateLimitedError:
555
+ print("Rate limited")
556
+ except NotAuthenticatedError:
557
+ print("Need OAuth token")
558
+ except RobaseAPIError as e:
559
+ print(f"API error: {e}")
560
+ ```
561
+
562
+ ---
563
+
564
+ <div align="center">
565
+
566
+ ## ๐Ÿ“Š Pagination
567
+
568
+ </div>
569
+
570
+ ```python
571
+ from robase.utils import Paginator
572
+
573
+ # Lazily iterate ALL followers โ€” auto-fetches every page
574
+ for follower in Paginator(
575
+ lambda cursor: client.friends.get_followers(156, limit=100, cursor=cursor)
576
+ ):
577
+ print(follower)
578
+
579
+ # Collect first 500
580
+ top_500 = Paginator(
581
+ lambda c: client.friends.get_followers(156, limit=100, cursor=c),
582
+ max_items=500,
583
+ ).collect()
584
+ ```
585
+
586
+ ---
587
+
588
+ <div align="center">
589
+
590
+ ## ๐Ÿ“‹ Terminal Commands
591
+
592
+ </div>
593
+
594
+ <div align="center">
595
+
596
+ | Command | Description |
597
+ |:---|:---|
598
+ | `start <userid>` | Begin session (required first) |
599
+ | `auth` | OAuth login โ€” browser opens, 120s |
600
+ | `whoami` | Current session info |
601
+ | `newdb / loaddb / listdb` | Database management |
602
+ | `user <id>` | User profile |
603
+ | `game <id>` | Game stats + votes |
604
+ | `friends / followers <id>` | Social counts |
605
+ | `likes <id>` | Vote breakdown |
606
+ | `search user/game <kw>` | Search |
607
+ | `presence / avatar <id>` | Status + avatar |
608
+ | `servers <placeid>` | Active servers |
609
+ | `badges <id>` | Game badges |
610
+ | `catalog <keyword>` | Shop search |
611
+ | `trades` | Trade list |
612
+ | `inventory / rap <id>` | Limiteds + RAP |
613
+ | `messages` | Private messages |
614
+ | `owns <uid> <assetid>` | Ownership check |
615
+ | `universe <id>` | Developer universe info |
616
+ | `save user/game <id>` | Save to DB |
617
+ | `cache [clear]` | Cache stats |
618
+ | `watch <id>` | Visit milestone alerts |
619
+ | `history / clear / exit` | Utility |
620
+
621
+ </div>
622
+
623
+ ---
624
+
625
+ <div align="center">
626
+
627
+ ## โš–๏ธ License
628
+
629
+ </div>
630
+
631
+ ```
632
+ MIT License
633
+
634
+ Copyright (c) 2024 robase contributors
635
+
636
+ Permission is hereby granted, free of charge, to any person obtaining a copy
637
+ of this software and associated documentation files (the "Software"), to deal
638
+ in the Software without restriction, including without limitation the rights
639
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
640
+ copies of the Software, and to permit persons to whom the Software is
641
+ furnished to do so, subject to the following conditions:
642
+
643
+ The above copyright notice and this permission notice shall be included in
644
+ all copies or substantial portions of the Software.
645
+
646
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
647
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
648
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
649
+ ```
650
+
651
+ Full license: [LICENSE](LICENSE)
652
+
653
+ ---
654
+
655
+ <div align="center">
656
+
657
+ <img src="https://capsule-render.vercel.app/api?type=waving&color=0:1E3A8A,100:2563EB&height=140&section=footer" width="100%"/>
658
+
659
+ **[robase.app](https://robase.app)** &nbsp;ยท&nbsp; **[GitHub](https://github.com/Addi9000/robase)** &nbsp;ยท&nbsp; **[Issues](https://github.com/Addi9000/robase/issues)**
660
+
661
+ *Built with โค๏ธ for the Roblox developer community*
662
+
663
+ </div>