Skip to main content

A Pycord-style Python wrapper for hackclub.tv

Project description

hctvwrapper

A Pycord-style Python wrapper for hackclub.tv. Build chat bots with decorators — no boilerplate.

pip install hctvwrapper

Quick Start

from hctvwrapper import Bot

bot = Bot(command_prefix="!")

@bot.event
async def on_ready(session):
    print(f"Logged in as {session.viewer}")

@bot.event
async def on_message(message):
    print(f"{message.author.username}: {message.content}")

@bot.command()
async def ping(ctx):
    await ctx.reply("pong!")

bot.run("hctvb_your_token_here", channel="bot-playground")

Getting a Bot Token

  1. Go to hackclub.tv
  2. Create a bot account and get your API key (starts with hctvb_)
  3. Set it as an environment variable: export BOT_TOKEN=hctvb_xxx

Guide

Events

Register event handlers with @bot.event. The function name determines which event it handles.

@bot.event
async def on_ready(session):
    """Fired when the bot connects and receives session info."""
    print(f"Logged in as {session.viewer.username}")
    print(f"Can moderate: {session.permissions.can_moderate}")
    print(f"Max message length: {session.moderation.max_message_length}")

@bot.event
async def on_message(message):
    """Fired on every chat message."""
    print(f"[{message.channel}] {message.author.username}: {message.content}")
    # message.author.id, .pfp_url, .display_name, .is_bot,
    # .is_platform_admin, .channel_role
    # message.msg_id, .timestamp, .type

@bot.event
async def on_history(messages):
    """Fired once on connect with up to 100 recent messages."""
    print(f"Got {len(messages)} historical messages")

@bot.event
async def on_system_message(message):
    """Fired on system notifications (bans, unbans, etc.)."""
    print(f"System: {message.content}")

@bot.event
async def on_message_deleted(event):
    """Fired when a message is deleted by a moderator."""
    print(f"Message {event.msg_id} deleted in {event.channel}")

@bot.event
async def on_chat_access(access, channel):
    """Fired when chat permissions change (timeouts, bans)."""
    print(f"Can send in {channel}: {access.can_send}")
    if access.restriction:
        print(f"  Restriction: {access.restriction.type}")

@bot.event
async def on_moderation_error(error, channel):
    """Fired when a moderation action or message is rejected."""
    print(f"Error in {channel}: {error.code}{error.message}")
    # error.code is one of: FORBIDDEN, RATE_LIMIT, SLOW_MODE,
    # TIMED_OUT, BANNED, MESSAGE_TOO_LONG, BLOCKED_TERM,
    # INVALID_TARGET, INVALID_REQUEST, NOT_FOUND

Commands

Register commands with @bot.command(). The bot automatically parses messages starting with the prefix.

bot = Bot(command_prefix="!")

# Simple command — no arguments
@bot.command()
async def ping(ctx):
    await ctx.reply("pong!")

# Named command with aliases
@bot.command(name="say", aliases=["echo", "repeat"])
async def say_cmd(ctx, *, text):
    await ctx.send(text)

# Positional arguments (split by whitespace)
@bot.command()
async def greet(ctx, name, greeting="hello"):
    await ctx.reply(f"{greeting}, {name}!")

Context

The ctx object passed to commands gives you everything you need:

@bot.command()
async def info(ctx):
    ctx.message     # the full Message object
    ctx.author      # shortcut to ctx.message.author (Author)
    ctx.channel     # channel name (str)
    ctx.bot         # reference to the Bot

    await ctx.reply("text")   # sends "@username text"
    await ctx.send("text")    # sends "text" without mention
    await ctx.delete()        # deletes the triggering message (needs mod perms)

Sending Messages

# Inside a command
await ctx.reply("mentioned reply")
await ctx.send("plain message")

# Anywhere (if you have a reference to the bot)
await bot.send("hello!", channel="bot-playground")

Multi-Channel

Connect to multiple channels at once:

bot.run("hctvb_xxx", channels=["channel1", "channel2", "bot-playground"])

Messages and commands work across all channels. Use ctx.channel or message.channel to know which channel a message came from.

@bot.event
async def on_message(message):
    print(f"[{message.channel}] {message.author.username}: {message.content}")

@bot.command()
async def where(ctx):
    await ctx.reply(f"you're in {ctx.channel}")

Moderation

Bots with moderation permissions can manage users:

# Timeout a user for 5 minutes (default)
await bot.timeout_user("channel", user_id="user123", duration=300, reason="spam")

# Ban a user
await bot.ban_user("channel", user_id="user123", reason="repeated violations")

# Remove a timeout
await bot.lift_timeout("channel", user_id="user123")

# Unban a user
await bot.unban_user("channel", user_id="user123")

# Delete a specific message
await bot.delete_message("channel", msg_id="msg-uuid")

Async Entry Point

If you manage your own event loop:

import asyncio

async def main():
    bot = Bot(command_prefix="!")

    @bot.event
    async def on_ready(session):
        print("Connected!")

    await bot.start("hctvb_xxx", channel="bot-playground")

asyncio.run(main())

Models Reference

Model Fields
Message content, author, channel, msg_id, timestamp, type, is_bot
Author id, username, pfp_url, display_name, is_bot, is_platform_admin, channel_role
Session viewer (Author), permissions, moderation
Permissions can_moderate
ModerationSettings has_blocked_terms, slow_mode_seconds, max_message_length
SystemMessage type, channel, content, timestamp
ChatAccess can_send, restriction
Restriction type (timeout/ban), reason, expires_at
ModerationError code, message, restriction
ModerationEvent type, msg_id, channel

Requirements

  • Python 3.10+
  • websockets (only dependency)

License

MIT

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

hctvwrapper-0.1.0.tar.gz (11.6 kB view details)

Uploaded Source

Built Distribution

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

hctvwrapper-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

File details

Details for the file hctvwrapper-0.1.0.tar.gz.

File metadata

  • Download URL: hctvwrapper-0.1.0.tar.gz
  • Upload date:
  • Size: 11.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for hctvwrapper-0.1.0.tar.gz
Algorithm Hash digest
SHA256 24fbe72f024bf08e7e4877f6c076f6fc81709c59f76dafe48775b4303bdd7d64
MD5 94dccc7cb688883e3a8360d369453c63
BLAKE2b-256 68ff9c5ecbbfd8663edfa96c3ab6aefa3dd4abbf160eb73af95318a8f23a01d7

See more details on using hashes here.

File details

Details for the file hctvwrapper-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: hctvwrapper-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for hctvwrapper-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0aee6800ca45ba4c7e0f41fe9ffce7e2607dd37accda3bdd5d0552b60746fb21
MD5 cc72e8ceda4d5202a0ee85815f53bc63
BLAKE2b-256 43d5e1508f04af61d7fbba1b69f533daf24a5de1667be86e84c772c913747df9

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