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