Python bot library for veretube sync channels
Project description
veretube-bot
Python library for writing bots on sync 4.0 aka veretube channels.
Bots connect over socket.io for real-time events (chat, user list, playlist changes) and use a REST API for commands (queue media, kick/ban, manage emotes, read/write settings). Both surfaces are covered by this library.
Installation
pip install veretube-bot
Getting a token
Tokens are issued in the channel settings modal on the Bots tab. You need at least moderator rank to see it. Fill in a name and rank, click Issue Token, and copy the token immediately — it starts with cbt_ and is only shown once.
Quick start
from veretube_bot import Bot
bot = Bot(
token="cbt_...",
channel="mychannel",
socket_url="http://your-server:1337", # socket.io port (default 1337)
api_url="http://your-server:8080/api/v1", # HTTP port (default 8080)
)
@bot.on("chatMsg")
def on_chat(data):
if data["msg"] == "!hello":
bot.send_message("Hello!", to=data["username"])
if data["msg"] == "!np":
if bot.now_playing:
bot.send_message(f"Now playing: {bot.now_playing['title']}")
@bot.on("changeMedia")
def on_media(data):
print(f"Now playing: {data['title']}")
bot.run() # connect and block until disconnected
Connection
Bot(
token, # str — bot token starting with 'cbt_'
channel, # str — channel name (lowercase, no '#')
socket_url, # str — socket.io server URL (uses io.port, not the HTTP port)
api_url, # str — REST API base URL, e.g. http://host:8080/api/v1
reconnection=False, # set True to reconnect automatically on drop
reconnection_delay=3, # seconds between reconnect attempts
)
| Method | Description |
|---|---|
bot.run() |
Connect and block until disconnected |
bot.connect() |
Open the connection (returns immediately) |
bot.wait() |
Block until disconnected (call after connect()) |
bot.disconnect() |
Close the connection |
By default reconnection=False — the expectation is that an external process supervisor (systemd, supervisord, etc.) handles restarts. Pass reconnection=True for bots that should self-recover.
Event handling
Register handlers with @bot.on(event_name). Multiple handlers for the same event are all called. Exceptions in a handler are logged and skipped so one bad handler doesn't affect the others.
@bot.on("chatMsg")
def on_chat(data):
print(data["username"], data["msg"])
@bot.on("userLeave")
def on_leave(data):
print(f"{data['name']} left")
Socket events
| Event | Payload | Description |
|---|---|---|
connect |
None |
Socket connected |
disconnect |
reason string or None |
Socket disconnected |
connect_error |
error object | Connection failed |
login |
{ success, name, guest } |
Server accepted the token |
chatMsg |
{ username, msg, meta, time } |
Chat message sent |
pm |
{ username, msg, meta } |
Private message received |
userlist |
[{ name, rank, meta }, ...] |
Full user list on join |
addUser |
{ name, rank, meta } |
User joined |
userLeave |
{ name } |
User left |
setUserMeta |
{ name, meta } |
User AFK/muted state changed |
setUserRank |
{ name, rank } |
User rank changed |
changeMedia |
{ id, type, title, seconds, ... } |
New video started |
playlist |
[{ uid, media, queueby, temp }, ...] |
Full playlist on join |
queue |
{ item, after } |
Item added to playlist |
delete |
{ uid } |
Playlist item removed |
channelOpts |
settings dict | Channel options updated |
clearchat |
None |
Chat cleared by a moderator |
errorMsg |
{ msg } |
Error from the server |
kick |
{ reason } |
Bot was kicked |
announcement |
{ title, text } |
Server-wide announcement |
updateEmote |
{ name, image } |
Emote added or changed |
removeEmote |
{ name } |
Emote removed |
meta.is_bot is True in chatMsg and userlist payloads for bots.
In-memory state
These are updated automatically from socket events before your handlers are called:
bot.users # list of { name, rank, meta } — current user list
bot.now_playing # { id, type, title, seconds, ... } or None
bot.playlist # list of playlist items
bot.channel_opts # channel options dict
Look up a specific user:
user = bot.get_user("Alice") # returns dict or None
Chat
bot.send_message("Hello!")
bot.send_message("Hey!", to="Alice") # sends "Alice: Hey!"
bot.send_action("waves") # sends "/me waves"
bot.send_pm("Alice", "Hello privately")
Playlist
bot.queue("dQw4w9WgXcQ", "yt") # add to end (rank >= MOD)
bot.queue("dQw4w9WgXcQ", "yt", "next") # add as next up
bot.skip() # skip to next item (rank >= MOD)
bot.skip_to(uid) # jump to specific uid (rank >= MOD)
bot.delete_item(uid) # remove by uid (rank >= ADMIN)
bot.shuffle_playlist() # shuffle (rank >= ADMIN)
bot.clear_playlist() # clear all (rank >= ADMIN)
Media types: yt YouTube, sc SoundCloud, tw Twitch stream, tc Twitch clip, vm Vimeo, dm Dailymotion, fi direct file URL, cu custom embed.
Moderation
bot.kick("BadUser") # rank >= MOD
bot.kick("BadUser", reason="Spamming")
bot.ban("BadUser") # rank >= ADMIN
bot.ban("BadUser", reason="Evading")
bot.unban("BadUser") # rank >= ADMIN
bot.set_rank("Alice", Rank.MOD) # rank >= OWNER
Emotes
Emote endpoints read/write the database directly and work even when the channel is offline.
emotes = bot.get_emotes() # list of { name, image, source }
bot.add_emote("KEKW", "https://...") # rank >= OWNER
bot.update_emote("KEKW", image="https://...")
bot.update_emote("KEKW", new_name="KEKWait")
bot.delete_emote("KEKW") # rank >= OWNER
Settings
settings = bot.get_settings() # rank >= OWNER, channel must be active
bot.update_settings(pagetitle="Now Playing: Chill Beats")
bot.update_settings(allow_voteskip=False, afk_timeout=300)
Available setting keys: allow_voteskip, allow_dupes, voteskip_ratio, maxlength, playlist_max_duration_per_user, afk_timeout, enable_link_regex, chat_antiflood, chat_antiflood_burst, chat_antiflood_sustained, new_user_chat_delay, new_user_chat_link_delay, pagetitle, password, externalcss, externaljs, show_public, torbanned, block_anonymous_users, allow_ascii_control, playlist_max_per_user.
Direct REST access
Every REST endpoint is also accessible on bot.api if you need something not covered by the shortcuts:
playlist = bot.api.get_playlist() # { items, currentIndex, locked }
bot.api.skip_to(uid)
bot.api.set_user_rank("Alice", 2)
Error handling
REST calls raise BotAPIError on failure:
from veretube_bot import Bot, BotAPIError
@bot.on("chatMsg")
def on_chat(data):
if data["msg"].startswith("!add "):
_, type, id = data["msg"].split(None, 2)
try:
bot.queue(id, type)
except BotAPIError as e:
bot.send_message(f"Error: {e}") # e.status_code has the HTTP code
Rank constants
from veretube_bot import Rank
Rank.MOD # 2
Rank.ADMIN # 3
Rank.OWNER # 4
Rank.CREATOR # 5
A bot's effective rank is capped at the rank of the user who issued its token.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file veretube_bot-0.1.0.tar.gz.
File metadata
- Download URL: veretube_bot-0.1.0.tar.gz
- Upload date:
- Size: 12.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e4de354fc6f6af0332d9e798bd628ff124fa809dd9fcbad1caf414d275381b0
|
|
| MD5 |
b0e82a7921e723e4cc79120c35182eaf
|
|
| BLAKE2b-256 |
e8a8f3f7175128b518ef016148a3e5ea5cd665b5c66fa12d46e71dd76ac394b0
|
File details
Details for the file veretube_bot-0.1.0-py3-none-any.whl.
File metadata
- Download URL: veretube_bot-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e9aa94b173b60fc3967a2cb91fd5fced39e7e26f125487f51a0d7bd8e2d9a91b
|
|
| MD5 |
5261c8687147c96c3a59414342af8c92
|
|
| BLAKE2b-256 |
aa63b33cd47f5b48fbb94d0fb52e866ff8b1b8daf7a33cbe7b55e3097823bc6d
|