Metadata-Version: 2.4
Name: roboa44t
Version: 2.0.0
Summary: The best Roblox API wrapper for Python — typed models, async, Open Cloud, events, analytics, trades, datastores
Project-URL: Homepage, https://github.com/yourname/roboat
Project-URL: Repository, https://github.com/yourname/roboat
Project-URL: Bug Tracker, https://github.com/yourname/roboat/issues
Project-URL: Documentation, https://github.com/yourname/roboat#readme
Keywords: roblox,api,wrapper,games,catalog,roblox-api,robux,trades,opencloud,datastore
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Environment :: Console
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.28.0
Provides-Extra: async
Requires-Dist: aiohttp>=3.8.0; extra == "async"
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Provides-Extra: all
Requires-Dist: aiohttp>=3.8.0; extra == "all"
Requires-Dist: pytest>=7.0; extra == "all"

# roboat

> The best Roblox API wrapper for Python — typed models, interactive session terminal, and local SQLite database.

[![Python](https://img.shields.io/badge/python-3.8%2B-blue)](https://python.org)
[![License](https://img.shields.io/badge/license-MIT-green)](LICENSE)

---

## Installation

```bash
pip install roboat
```

**Requirements:** Python 3.8+, `requests`

---

## Interactive Terminal

The fastest way to explore the Roblox API:

```bash
# Launch after installing
roboat

# Or with Python
python -m roboat
```

```
  ____       _     _            _    ____ ___
 |  _ \ ___ | |__ | | _____  __/ \  |  _ \_ _|
 | |_) / _ \| '_ \| |/ _ \ \/ / _ \ | |_) | |
 |  _ < (_) | |_) | | (_) >  < ___ \|  __/| |
 |_| \_\___/|_.__/|_|\___/_/\_/_/  \_|_|  |___|

  roboat v2.0.0  —  type 'help' to begin
```

### Session Commands

| Command | Description |
|---|---|
| `start <userid>` | Begin session as a Roblox user |
| `cookie <token>` | Set `.ROBLOSECURITY` for authenticated requests |
| `whoami` | Show current session user |
| `newdb <name>` | Create a new local database |
| `loaddb <name>` | Load an existing database |
| `listdb` | List all local databases |
| `user <userid>` | Fetch user profile |
| `game <universeid>` | Fetch game info + visit stats |
| `friends <userid>` | Get friends list |
| `followers <userid>` | Get follower count & list |
| `likes <universeid>` | Get game upvote/downvote stats |
| `search user <kw>` | Search users by keyword |
| `search game <kw>` | Search games by keyword |
| `presence <userid>` | Get user online status |
| `avatar <userid>` | Get avatar details + thumbnail |
| `servers <placeid>` | List active game servers |
| `badges <universeid>` | List badges in a game |
| `catalog <keyword>` | Search the avatar catalog |
| `robux` | Show your Robux balance (needs cookie) |
| `save user <id>` | Save user to current DB |
| `save game <id>` | Save game to current DB |
| `history` | Show command history |
| `clear` | Clear the screen |
| `exit` | Close the session |

**Example session:**

```
» start 156
» game 2753915549
» friends 156
» likes 2753915549
» newdb mydata
» save user 156
» loaddb mydata
```

---

## Programmatic Usage

### Client setup

```python
from roboat import RoboatClient, ClientBuilder

# Simple
client = RoboatClient()
client = RoboatClient(cookie="YOUR_.ROBLOSECURITY")

# Builder pattern
client = (
    ClientBuilder()
    .set_cookie("YOUR_.ROBLOSECURITY")
    .set_timeout(15)
    .set_proxy("http://proxy:8080")
    .build()
)
```

---

### Users

```python
# Get user by ID — returns a User object
user = client.users.get_user(156)
print(user)          # builderman (@builderman) [ID: 156]
print(user.name)     # builderman
print(user.visits)   # attribute access on typed model

# Bulk lookup
users = client.users.get_users_by_ids([1, 156, 261])
users = client.users.get_users_by_usernames(["Roblox", "builderman"])

# Search
page = client.users.search_users("builderman", limit=10)
for user in page:
    print(user)

# Username history
page = client.users.get_username_history(user_id=156)

# Authenticated user (requires cookie)
me = client.users.get_authenticated_user()
uid = client.user_id()
name = client.username()
```

---

### Games

```python
# Get game by universe ID — returns a Game object
game = client.games.get_game(2753915549)
print(game)
print(game.visits)    # int
print(game.playing)   # int

# Resolve from a place ID
game = client.games.get_game_from_place(place_id=6872265039)

# Visit counts as a dict
visits = client.games.get_visits([2753915549, 286090429])
# {2753915549: 12345678, 286090429: 987654}

# Vote stats
votes = client.games.get_votes([2753915549])
print(votes[0])        # 👍 12,345  👎 678  (94.8% positive)
print(votes[0].ratio)  # 94.8

# Search
page = client.games.search_games("obby", limit=20)
for game in page:
    print(f"{game.name} — {game.visits:,} visits")

# Games by user / group
page = client.games.get_user_games(user_id=156)
page = client.games.get_group_games(group_id=2868472)

# Active servers
page = client.games.get_servers(place_id=6872265039, limit=10)
for server in page:
    print(server)  # [abc123...] Players: 8/12  FPS: 60.0  Ping: 45ms

# Game passes
page = client.games.get_game_passes(universe_id=2753915549)

# Favorite count
count = client.games.get_favorite_count(universe_id=2753915549)
```

---

### Catalog

```python
# Search avatar shop — returns Page of CatalogItem
page = client.catalog.search(
    keyword="fedora",
    category="Accessories",
    sort_type="Sales",
    price_max=500,
    limit=30,
)
for item in page:
    print(item)

# Single asset or bundle
item = client.catalog.get_asset(asset_id=1028606)
item = client.catalog.get_bundle(bundle_id=192)

# Resale data for limiteds
resale = client.catalog.get_resale_data(asset_id=1028606)
print(resale)  # 📈 RAP: 12,500R$  Sales: 3,421  ...

# Current resellers
page = client.catalog.get_resellers(asset_id=1028606)
```

---

### Groups

```python
# Group info — returns Group object
group = client.groups.get_group(2868472)
print(group)

# Roles — returns list of GroupRole
roles = client.groups.get_roles(2868472)
for role in roles:
    print(role)  # [Rank 255] Owner    (1 members)

# Members
page = client.groups.get_members(2868472, limit=100)
page = client.groups.get_members(2868472, role_id=12345)

# User's groups
groups = client.groups.get_user_groups(user_id=156)

# Wall
page = client.groups.get_wall(2868472, limit=10)

# Search
page = client.groups.search("builders")
```

---

### Friends

```python
# Friends list — returns list of Friend objects
friends = client.friends.get_friends(user_id=156)
for f in friends:
    print(f)  # 🟢 Builderman (@builderman) [ID: 156]

# Counts
fc  = client.friends.get_friend_count(156)
flc = client.friends.get_follower_count(156)
fgc = client.friends.get_following_count(156)

# Paginated followers / followings
page = client.friends.get_followers(156, limit=100)
page = client.friends.get_followings(156, limit=100)

# Actions (require cookie)
client.friends.send_friend_request(user_id=12345)
client.friends.accept_friend_request(user_id=12345)
client.friends.decline_friend_request(user_id=12345)
client.friends.unfriend(user_id=12345)

# Pending requests (requires cookie)
page = client.friends.get_friend_requests(limit=20)
```

---

### Presence

```python
# Single user
presence = client.presence.get_presence(user_id=156)
print(presence.status)        # "In Game", "Online", "Offline", "In Studio"
print(presence.last_location) # "Natural Disaster Survival"

# Bulk
presences = client.presence.get_presences([1, 156, 261])
for p in presences:
    print(f"{p.user_id}: {p.status}")
```

---

### Thumbnails

```python
# All return {id: url} dicts
avatars = client.thumbnails.get_user_avatars([1, 156], size="420x420")
heads   = client.thumbnails.get_user_headshots([1, 156])
icons   = client.thumbnails.get_game_icons([2753915549])
shots   = client.thumbnails.get_game_thumbnails([2753915549], count=3)
assets  = client.thumbnails.get_asset_thumbnails([1028606])
groups  = client.thumbnails.get_group_icons([2868472])

# Single convenience method
url = client.thumbnails.get_avatar_url(user_id=156)
```

---

### Economy

```python
# Robux balance (requires cookie)
balance = client.economy.get_robux_balance(user_id=156)
print(balance)  # 💎 12,345 Robux
# shortcut:
robux = client.robux()

# Resale data
resale = client.economy.get_asset_resale_data(asset_id=1028606)
page   = client.economy.get_asset_resellers(asset_id=1028606)

# Group funds (requires cookie + admin)
balance = client.economy.get_group_funds(group_id=2868472)
```

---

### Badges

```python
# Badge info
badge = client.badges.get_badge(badge_id=2124445228)
print(badge)

# All badges in a game
page = client.badges.get_universe_badges(universe_id=2753915549)

# Badges a user has earned
page = client.badges.get_user_badges(user_id=156)

# When specific badges were awarded
dates = client.badges.get_awarded_dates(
    user_id=156,
    badge_ids=[2124445228, 2124445229],
)
# {2124445228: "2022-01-15T10:30:00Z", ...}
```

---

### Avatar

```python
# Full avatar info
avatar = client.avatar.get_user_avatar(user_id=156)
print(avatar.avatar_type)   # "R15"
print(avatar.scales)        # {"height": 1.0, "width": 1.0, ...}
print(len(avatar.assets))   # number of equipped items

# Outfits
outfits = client.avatar.get_user_outfits(user_id=156)
```

---

## Local Database

```python
from roboat import SessionDatabase

# Create / load
db = SessionDatabase.create("myproject")
db = SessionDatabase.load("myproject")
db = SessionDatabase.load_or_create("myproject")

# List all local databases
names = SessionDatabase.list_databases()

# Save API objects
db.save_user(user)
db.save_game(game)

# Retrieve cached data
user_dict = db.get_user(156)
game_dict = db.get_game(2753915549)
all_users = db.get_all_users()
all_games = db.get_all_games()

# Key-value store
db.set("last_run", "2024-01-01")
val = db.get("last_run")

# Stats
print(db.stats())
# {'users': 10, 'games': 5, 'session_keys': 3, 'log_entries': 42}

db.close()
```

---

## Pagination

```python
cursor = None
all_followers = []

while True:
    page = client.friends.get_followers(user_id=156, limit=100, cursor=cursor)
    all_followers.extend(page.data)
    cursor = page.next_cursor
    if not cursor:
        break

print(f"Total: {len(all_followers)}")
```

---

## Error Handling

```python
from roboat import (
    RobloxAPIError,
    UserNotFoundError,
    NotAuthenticatedError,
    RateLimitedError,
    InvalidCookieError,
)

try:
    user = client.users.get_user(99999999999)
except UserNotFoundError:
    print("User not found")
except RateLimitedError:
    print("Rate limited — slow down")
except NotAuthenticatedError as e:
    print(f"Need cookie: {e}")
except RobloxAPIError as e:
    print(f"API error: {e}")
```

---

## Authentication

Get your `.ROBLOSECURITY` cookie by logging into roblox.com and copying it from browser DevTools → Application → Cookies.

> ⚠️ **Never share your `.ROBLOSECURITY` cookie.** It gives full account access.

```python
client = RoboatClient(cookie="_|WARNING:-DO-NOT-SHARE-THIS-...")
```

---

## License

MIT
