Skip to main content

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

Project description

kroxy

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

PyPI version Python License


Installation

pip install kroxy
pip install --upgrade kroxy

Import Style

Everything in kroxy is available at the top level — no need to navigate into submodules.

# Import the whole package and use anything directly
import kroxy

antinuke = kroxy.AntiNuke(whitelist=[OWNER_ID])
manager  = kroxy.GiveawayManager()
utils    = kroxy.Utils()
api      = kroxy.DiscordAPI(token="Bot TOKEN")
# Or import exactly what you need
from kroxy import AntiNuke, Checkers, Utils
from kroxy import GiveawayManager, Giveaway
from kroxy import MusicPlayerManager, Track
from kroxy import SlashCommand, PrefixCommand, Option
from kroxy import DiscordAPI
# Submodule access also works if preferred
from kroxy import discord

discord.AntiNuke(...)
discord.Utils.build_embed(...)

Package Structure

kroxy/
├── discord/
│   ├── api.py        ← Async Discord REST API client
│   ├── commands.py   ← Slash and prefix command builders
│   ├── utils.py      ← Embeds, mentions, timestamps, permissions, formatting
│   ├── antinuke.py   ← Real-time nuke detection and auto-punishment
│   ├── checkers.py   ← Permission, role, and hierarchy validation
│   ├── giveaway.py   ← Weighted giveaway engine with scheduling
│   └── music.py      ← Multi-guild music queue and player manager
└── website/          ← Coming soon

Module Reference

DiscordAPI — Discord REST API Client

Async HTTP client for the Discord REST API v10.

Constructor: DiscordAPI(token: str, bot: bool = True)

from kroxy import DiscordAPI

api = DiscordAPI(token="Bot YOUR_TOKEN")

guild   = await api.get_guild(GUILD_ID)
channel = await api.get_channel(CHANNEL_ID)
user    = await api.get_user(USER_ID)

await api.send_message(channel_id=CHANNEL_ID, content="Hello!")
await api.send_message(channel_id=CHANNEL_ID, embed=embed_dict)

await api.ban_member(GUILD_ID, USER_ID, reason="Spam", delete_message_days=1)
await api.unban_member(GUILD_ID, USER_ID)
await api.kick_member(GUILD_ID, USER_ID, reason="AFK")

await api.add_role(GUILD_ID, USER_ID, ROLE_ID)
await api.remove_role(GUILD_ID, USER_ID, ROLE_ID)

await api.create_channel(GUILD_ID, name="general", channel_type=0)
await api.delete_channel(CHANNEL_ID)

await api.get_audit_logs(GUILD_ID, limit=50)
await api.get_invites(GUILD_ID)
await api.delete_invite("invite_code")
await api.get_webhooks(GUILD_ID)
await api.delete_webhook(WEBHOOK_ID)

await api.close()

AntiNuke — Anti-Nuke System

Detects mass destructive actions and triggers automatic punishment.

Constructor: AntiNuke(whitelist: list = [], limits: dict = {})

Default Limits:

Action Threshold 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
from kroxy import AntiNuke

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

async def on_nuke(action, user_id, guild):
    print(f"[NUKE] {action} by {user_id}")

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

# Wire to your event handlers:
await antinuke.on_member_ban(user_id=executor_id, guild=guild)
await antinuke.on_member_kick(user_id=executor_id, guild=guild)
await antinuke.on_channel_delete(user_id=executor_id, guild=guild)
await antinuke.on_channel_create(user_id=executor_id, guild=guild)
await antinuke.on_role_delete(user_id=executor_id, guild=guild)
await antinuke.on_role_create(user_id=executor_id, guild=guild)
await antinuke.on_webhook_create(user_id=executor_id, guild=guild)
await antinuke.on_webhook_delete(user_id=executor_id, guild=guild)
await antinuke.on_bot_add(user_id=executor_id, guild=guild)
await antinuke.on_mass_mention(user_id=executor_id, guild=guild)

# Whitelist management
antinuke.add_whitelist(MOD_ID)
antinuke.remove_whitelist(MOD_ID)
antinuke.reset_user(USER_ID)

# View current config
print(antinuke.get_stats())

Checkers — Permission & Role Validation

Raises CheckFailed on failure, returns True on success.

from kroxy import Checkers, CheckFailed

