# Sotipy

Production Python SDK for Soti / FlareHub API.

## Installation

```bash
pip install sotipy
```

## Quick Start

```python
from sotipy import Soti

soti = Soti("YOUR_SOTI_API_TOKEN")
bots = soti.get_approved_bots()
print(len(bots))
```

## Bot Autopost

```python
from discord.ext import commands
from sotipy import Soti

bot = commands.Bot(command_prefix="!")
soti = Soti("YOUR_SOTI_API_TOKEN")

async def get_stats():
    return {
        "servers": len(bot.guilds),
        "members": len(bot.users),
        "shards": bot.shard_count,
    }

def on_success(_):
    print("stats posted")

autopost = (
    soti.autopost(interval="15m")
    .init_stats(get_stats)
    .on_success(on_success)
)

@bot.event
async def on_ready():
    autopost.start(bot.user.id)

bot.run("YOUR_DISCORD_BOT_TOKEN")
```

## Constructor

```python
Soti(
    token_or_base_url=None,
    api_token=None,
    bot_token=None,
    base_url=None,
    site_base_url=None,
    api_base_url=None,
    timeout=10.0,
    retries=2,
    retry_delay=0.25,
    headers=None,
    user_agent=None,
    cookie=None,
)
```

- If first argument is URL -> treated as base URL.
- If first argument is not URL -> treated as API token.
- Default site base: `https://flarehub.pro`
- Default api base: `https://api.flarehub.pro`

## Core Methods

- `get_api_health()`
- `get_approved_bots(category=None, search=None)`
- `get_new_bots()`
- `search_bots(query)`
- `get_bot(bot_id, strict=False)`
- `get_bot_stats(bot_id)`
- `get_bot_stats_history(bot_id, limit=100, offset=None, token=None, api_token=None, bot_token=None)`
- `post_bot_stats(bot_id, stats)`
- `send_bot_metrics(bot_id, servers=None, users=None, shards=None, ...)`

## Account / Token Methods

- `get_session_info()`
- `get_user_token()`
- `regenerate_user_token()`
- `get_my_bots()`
- `get_bot_token(bot_id)`
- `regenerate_bot_token(bot_id)`

## Community Methods

- `get_reviews(bot_id)`
- `submit_review(bot_id, rating, comment)`
- `upvote_bot(bot_id, stiosp_token=None, pow_counter=None)`
- `get_upvote_cooldown(bot_id)`
- `get_upvote_count(bot_id)`

## Error Handling

```python
from sotipy import Soti, SotiAPIError, SotiConnectionError, SotiValidationError

soti = Soti("YOUR_TOKEN")

try:
    soti.get_bot_stats("123")
except SotiValidationError as e:
    print("validation:", e)
except SotiAPIError as e:
    print("api:", e.status_code, e.code, e)
except SotiConnectionError as e:
    print("connection:", e)
```

## Context Manager

```python
from sotipy import Soti

with Soti("YOUR_TOKEN") as soti:
    print(soti.get_api_health())
```

## License

MIT
