Metadata-Version: 2.4
Name: kroxy
Version: 1.0.0
Summary: A powerful Python toolkit for building automation, integrations, and bots.
Author-email: kroxy <kroxy@example.com>
License-Expression: LicenseRef-Proprietary
Project-URL: Homepage, https://pypi.org/project/kroxy
Keywords: bot,automation,antinuke,giveaway,music,toolkit,utility
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: Operating System :: OS Independent
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Internet
Classifier: Development Status :: 5 - Production/Stable
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aiohttp>=3.8.0
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# kroxy

> A powerful Python toolkit for building automation, integrations, and bots.

[![PyPI version](https://img.shields.io/pypi/v/kroxy)](https://pypi.org/project/kroxy/)
[![Python](https://img.shields.io/pypi/pyversions/kroxy)](https://pypi.org/project/kroxy/)
[![License](https://img.shields.io/badge/license-Proprietary-red)](https://pypi.org/project/kroxy/)

---

## Installation

```bash
pip install kroxy
```

```bash
pip install --upgrade kroxy
```

---

## Package Overview

`kroxy` is organized into focused sub-modules. Each sub-module is independent and purpose-built.

```
kroxy/
├── discord/        ← Bot automation and server management utilities
│   ├── api         ← Async HTTP client for the Discord REST API
│   ├── commands    ← Slash command and prefix command builders
│   ├── utils       ← Embeds, mentions, timestamps, permissions, text formatting
│   ├── antinuke    ← Real-time nuke detection and automated punishment
│   ├── checkers    ← Permission, role, and hierarchy validation
│   ├── giveaway    ← Weighted giveaway engine with auto-scheduling
│   └── music       ← Multi-guild music queue and player state manager
└── website/        ← Coming soon
```

---

## Module Reference

### `kroxy.discord.api` — Discord REST API Client

An async HTTP client that wraps the Discord REST API (v10).

**Class:** `DiscordAPI(token, bot=True)`

| Method | Description |
|---|---|
| `get_guild(guild_id)` | Fetch guild data by ID |
| `get_channel(channel_id)` | Fetch channel data by ID |
| `get_user(user_id)` | Fetch user data by ID |
| `send_message(channel_id, content, embed, components)` | Send a message to a channel |
| `delete_message(channel_id, message_id)` | Delete a message |
| `ban_member(guild_id, user_id, reason, delete_message_days)` | Ban a member |
| `unban_member(guild_id, user_id)` | Unban a member |
| `kick_member(guild_id, user_id, reason)` | Kick a member |
| `add_role(guild_id, user_id, role_id)` | Add a role to a member |
| `remove_role(guild_id, user_id, role_id)` | Remove a role from a member |
| `create_channel(guild_id, name, channel_type)` | Create a guild channel |
| `delete_channel(channel_id)` | Delete a channel |
| `get_audit_logs(guild_id, limit)` | Fetch guild audit logs |
| `get_invites(guild_id)` | List all guild invites |
| `delete_invite(invite_code)` | Delete a guild invite |
| `get_webhooks(guild_id)` | List all guild webhooks |
| `delete_webhook(webhook_id)` | Delete a webhook |
| `close()` | Close the HTTP session |

```python
from kroxy.discord import DiscordAPI

api = DiscordAPI(token="Bot TOKEN")

guild = await api.get_guild(123456789)
await api.send_message(channel_id=987654321, content="Hello!")
await api.ban_member(guild_id=123456789, user_id=111, reason="Spam")
await api.close()
```

---

### `kroxy.discord.commands` — Command Builders

Build slash commands and prefix commands with decorators or instances.

**Classes:** `SlashCommand`, `PrefixCommand`, `Option`, `CommandRegistry`

```python
from kroxy.discord.commands import SlashCommand, PrefixCommand, Option, CommandRegistry

# Slash command with options
@SlashCommand.decorator(
    name="warn",
    description="Warn a member",
    options=[
        Option("user", "The member to warn", option_type="user", required=True),
        Option("reason", "Reason for the warning", required=False),
    ],
    permissions="8",  # Administrator
)
async def warn(interaction, user, reason="No reason provided"):
    ...

# Prefix command with cooldown and aliases
@PrefixCommand.decorator(
    name="ban",
    aliases=["b"],
    description="Ban a member",
    cooldown=5,  # seconds
    permissions=["ban_members"],
)
async def ban(ctx, member, *, reason="No reason"):
    ...

# Registry to manage all commands
registry = CommandRegistry()
registry.add_slash(warn)
registry.add_prefix(ban)
```

---

### `kroxy.discord.utils` — Utility Helpers

Formatting, embed building, permission checks, snowflake parsing, and text helpers.

**Class:** `Utils` (all static methods)

| Method | Description |
|---|---|
| `build_embed(title, description, color, fields, footer, thumbnail, image, author_name, author_icon, timestamp)` | Build a Discord embed dict |
| `mention_user(user_id)` | Returns `<@user_id>` |
| `mention_role(role_id)` | Returns `<@&role_id>` |
| `mention_channel(channel_id)` | Returns `<#channel_id>` |
| `parse_mention(mention)` | Extract raw ID from a mention string |
| `discord_timestamp(dt, style)` | Format datetime as Discord timestamp |
| `time_until(seconds)` | Human-readable countdown (e.g. `"2 hours, 5 minutes"`) |
| `snowflake_to_timestamp(snowflake)` | Convert Discord snowflake to `datetime` |
| `has_permission(permissions, permission_name)` | Check a named permission in a bitfield |
| `permissions_list(permissions)` | List all permissions from a bitfield |
| `truncate(text, max_length, suffix)` | Truncate text to Discord limits |
| `code_block(content, language)` | Wrap in ` ```lang\n...\n``` ` |
| `bold(text)` | `**text**` |
| `italic(text)` | `*text*` |
| `underline(text)` | `__text__` |
| `strikethrough(text)` | `~~text~~` |
| `spoiler(text)` | `\|\|text\|\|` |

```python
from kroxy.discord import Utils

embed = Utils.build_embed(
    title="Server Report",
    description="Weekly summary",
    color=0x5865F2,
    fields=[
        {"name": "Members", "value": "1,200", "inline": True},
        {"name": "Messages", "value": "45,000", "inline": True},
    ],
    footer="kroxy",
    timestamp=True,
)

print(Utils.time_until(3725))       # "1 hour, 2 minutes, 5 seconds"
print(Utils.mention_user(123456))   # "<@123456>"
print(Utils.has_permission(0x8, "administrator"))  # True
```

---

### `kroxy.discord.antinuke` — Anti-Nuke System

Detects and responds to mass destructive actions in real time using rate-limit tracking per user.

**Classes:** `AntiNuke`, `ActionLog`

**Default Thresholds:**

| Action | Limit | Window |
|---|---|---|
| `ban` | 3 | 10s |
| `kick` | 3 | 10s |
| `channel_delete` | 3 | 10s |
| `channel_create` | 5 | 10s |
| `role_delete` | 3 | 10s |
| `role_create` | 5 | 10s |
| `webhook_create` | 3 | 10s |
| `webhook_delete` | 3 | 10s |
| `bot_add` | 2 | 30s |
| `mass_mention` | 5 | 5s |

```python
from kroxy.discord import AntiNuke

antinuke = AntiNuke(
    whitelist=[OWNER_ID, CO_OWNER_ID],
    limits={
        "ban": (2, 5),           # 2 bans in 5s triggers
        "channel_delete": (2, 8),
    }
)

async def on_nuke_detected(action, user_id, guild):
    print(f"[ANTINUKE] {action} triggered by {user_id}")
    # ban/kick/strip roles here

antinuke.on_trigger = on_nuke_detected
antinuke.punishment = "ban"  # "ban" | "kick" | "strip_roles"

# Wire to your event system:
await antinuke.on_member_ban(user_id=executor_id, guild=guild)
await antinuke.on_channel_delete(user_id=executor_id, guild=guild)
await antinuke.on_bot_add(user_id=executor_id, guild=guild)

# Whitelist management:
antinuke.add_whitelist(TRUSTED_MOD_ID)
antinuke.remove_whitelist(REMOVED_MOD_ID)
antinuke.reset_user(user_id)    # Clear all logs for a user
```

---

### `kroxy.discord.checkers` — Permission & Role Checks

Validates permissions and roles, raises `CheckFailed` on failure.

**Class:** `Checkers` (all static methods)

```python
from kroxy.discord import Checkers
from kroxy.discord.checkers import CheckFailed

try:
    Checkers.require_admin(member.permissions)
    Checkers.require_ban_members(member.permissions)
    Checkers.require_role(member.role_ids, MOD_ROLE_ID, "Moderator")
    Checkers.check_hierarchy(
        executor_top_role_pos=member.top_role.position,
        target_top_role_pos=target.top_role.position,
        bot_top_role_pos=bot.top_role.position,
    )
    Checkers.require_guild_only(ctx.guild_id)
    Checkers.block_bots(ctx.author.bot)
except CheckFailed as e:
    await ctx.send(f"❌ {e.message}")
```

| Method | Description |
|---|---|
| `require_admin(permissions)` | Must have Administrator |
| `require_manage_guild(permissions)` | Must have Manage Server |
| `require_manage_roles(permissions)` | Must have Manage Roles |
| `require_ban_members(permissions)` | Must have Ban Members |
| `require_kick_members(permissions)` | Must have Kick Members |
| `require_manage_channels(permissions)` | Must have Manage Channels |
| `require_manage_messages(permissions)` | Must have Manage Messages |
| `require_manage_webhooks(permissions)` | Must have Manage Webhooks |
| `require_role(role_ids, role_id, name)` | Must have specific role |
| `require_any_role(role_ids, role_ids_list)` | Must have at least one role |
| `check_hierarchy(exec_pos, target_pos, bot_pos)` | Role hierarchy validation |
| `require_guild_owner(user_id, owner_id)` | Must be server owner |
| `require_guild_only(guild_id)` | Command must be in a server |
| `require_dm_only(guild_id)` | Command must be in DMs |
| `block_bots(is_bot)` | Reject bot users |
| `require_nsfw(channel_is_nsfw)` | Must be in NSFW channel |

---

### `kroxy.discord.giveaway` — Giveaway Engine

Weighted giveaway system with automatic scheduling, reroll, and bonus-role support.

**Classes:** `GiveawayManager`, `Giveaway`, `GiveawayEntry`

```python
from kroxy.discord.giveaway import GiveawayManager

manager = GiveawayManager()

async def on_end(giveaway, winners):
    winner_mentions = ", ".join(f"<@{w}>" for w in winners)
    print(f"🎉 {giveaway.prize} winners: {winner_mentions}")

manager.on_end = on_end

# Create a giveaway
giveaway = await manager.create(
    prize="1 Month Nitro",
    host_id=123456789,
    channel_id=987654321,
    guild_id=111111111,
    duration=86400,       # 24 hours in seconds
    winner_count=3,
    required_role_id=MEMBER_ROLE_ID,
    bonus_roles={
        BOOSTER_ROLE_ID: 2,   # Boosters get 3 entries total
        VIP_ROLE_ID: 4,       # VIPs get 5 entries total
    },
)

# User joins giveaway
giveaway.add_entry(user_id=555, role_ids=[BOOSTER_ROLE_ID])

# Reroll (exclude previous winners)
new_winners = giveaway.reroll()

# Force-end
await manager.end_now(giveaway.giveaway_id)

# Cancel without picking winners
await manager.cancel(giveaway.giveaway_id)
```

**Giveaway properties:**

| Property | Description |
|---|---|
| `giveaway_id` | Unique 8-char ID |
| `is_active` | `True` if running and not ended |
| `time_remaining` | Seconds until end |
| `total_entries` | Sum of all weighted entries |
| `participant_count` | Number of unique participants |
| `winners` | List of winner user IDs after end |

---

### `kroxy.discord.music` — Music Player

Multi-guild music queue and player state manager. Handles queue logic, looping, shuffle, and volume — plug in your own voice client for audio output.

**Classes:** `MusicPlayerManager`, `MusicPlayer`, `MusicQueue`, `Track`, `LoopMode`

```python
from kroxy.discord.music import MusicPlayerManager, Track, LoopMode

manager = MusicPlayerManager()

# Get or create a player for a guild
player = manager.get_or_create(
    guild_id=111111111,
    channel_id=222222222,      # voice channel
    text_channel_id=333333333, # text channel for now-playing
)

# Create a track
track = Track(
    title="Never Gonna Give You Up",
    url="https://youtube.com/watch?v=...",
    stream_url="https://stream.url/audio.mp3",
    duration=213,              # seconds
    requester_id=123456789,
    thumbnail="https://img.youtube.com/...",
    source="youtube",
)

# Queue management
player.queue.add(track)
player.queue.add_next(track)    # Insert at front
player.queue.shuffle()
player.queue.remove(index=0)
player.queue.move(from_index=2, to_index=0)

# Playback control
await player.play_next()
await player.skip()
player.toggle_pause()           # Returns new paused state
player.set_volume(0.75)         # 0.0 – 2.0
player.set_loop("track")        # "none" | "track" | "queue"
player.stop()                   # Stop + clear queue

# State
state = player.get_state()
# {guild_id, channel_id, current, queue_length, queue_duration,
#  loop_mode, volume, paused, position}

# Events
async def on_track_start(track, player):
    print(f"Now playing: {track.title}")

async def on_queue_empty(guild_id):
    print(f"Queue is empty for guild {guild_id}")

player.on_track_start = on_track_start
player.on_queue_empty = on_queue_empty

# Remove a guild's player
manager.remove(guild_id=111111111)
```

---

## Importing

```python
# Import full module
import kroxy.discord as kd

api      = kd.DiscordAPI(token="Bot TOKEN")
antinuke = kd.AntiNuke(whitelist=[OWNER_ID])
checker  = kd.Checkers()
utils    = kd.Utils()

# Or import specific classes
from kroxy.discord import AntiNuke, Checkers, Utils
from kroxy.discord.giveaway import GiveawayManager
from kroxy.discord.music import MusicPlayerManager, Track
from kroxy.discord.commands import SlashCommand, PrefixCommand, Option
```

---

## Requirements

- Python **3.9+**
- `aiohttp >= 3.8.0`

---

## License

**Proprietary** — Copyright © 2026 kroxy. All rights reserved.

Unauthorized copying, redistribution, or modification of this software is strictly prohibited.
For permissions, contact **@kroxy**.