try:
    Checkers.require_admin(member.permissions)
    Checkers.require_ban_members(member.permissions)
    Checkers.require_manage_guild(member.permissions)
    Checkers.require_manage_roles(member.permissions)
    Checkers.require_manage_channels(member.permissions)
    Checkers.require_manage_messages(member.permissions)
    Checkers.require_manage_webhooks(member.permissions)

    Checkers.require_role(member.role_ids, MOD_ROLE_ID, "Moderator")
    Checkers.require_any_role(member.role_ids, [MOD_ROLE_ID, ADMIN_ROLE_ID])

    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_owner(user_id, guild.owner_id)
    Checkers.require_guild_only(ctx.guild_id)
    Checkers.require_dm_only(ctx.guild_id)
    Checkers.block_bots(ctx.author.bot)
    Checkers.require_nsfw(channel.nsfw)

except CheckFailed as e:
    await ctx.send(f"❌ {e.message}")

Utils — General Utilities

Embed builder, mentions, timestamps, permissions, and text formatters.

from kroxy import Utils

# Embed builder
embed = Utils.build_embed(
    title="Title",
    description="Description here",
    color=0x5865F2,
    fields=[
        {"name": "Field 1", "value": "Value 1", "inline": True},
        {"name": "Field 2", "value": "Value 2", "inline": True},
    ],
    footer="kroxy",
    thumbnail="https://example.com/thumb.png",
    image="https://example.com/image.png",
    author_name="Bot Name",
    author_icon="https://example.com/icon.png",
    timestamp=True,
)

# Mentions
Utils.mention_user(123456)         # <@123456>
Utils.mention_role(654321)         # <@&654321>
Utils.mention_channel(999999)      # <#999999>
Utils.parse_mention("<@123456>")   # 123456

# Timestamps
Utils.discord_timestamp(datetime.now(), style="R")   # Relative: "5 minutes ago"
Utils.discord_timestamp(datetime.now(), style="F")   # Full: "21 June 2026 12:00"
Utils.time_until(3725)             # "1 hour, 2 minutes, 5 seconds"
Utils.snowflake_to_timestamp(snowflake_id)

# Permissions
Utils.has_permission(perms_bitfield, "administrator")   # True/False
Utils.has_permission(perms_bitfield, "ban_members")
Utils.permissions_list(perms_bitfield)   # ["administrator", "ban_members", ...]

# Text formatting
Utils.truncate(text, max_length=2048)
Utils.code_block("print('hi')", language="python")
Utils.bold("text")           # **text**
Utils.italic("text")         # *text*
Utils.underline("text")      # __text__
Utils.strikethrough("text")  # ~~text~~
Utils.spoiler("text")        # ||text||
Utils.inline_code("text")    # `text`

GiveawayManager / Giveaway — Giveaway Engine

Weighted giveaway system with bonus roles, reroll, and auto-scheduling.

from kroxy import GiveawayManager

manager = GiveawayManager()

async def on_end(giveaway, winners):
    print(f"Winners of '{giveaway.prize}': {winners}")

manager.on_end = on_end

# Create
giveaway = await manager.create(
    prize="Discord Nitro",
    host_id=HOST_USER_ID,
    channel_id=CHANNEL_ID,
    guild_id=GUILD_ID,
    duration=86400,          # seconds (24 hours)
    winner_count=3,
    required_role_id=MEMBER_ROLE_ID,
    bonus_roles={
        BOOSTER_ROLE_ID: 2,  # Boosters: 3 entries
        VIP_ROLE_ID: 4,      # VIPs: 5 entries
    },
)

# Entries
giveaway.add_entry(user_id=555, role_ids=[BOOSTER_ROLE_ID])
giveaway.remove_entry(user_id=555)

# Info
giveaway.is_active         # True/False
giveaway.time_remaining    # seconds left
giveaway.total_entries     # weighted total
giveaway.participant_count # unique users
giveaway.giveaway_id       # "A1B2C3D4"

# Control
await manager.end_now(giveaway.giveaway_id)    # Force end
await manager.cancel(giveaway.giveaway_id)     # Cancel (no winner)
new_winners = giveaway.reroll()                # Reroll

# Lookup
manager.get(giveaway_id)
manager.get_by_message(message_id)
manager.all_active()
manager.all_ended()

MusicPlayerManager / MusicPlayer / Track — Music

Multi-guild music queue and player state manager.

from kroxy import MusicPlayerManager, Track, LoopMode

