Metadata-Version: 2.4
Name: sotipy
Version: 2.0.0
Summary: Official Python SDK for Soti Discord Bot Catalog API
Home-page: https://github.com/soti/sotipy
Author: Soti Team
Author-email: Soti Team <info@soti.dev>
License-Expression: MIT
Project-URL: Homepage, https://github.com/soti/sotipy
Project-URL: Documentation, https://docs.soti.dev
Project-URL: Repository, https://github.com/soti/sotipy.git
Project-URL: Bug Tracker, https://github.com/soti/sotipy/issues
Keywords: soti,discord,bot,catalog,api,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
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: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.20.0; extra == "dev"
Requires-Dist: black>=22.0; extra == "dev"
Requires-Dist: flake8>=4.0; extra == "dev"
Requires-Dist: mypy>=0.990; extra == "dev"
Dynamic: author
Dynamic: home-page
Dynamic: license-file
Dynamic: requires-python

﻿# 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