manager = MusicPlayerManager()

# Get or create a guild player
player = manager.get_or_create(
    guild_id=GUILD_ID,
    channel_id=VOICE_CHANNEL_ID,
    text_channel_id=TEXT_CHANNEL_ID,
)

# Create a track
track = Track(
    title="Song Name",
    url="https://youtube.com/watch?v=...",
    stream_url="https://audio.stream/url.mp3",
    duration=240,             # seconds
    requester_id=USER_ID,
    thumbnail="https://img.youtube.com/vi/.../0.jpg",
    source="youtube",
)

# Queue
player.queue.add(track)
player.queue.add_next(track)       # Play next
player.queue.shuffle()
player.queue.remove(index=0)
player.queue.move(from_index=2, to_index=0)
player.queue.clear()
len(player.queue)                  # queue size
player.queue.total_duration        # seconds
player.queue.is_empty              # True/False

# Playback
await player.play_next()           # Play next track (respects loop)
await player.skip()                # Skip current track
player.toggle_pause()              # Returns new paused state (True/False)
player.set_volume(0.75)            # 0.0 – 2.0
player.set_loop("track")           # "none" | "track" | "queue"
player.stop()                      # Stop + clear queue

# State
player.current                     # Current Track or None
player.paused                      # True/False
player.volume                      # 0.0 – 2.0
player.position                    # Current position in seconds
player.loop_mode                   # LoopMode.NONE / TRACK / QUEUE
player.get_state()                 # Full state dict

# Events
async def now_playing(track, player):
    print(f"Now playing: {track.title} [{track.duration_str}]")

async def queue_empty(guild_id):
    print("Queue finished.")

player.on_track_start = now_playing
player.on_track_end   = None
player.on_queue_empty = queue_empty

# Cleanup
manager.remove(guild_id=GUILD_ID)

SlashCommand / PrefixCommand — Command Builders

from kroxy import SlashCommand, PrefixCommand, Option, CommandRegistry

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

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

# Slash command export (for registering with Discord API)
warn.to_dict()

# Command registry
registry = CommandRegistry()
registry.add_slash(warn)
registry.add_prefix(ban)

registry.get_slash("warn")
registry.get_prefix("ban")
registry.get_prefix("b")    # aliases work too
registry.all_slash()
registry.all_prefix()

Quick Start Example

import kroxy

async def main():
    api      = kroxy.DiscordAPI(token="Bot YOUR_TOKEN")
    antinuke = kroxy.AntiNuke(whitelist=[OWNER_ID])
    manager  = kroxy.GiveawayManager()
    player   = kroxy.MusicPlayerManager().get_or_create(GUILD_ID)

    embed = kroxy.Utils.build_embed(
        title="Bot Ready",
        description="kroxy is running.",
        color=0x5865F2,
        timestamp=True,
    )
    await api.send_message(LOG_CHANNEL_ID, embed=embed)

    giveaway = await manager.create(
        prize="Nitro",
        host_id=HOST_ID,
        channel_id=CHANNEL_ID,
        guild_id=GUILD_ID,
        duration=3600,
        winner_count=1,
    )

    await api.close()

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. Contact @kroxy for permissions.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kroxy-1.0.1.tar.gz (22.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kroxy-1.0.1-py3-none-any.whl (21.2 kB view details)

Uploaded Python 3

File details

Details for the file kroxy-1.0.1.tar.gz.

File metadata

  • Download URL: kroxy-1.0.1.tar.gz
  • Upload date:
  • Size: 22.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for kroxy-1.0.1.tar.gz
Algorithm Hash digest
SHA256 1bbceb2911cf192527dbc4d00c62fbe5c9fc3ea79f46e1a836edfc076ce16b4f
MD5 fa0e84b8fae58e21e584965f44929388
BLAKE2b-256 2d4b0c6018be78e4ce2200c66961598a63f49ca15dc47c46af0e5b75f1fa9936

See more details on using hashes here.

File details

Details for the file kroxy-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: kroxy-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 21.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.14

File hashes

Hashes for kroxy-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 e2e03ca6a3017d9cf464deb7e4119cc50a51677b3dbe717f531c4758ae771305
MD5 a5ed30b4ef200e4ecd25339fa6dec97c
BLAKE2b-256 0209c54c396f8b05eaf1cc2add0eca7b1814c875c7d3edaccff57bce101faf48

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page