ggbro Developer Documentation

Build bots, integrations, and tools for your ggbro community.

Need a single URL for another AI? Use /developers/reference.md. It is a raw Markdown reference covering bot creation, Socket.IO events, embeds, interactions, and the full REST route catalog.

Introduction

Platform: ggbro is a custom Socket.IO-based chat platform (similar to Discord but with its own protocol). Bots connect via Socket.IO v4 for real-time events and use a REST API for data fetching. There is no official SDK — you use raw python-socketio (Python) or socket.io-client (JavaScript/Node.js) directly.

Base URL: https://ggbro.jadadev.com
API Base: https://ggbro.jadadev.com/api
Socket.IO Gateway: https://ggbro.jadadev.com (same origin)

The ggbro Bot API allows you to create bots that:

Technology Stack

ComponentTechnologyPackage to Install
Real-time GatewaySocket.IO v4Python: python-socketio[client] — Node.js: socket.io-client
REST APIHTTP JSONPython: requests — Node.js: axios or built-in fetch
AuthenticationBearer token (JWT)Passed in headers (REST) and handshake auth (Socket.IO)

Quick Start

Here's the fastest way to get a bot running:

  1. Go to the Developer Portal or ggbro app → User SettingsApplications
  2. Create an Application — this automatically creates a bot user and gives you a token
  3. Copy the Bot Token — you'll need it to authenticate
  4. Add the bot to a server you own or admin
  5. Connect via Socket.IO, register slash commands, and start responding!

Minimal Python Bot (5 lines to connect)

bash Install dependencies
pip install "python-socketio[client]" requests
Python minimal_bot.py
import socketio sio = socketio.Client() @sio.event def connect(): print("Connected to ggbro!") sio.connect("https://ggbro.jadadev.com", auth={"token": "YOUR_BOT_TOKEN"}) sio.wait()

Minimal Node.js Bot

bash Install dependencies
npm install socket.io-client
JavaScript minimal_bot.js
const { io } = require("socket.io-client"); const socket = io("https://ggbro.jadadev.com", { auth: { token: "YOUR_BOT_TOKEN" } }); socket.on("connect", () => console.log("Connected to ggbro!"));

Authentication

All API requests require a Bearer token in the Authorization header:

HTTP Authentication Header
Authorization: Bearer YOUR_BOT_TOKEN

For Socket.IO connections, pass the token in the handshake auth object:

Python Socket.IO Auth
import socketio sio = socketio.Client(reconnection=True, reconnection_delay=1) sio.connect("https://ggbro.jadadev.com", auth={"token": "YOUR_BOT_TOKEN"})
JavaScript Socket.IO Auth
const { io } = require("socket.io-client"); const socket = io("https://ggbro.jadadev.com", { auth: { token: "YOUR_BOT_TOKEN" } });
Keep your token secret! Anyone with your bot token can control your bot. If compromised, regenerate it immediately from the Developer Portal.

Creating a Bot

Create an application via the Developer Portal UI, or via the REST API:

POST /api/oauth2/applications

Create a new application. Automatically creates a bot user account and returns a bot token.

JSON Request Body
{ "name": "My Awesome Bot", "description": "A bot that does cool things" }
JSON Response
{ "application": { "id": "abc123...", "name": "My Awesome Bot", "bot_user_id": "bot456...", "client_secret": "hex..." }, "bot_token": "eyJhbGciOi..." }

Application Management Endpoints

MethodPathDescription
GET/api/oauth2/applicationsList your applications
GET/api/oauth2/applications/:appIdGet application details
PUT/api/oauth2/applications/:appIdUpdate application name and description
POST/api/oauth2/applications/:appId/tokenRegenerate the bot token
DELETE/api/oauth2/applications/:appIdDelete the application and its bot user
POST/api/oauth2/applications/:appId/avatarUpload bot avatar (multipart, field: avatar)
POST/api/oauth2/applications/:appId/bannerUpload bot banner (multipart, field: banner)
PATCH/api/oauth2/applications/:appId/banner-offsetSet banner offset position
PATCH/api/oauth2/applications/:appId/public-inviteToggle public invite on/off

Bot Command Management

MethodPathDescription
GET/api/oauth2/applications/:appId/commandsList all commands registered for this bot
POST/api/oauth2/applications/:appId/commandsCreate a new command for this bot
PUT/api/oauth2/applications/:appId/commands/:cmdIdUpdate a specific command
DELETE/api/oauth2/applications/:appId/commands/:cmdIdDelete a specific command
GET/api/oauth2/servers/:serverId/commandsList all bot commands available in a server

Adding Bot to a Server

To add your bot to a server, you must be an admin or owner of that server:

POST /api/oauth2/applications/:appId/servers/:serverId

Add the bot to a server. Requires admin/owner permissions on the target server.

DELETE /api/oauth2/applications/:appId/servers/:serverId

Remove the bot from a server.

GET /api/oauth2/applications/:appId/servers

List the servers the bot is currently a member of.

Socket.IO Gateway

Bots connect to the real-time gateway using Socket.IO v4. The gateway provides live events for messages, interactions, typing, presence, and voice.

Important: This is a standard Socket.IO v4 server. Use python-socketio (Python) or socket.io-client (Node.js). Do not use raw WebSocket libraries — Socket.IO has its own protocol on top of WebSocket.

Connecting & Joining Rooms

After connecting, you must join server and channel rooms to receive events:

Python Connect and Join Rooms
import socketio sio = socketio.Client(reconnection=True) @sio.event def connect(): print("Connected!") # Join a server room to receive member events, typing, etc. sio.emit("server:join", "YOUR_SERVER_ID") # Join a channel room to receive messages in that channel sio.emit("channel:join", "YOUR_CHANNEL_ID") sio.connect("https://ggbro.jadadev.com", auth={"token": "YOUR_BOT_TOKEN"}) sio.wait()
JavaScript Connect and Join Rooms
const { io } = require("socket.io-client"); const socket = io("https://ggbro.jadadev.com", { auth: { token: "YOUR_BOT_TOKEN" } }); socket.on("connect", () => { console.log("Connected!"); socket.emit("server:join", "YOUR_SERVER_ID"); socket.emit("channel:join", "YOUR_CHANNEL_ID"); });

Room Events

Emit EventPayloadDescription
server:join"serverId" (string)Join a server room to receive member/presence events
channel:join"channelId" (string)Join a channel room to receive message:new events

Slash Commands

Slash commands let users interact with your bot by typing /commandname. Users see an autocomplete dropdown.

Registering Commands

Register commands via REST API using your bot token. This replaces all existing global commands:

POST /api/oauth2/commands

Bulk register slash commands. Requires bot token auth. Send an array of command objects.

Python Register Commands
import requests BOT_TOKEN = "YOUR_BOT_TOKEN" API_URL = "https://ggbro.jadadev.com" commands = [ { "name": "ping", "description": "Check if the bot is alive", "options": [] }, { "name": "play", "description": "Play a song", "options": [ {"name": "query", "description": "YouTube URL or search term", "required": True} ] } ] r = requests.post( f"{API_URL}/api/oauth2/commands", json=commands, headers={"Authorization": f"Bearer {BOT_TOKEN}"} ) print("Commands registered!" if r.ok else f"Failed: {r.text}")
JavaScript Register Commands
const axios = require("axios"); const BOT_TOKEN = "YOUR_BOT_TOKEN"; const API_URL = "https://ggbro.jadadev.com"; axios.post(`${API_URL}/api/oauth2/commands`, [ { name: "ping", description: "Check bot latency", options: [] } ], { headers: { Authorization: `Bearer ${BOT_TOKEN}` } }).then(() => console.log("Commands registered!"));

Command Options

FieldTypeDescription
namestringCommand name (1-32 chars, alphanumeric/hyphens/underscores)
descriptionstringShort description shown in autocomplete
optionsarrayArray of {name, description, required?} option objects

Receiving & Responding to Interactions

When a user runs a slash command, your bot receives an interaction:create event via Socket.IO. Respond with interaction:response:

Python Handle Slash Command
@sio.on("interaction:create") def on_interaction(data): # data object: # { # "id": "interaction-uuid", <-- use this as interaction_id in response # "type": "slash_command", # "command": "ping", <-- the command name # "args": "raw argument string", <-- everything after /command # "options": {"query": "value"}, <-- parsed options dict # "channel_id": "channel-uuid", # "server_id": "server-uuid", # "user": {"id": "user-uuid", "username": "JadaDev"} # } cmd = data.get("command", "").lower() if cmd == "ping": sio.emit("interaction:response", { "interaction_id": data["id"], "channel_id": data["channel_id"], "content": "Pong! πŸ“" })
JavaScript Handle Slash Command
socket.on("interaction:create", (data) => { const cmd = (data.command || "").toLowerCase(); if (cmd === "ping") { socket.emit("interaction:response", { interaction_id: data.id, channel_id: data.channel_id, content: "Pong! πŸ“" }); } });
Key fields in the interaction data:
data["id"] → Use as interaction_id in your response
data["command"] → The slash command name (e.g. "ping")
data["args"] → Raw text after the command name
data["options"] → Parsed options as a dictionary (e.g. {"query": "lofi"})
data["channel_id"] → Channel where the command was used
data["server_id"] → Server ID
data["user"] → User object with id and username

Sending Messages

Bots can send messages to any channel they have access to. Use the bot:send_message Socket.IO event:

Ack payloads: bot:send_message, interaction:response, and bot:edit_message all return an acknowledgement payload with {ok, message_id, message}. Store the returned message_id if you plan to edit the message later.
Python Send a Message
# Send a simple text message sio.emit("bot:send_message", { "channel_id": "YOUR_CHANNEL_ID", "content": "Hello from my bot! πŸ€–" })
JavaScript Send a Message
// Send a simple text message socket.emit("bot:send_message", { channel_id: "YOUR_CHANNEL_ID", content: "Hello from my bot! πŸ€–" });

Editing a Bot Message

Bot-authored channel messages can be edited later with bot:edit_message. Edited messages automatically show an edited marker and timestamp in the client UI.

JavaScript Edit a Previously Sent Message
socket.emit("bot:edit_message", { channel_id: channelId, message_id: existingMessageId, content: "Updated content", embeds: [{ title: "Updated Panel", description: "This embed was edited in place.", color: "#23A55A" }] });

You can also send messages via the REST API:

POST /api/messages/:channelId/upload

Send a message (with optional file attachments). Use form data with a content field.

Embed Messages

Bots can send rich embed messages — similar to Discord embeds. Embeds display a colored sidebar, title, description, fields grid, images, and footer. Use them for /serverinfo, now-playing cards, leaderboards, help menus, and more.

Embed Object

FieldTypeDescription
titlestring?Embed title (rendered as a link if url is set)
descriptionstring?Main text body
urlstring?URL the title links to
colorstring?Left border colour as hex string, e.g. "#5865F2"
fieldsarray?Array of {name: string, value: string, inline?: boolean}
thumbnailstring?Small image URL (top-right corner)
imagestring?Large image URL (bottom of embed)
footerobject?{text: string, icon_url?: string}
authorobject?{name: string, url?: string, icon_url?: string}
timestampstring?ISO-8601 timestamp shown next to footer
componentsarray?Interactive components rendered under the embed. Supported types: button, string_select, channel_select

Interactive Components

TypeRequired FieldsNotes
button{type, label, custom_id}Use style = primary, secondary, success, danger, or link. Link buttons use url instead of custom_id.
string_select{type, custom_id, options[]}Each option supports {label, value, description?, emoji?, default?}.
channel_select{type, custom_id}Use channel_types to limit results, for example ["text"].

Sending Embeds

Pass an embeds array in either bot:send_message or interaction:response. You can include content alongside embeds, or send embeds only (with empty content):

Python Send an Embed via bot:send_message
sio.emit("bot:send_message", { "channel_id": channel_id, "content": "", "embeds": [{ "title": "Hello World", "description": "This is a rich embed message!", "color": "#5865F2", "fields": [ {"name": "Field 1", "value": "Some value", "inline": True}, {"name": "Field 2", "value": "Another value", "inline": True}, ], "footer": {"text": "Powered by ggbro"} }] })
Python Reply to a Slash Command with an Embed
@sio.on("interaction:create") def on_interaction(data): if data["command"] == "info": sio.emit("interaction:response", { "interaction_id": data["id"], "channel_id": data["channel_id"], "content": "", "embeds": [{ "title": "Bot Info", "description": "I'm a bot built for ggbro!", "color": "#23a55a", "author": {"name": "My Bot"}, "timestamp": datetime.utcnow().isoformat() }] })
JavaScript Send an Embed
socket.emit("bot:send_message", { channel_id: channelId, content: "", embeds: [{ title: "Now Playing 🎡", description: `Duration: 3:45 | Requested by JadaDev`, color: "#FF0000", thumbnail: "https://i.ytimg.com/vi/.../hqdefault.jpg", author: { name: "Music Bot" }, footer: { text: "Queue: 5 songs remaining" }, components: [ { type: "button", custom_id: "music:pause", label: "Pause", style: "secondary", emoji: { name: "⏸️" } }, { type: "button", custom_id: "music:skip", label: "Skip", style: "primary", emoji: { name: "⏭️" } }, { type: "string_select", custom_id: "music:volume", placeholder: "Set volume", options: [ { label: "50%", value: "50" }, { label: "100%", value: "100", default: true }, { label: "150%", value: "150" } ] }, { type: "channel_select", custom_id: "music:panel-channel", placeholder: "Move panel to a text channel", channel_types: ["text"] } ] }] });

Handling Component Interactions

When a user presses a button or changes a select menu, your bot receives another interaction:create event with type = "message_component".

JavaScript Handle Button and Select Interactions
socket.on("interaction:create", async (data) => { if (data.type !== "message_component") return; if (data.custom_id === "music:skip") { // Update your state, then edit the original control message socket.emit("bot:edit_message", { channel_id: data.channel_id, message_id: data.message_id, embeds: [{ title: "Skipped", description: "Queue advanced.", color: "#5865F2" }] }); } if (data.custom_id === "music:panel-channel") { const selected = data.selected_channels?.[0]; if (!selected) return; socket.emit("bot:send_message", { channel_id: selected.id, embeds: [{ title: "Panel moved", description: "Controls are now posted in this channel." }] }); } });

Events Reference

Events Your Bot Receives (listen with sio.on() or socket.on())

EventWhenPayload
interaction:createUser runs a slash command or uses an embed component{id, type, command?, args?, options?, custom_id?, component_type?, values?, selected_channels?, channel_id, server_id, message_id?, user}
message:newNew message in a joined channel{id, channel_id, user_id, content, username, avatar, is_bot, embeds?, ...}
message:updateA message in a joined channel was edited{id, channel_id, content, updated_at, embeds?, ...}
member:joinedUser joins a server{serverId, userId, username, avatar}
user:statusUser goes online/offline{userId, status}
message:reactionReaction added/removed{channelId, messageId, emoji, userId, action}
typing:startUser starts typing{userId, username}
voice:existingAfter joining a voice room[{socketId, userId, username, muted, deafened, videoEnabled, screenSharing}]
voice:user-joinedUser joins your voice room{socketId, userId, username, ...}

Events Your Bot Can Emit (send with sio.emit() or socket.emit())

EventPayloadDescription
interaction:response{interaction_id, channel_id, content, embeds?}Respond to a slash command
bot:send_message{channel_id, content?, embeds?}Send a message to any channel (text and/or embeds)
bot:edit_message{message_id, channel_id?, content?, embeds?}Edit a previously sent bot message and update embeds/components in place
server:join"serverId"Join a server room
channel:join"channelId"Join a channel room
voice:join{channelId}Join a voice channel
voice:leave(none)Leave voice channel
bot:voice-query{userId, serverId}Look up which voice channel a user is in
bot:voice-participants{channelId}Get participant list for a voice channel

REST API Overview

All REST endpoints use the base URL https://ggbro.jadadev.com/api and require Bearer token authentication in the Authorization header.

Servers

GET/api/servers

List all servers the bot is a member of.

GET/api/servers/:id

Get server details (name, icon, banner, description, member count).

GET/api/servers/:id/members

List server members with roles, avatars, statuses, and bios.

GET/api/servers/:id/bans

Get the list of banned users for this server.

GET/api/servers/:id/audit-log

Get the server audit log. Query params: ?limit=50

POST/api/servers/:id/bans

Ban a user from the server. Body: {"targetUserId": "..."}

DELETE/api/servers/:id/bans/:targetUserId

Unban a user from the server.

DELETE/api/servers/:id/members/:targetUserId

Kick a member from the server.

POST/api/servers/:id/timeouts

Timeout a member. Body: {"targetUserId": "...", "duration": 300}

DELETE/api/servers/:id/timeouts/:targetUserId

Remove timeout from a member.

GET/api/servers/:id/gifs

List server custom GIFs/stickers.

POST/api/servers/:id/gifs

Upload a custom GIF/sticker (multipart form data).

DELETE/api/servers/:id/gifs/:gifId

Delete a server GIF/sticker.

POST/api/servers/:id/mute

Mute a server for the current user. Body: {"duration": 3600}

DELETE/api/servers/:id/mute

Unmute a server for the current user.

GET/api/servers/me/muted

Get list of servers muted by the current user.

Channels

GET/api/channels/:serverId

List all channels in a server (grouped by category).

GET/api/channels/id/:channelId

Get a specific channel by its ID.

POST/api/channels/:serverId

Create a new channel. Body: {"name": "general", "type": "text", "category_id": "..."}

PUT/api/channels/:id

Update a channel's name, topic, or slowmode. Body: {"name": "...", "topic": "...", "slowmode": 0}

DELETE/api/channels/:id

Delete a channel.

PUT/api/channels/:serverId/reorder

Reorder channels. Body: [{"id": "...", "position": 0}]

POST/api/channels/:serverId/categories

Create a channel category. Body: {"name": "Voice Channels"}

PUT/api/channels/categories/:id

Rename a category. Body: {"name": "..."}

DELETE/api/channels/categories/:id

Delete a category (channels are uncategorized, not deleted).

GET/api/channels/:channelId/permissions

Get channel permission overrides for all roles.

PUT/api/channels/:channelId/permissions/:roleId

Set channel permission overrides for a role. Body: {"allow": 0, "deny": 0}

DELETE/api/channels/:channelId/permissions/:roleId

Remove channel permission overrides for a role.

Messages

GET/api/messages/:channelId

Fetch messages (50 per page). Use ?before=messageId for older messages.

GET/api/messages/id/:messageId

Get a single message by ID.

POST/api/messages/:channelId/upload

Send a message with optional file attachments (multipart form data). Field: content for text, files for attachments.

DELETE/api/messages/:id

Delete a message. Must be the message author or have manage_messages permission.

GET/api/messages/:channelId/search

Search messages in a channel. Query params: ?q=search+term&limit=25

GET/api/messages/attachment/:attachmentId

Get attachment metadata (filename, size, mime type, url).

POST/api/messages/:channelId/read

Mark channel as read (for unread indicators).

Members & Users

GET/api/users/me/info

Get the current authenticated user/bot. Returns: id, username, email, avatar, banner, bio, status, is_bot, created_at.

GET/api/users/:id

Get a user by ID. Returns: username, avatar, status, banner, bio, is_bot, created_at.

GET/api/users/:id/profile

Get a user's full profile including mutual friends and mutual servers.

PUT/api/users/me/profile

Update the current user's profile. Body: {"username": "...", "bio": "..."} (bio max 500 chars)

POST/api/users/me/avatar

Upload a new avatar (multipart form data, field: avatar).

POST/api/users/me/banner

Upload a new banner (multipart form data, field: banner).

PUT/api/users/me/password

Change password. Body: {"currentPassword": "...", "newPassword": "..."}

PUT/api/servers/:id/members/:targetUserId/role

Change a member's role in a server. Body: {"role": "admin"}

Friends

GET/api/friends

List all friends (accepted friend relationships).

GET/api/friends/search

Search for users to add as friends. Query: ?q=username

POST/api/friends/request

Send a friend request. Body: {"username": "..."}

POST/api/friends/accept/:friendId

Accept a pending friend request.

DELETE/api/friends/:friendId

Remove a friend or reject a pending request.

GET/api/friends/voice-activity

Get which voice channels your friends are currently in.

Direct Messages

GET/api/dm/channels

List all DM channels (recent conversations).

POST/api/dm/channels/:targetUserId

Open or create a DM channel with a user.

GET/api/dm/:targetUserId/messages

Fetch DM messages with a user. Supports ?before=messageId

POST/api/dm/:targetUserId/messages

Send a DM. Body: {"content": "Hello!"}

POST/api/dm/:targetUserId/upload

Send a DM with file attachments (multipart form data).

DELETE/api/dm/:targetUserId/messages/:messageId

Delete a DM message.

POST/api/dm/:targetUserId/read

Mark DM conversation as read.

Roles

GET/api/roles/:serverId

List all roles in a server with permissions, colors, and positions.

GET/api/roles/:serverId/role/:roleId

Get details for a specific role.

POST/api/roles/:serverId

Create a new role. Body: {"name": "Moderator", "color": "#5865F2", "permissions": 0}

PUT/api/roles/:serverId/:roleId

Update role name, color, permissions, or hoist. Body: {"name": "...", "color": "...", "permissions": 0}

DELETE/api/roles/:serverId/:roleId

Delete a role from the server.

PUT/api/roles/:serverId/reorder

Reorder roles. Body: array of {"id": "...", "position": 0}

POST/api/roles/:serverId/assign

Assign a role to a member. Body: {"userId": "...", "roleId": "..."}

DELETE/api/roles/:serverId/assign/:targetUserId/:roleId

Remove a role from a member.

GET/api/roles/:serverId/member/:targetUserId

Get all roles assigned to a specific member.

Reactions & Pins

PUT/api/messages/:channelId/reactions/:messageId

Add a reaction to a message. Body: {"emoji": "πŸ‘"}

DELETE/api/messages/:channelId/reactions/:messageId/:emoji

Remove your reaction from a message.

GET/api/messages/:channelId/reactions/:messageId

Get all reactions on a message with user lists.

GET/api/messages/:channelId/pins

Get all pinned messages in a channel.

POST/api/messages/:channelId/pins/:messageId

Pin a message to a channel.

DELETE/api/messages/:channelId/pins/:messageId

Unpin a message from a channel.

GET/api/dm/:targetUserId/pins

Get pinned messages in a DM conversation.

POST/api/dm/:targetUserId/pins/:messageId

Pin a DM message.

DELETE/api/dm/:targetUserId/pins/:messageId

Unpin a DM message.

Invites

POST/api/servers/:id/invite/regenerate

Regenerate the server invite code. Requires owner/admin.

POST/api/servers/join/:inviteCode

Join a server using an invite code.

GET/api/oauth2/invite/:botUserId

Get public invite info for a bot (name, avatar, description, public_invite status).

POST/api/oauth2/invite/:botUserId/add/:serverId

Add a bot to a server via invite. Checks public_invite — if disabled, only bot owner can invite.

PATCH/api/oauth2/applications/:appId/public-invite

Toggle the public invite setting on your bot. Body: {"public_invite": true}

Stats

GET/api/stats

Get public platform statistics: {"users": 150, "bots": 12, "servers": 45, "messages": 50000}

Full Example: Ping Pong Bot (Python)

A complete, copy-paste-ready bot. Responds to /ping with "Pong!", /echo with the user's message, and /hello with a rich embed.

bash Install Dependencies
pip install "python-socketio[client]" requests
Python ping_bot.py — Complete Working Example
""" ggbro Ping Pong Bot (Python) A complete working example for the ggbro platform. ggbro uses Socket.IO v4 for real-time communication. Install: pip install "python-socketio[client]" requests """ import socketio import requests # --- Configuration --- BOT_TOKEN = "YOUR_BOT_TOKEN" # Get from Developer Portal API_URL = "https://ggbro.jadadev.com" # --- Socket.IO Client --- sio = socketio.Client(reconnection=True, reconnection_delay=1) # --- Helper: Reply to a slash command --- def reply(ctx, content, embeds=None): """Respond to an interaction (slash command).""" payload = { "interaction_id": ctx["id"], "channel_id": ctx["channel_id"], "content": content } if embeds: payload["embeds"] = embeds sio.emit("interaction:response", payload) # --- Helper: Send a message to a channel --- def send_message(channel_id, content, embeds=None): """Send a message to any channel.""" payload = {"channel_id": channel_id, "content": content} if embeds: payload["embeds"] = embeds sio.emit("bot:send_message", payload) # --- Events --- @sio.event def connect(): print("[+] Connected to ggbro!") @sio.event def disconnect(): print("[!] Disconnected from ggbro") # --- Slash Command Handler --- @sio.on("interaction:create") def on_interaction(data): cmd = (data.get("command") or "").lower() args = data.get("args", "") user = data["user"]["username"] print(f"[cmd] /{cmd} from {user}") if cmd == "ping": reply(data, "Pong! πŸ“") elif cmd == "echo": message = data.get("options", {}).get("message") or args if message: reply(data, f"πŸ“’ {message}") else: reply(data, "❌ Please provide a message!") elif cmd == "hello": # Reply with an embed reply(data, "", embeds=[{ "title": f"Hello, {user}!", "description": "Welcome! I'm a bot running on ggbro.", "color": "#23a55a" }]) # --- Register Commands --- def register_commands(): commands = [ {"name": "ping", "description": "Check if the bot is alive", "options": []}, {"name": "echo", "description": "Repeat your message", "options": [ {"name": "message", "description": "Text to echo", "required": True} ]}, {"name": "hello", "description": "Say hello with an embed", "options": []}, ] r = requests.post( f"{API_URL}/api/oauth2/commands", json=commands, headers={"Authorization": f"Bearer {BOT_TOKEN}"} ) if r.ok: print("[+] Commands registered: /ping, /echo, /hello") else: print(f"[!] Failed to register commands: {r.status_code} {r.text}") # --- Main --- if __name__ == "__main__": print("Starting ggbro Ping Bot...") register_commands() sio.connect(API_URL, auth={"token": BOT_TOKEN}) sio.wait()

Full Example: Ping Pong Bot (JavaScript / Node.js)

bash Install Dependencies
npm install socket.io-client axios
JavaScript ping_bot.js — Complete Working Example
/** * ggbro Ping Pong Bot (Node.js) * A complete working example for the ggbro platform. * ggbro uses Socket.IO v4 for real-time communication. * * Install: npm install socket.io-client axios */ const { io } = require("socket.io-client"); const axios = require("axios"); // --- Configuration --- const BOT_TOKEN = "YOUR_BOT_TOKEN"; // Get from Developer Portal const API_URL = "https://ggbro.jadadev.com"; // --- Socket.IO Client --- const socket = io(API_URL, { auth: { token: BOT_TOKEN }, reconnection: true, reconnectionDelay: 1000 }); // --- Helper: Reply to a slash command --- function reply(ctx, content, embeds) { const payload = { interaction_id: ctx.id, channel_id: ctx.channel_id, content }; if (embeds) payload.embeds = embeds; socket.emit("interaction:response", payload); } // --- Helper: Send a message to a channel --- function sendMessage(channelId, content, embeds) { const payload = { channel_id: channelId, content }; if (embeds) payload.embeds = embeds; socket.emit("bot:send_message", payload); } // --- Events --- socket.on("connect", () => console.log("[+] Connected to ggbro!")); socket.on("disconnect", () => console.log("[!] Disconnected")); // --- Slash Command Handler --- socket.on("interaction:create", (data) => { const cmd = (data.command || "").toLowerCase(); const args = data.args || ""; const user = data.user.username; console.log(`[cmd] /${cmd} from ${user}`); if (cmd === "ping") { reply(data, "Pong! πŸ“"); } else if (cmd === "echo") { const message = (data.options && data.options.message) || args; reply(data, message ? `πŸ“’ ${message}` : "❌ Please provide a message!"); } else if (cmd === "hello") { reply(data, "", [{ title: `Hello, ${user}!`, description: "Welcome! I'm a bot running on ggbro.", color: "#23a55a" }]); } }); // --- Register Commands --- async function registerCommands() { try { await axios.post(`${API_URL}/api/oauth2/commands`, [ { name: "ping", description: "Check if the bot is alive", options: [] }, { name: "echo", description: "Repeat your message", options: [ { name: "message", description: "Text to echo", required: true } ]}, { name: "hello", description: "Say hello with an embed", options: [] }, ], { headers: { Authorization: `Bearer ${BOT_TOKEN}` } }); console.log("[+] Commands registered: /ping, /echo, /hello"); } catch (err) { console.error("[!] Failed to register:", err.response?.data || err.message); } } // --- Start --- registerCommands();

Full Example: /serverinfo with Embeds (Python)

A complete bot that responds to /serverinfo with a rich embed containing server name, owner, member count, and creation date:

Python serverinfo_bot.py — Complete Working Example
""" ggbro Server Info Bot Responds to /serverinfo with a rich embed showing server details. Uses Socket.IO for real-time + REST API for data fetching. Install: pip install "python-socketio[client]" requests """ import socketio import requests from datetime import datetime # --- Configuration --- BOT_TOKEN = "YOUR_BOT_TOKEN" API_URL = "https://ggbro.jadadev.com" HEADERS = {"Authorization": f"Bearer {BOT_TOKEN}"} sio = socketio.Client(reconnection=True) def reply(ctx, content="", embeds=None): payload = { "interaction_id": ctx["id"], "channel_id": ctx["channel_id"], "content": content, } if embeds: payload["embeds"] = embeds sio.emit("interaction:response", payload) @sio.event def connect(): print("[+] Connected to ggbro!") @sio.on("interaction:create") def on_interaction(data): cmd = (data.get("command") or "").lower() if cmd == "serverinfo": server_id = data["server_id"] user = data["user"]["username"] # Fetch server details from REST API r = requests.get(f"{API_URL}/api/servers/{server_id}", headers=HEADERS) if not r.ok: reply(data, "❌ Failed to fetch server info") return server = r.json() # Fetch members mr = requests.get(f"{API_URL}/api/servers/{server_id}/members", headers=HEADERS) members = mr.json().get("members", []) if mr.ok else [] # Find the owner owner = next((m for m in members if m.get("role") == "owner"), None) owner_name = owner["username"] if owner else "Unknown" # Build the embed icon_url = f"{API_URL}/uploads/icons/{server['icon']}" if server.get("icon") else None reply(data, "", embeds=[{ "title": server.get("name", "Unknown Server"), "description": server.get("description") or "No description set.", "color": "#5865F2", "thumbnail": icon_url, "fields": [ {"name": "πŸ‘‘ Owner", "value": owner_name, "inline": True}, {"name": "πŸ‘₯ Members", "value": str(len(members)), "inline": True}, {"name": "πŸ†” Server ID", "value": f"`{server_id}`"}, ], "footer": {"text": f"Requested by {user}"}, "timestamp": datetime.utcnow().isoformat(), }]) # --- Register Commands --- def register_commands(): r = requests.post( f"{API_URL}/api/oauth2/commands", json=[{"name": "serverinfo", "description": "Show server details", "options": []}], headers=HEADERS ) print("[+] /serverinfo registered" if r.ok else f"[!] Failed: {r.text}") if __name__ == "__main__": print("Starting Server Info Bot...") register_commands() sio.connect(API_URL, auth={"token": BOT_TOKEN}) sio.wait()

Full Example: Welcome Bot (Python)

Greets new members with a rich embed when they join a server:

Python welcome_bot.py — Complete Working Example
""" ggbro Welcome Bot Greets new members with a rich embed when they join. Install: pip install "python-socketio[client]" requests """ import socketio import requests from datetime import datetime # --- Configuration --- BOT_TOKEN = "YOUR_BOT_TOKEN" API_URL = "https://ggbro.jadadev.com" HEADERS = {"Authorization": f"Bearer {BOT_TOKEN}"} # Set your welcome channel ID per server WELCOME_CHANNELS = { "your-server-id": "your-welcome-channel-id", } sio = socketio.Client(reconnection=True) def send_message(channel_id, content="", embeds=None): payload = {"channel_id": channel_id, "content": content} if embeds: payload["embeds"] = embeds sio.emit("bot:send_message", payload) def reply(ctx, content="", embeds=None): payload = {"interaction_id": ctx["id"], "channel_id": ctx["channel_id"], "content": content} if embeds: payload["embeds"] = embeds sio.emit("interaction:response", payload) @sio.event def connect(): print("[+] Welcome Bot connected!") # Join all configured server rooms for server_id in WELCOME_CHANNELS: sio.emit("server:join", server_id) # --- Welcome new members with an embed --- @sio.on("member:joined") def on_member_join(data): server_id = data.get("serverId") username = data.get("username", "Someone") avatar = data.get("avatar") channel_id = WELCOME_CHANNELS.get(server_id) if not channel_id: return avatar_url = f"{API_URL}/uploads/avatars/{avatar}" if avatar else None send_message(channel_id, "", embeds=[{ "title": f"Welcome, {username}! πŸ‘‹", "description": "We're glad to have you here. Check out the channels and say hi!", "color": "#23a55a", "thumbnail": avatar_url, "timestamp": datetime.utcnow().isoformat(), }]) # --- Slash command to set welcome channel --- @sio.on("interaction:create") def on_interaction(data): cmd = (data.get("command") or "").lower() if cmd == "setwelcome": channel_id = (data.get("options", {}).get("channel_id") or data.get("args", "")).strip() if not channel_id: reply(data, "❌ Please provide a channel ID!") return WELCOME_CHANNELS[data["server_id"]] = channel_id reply(data, "", embeds=[{ "title": "βœ… Welcome Channel Set", "description": f"New members will be greeted in this channel.", "color": "#23a55a" }]) # --- Register Commands --- def register_commands(): r = requests.post( f"{API_URL}/api/oauth2/commands", json=[ {"name": "setwelcome", "description": "Set the welcome channel", "options": [ {"name": "channel_id", "description": "Channel ID for welcome messages", "required": True} ]} ], headers=HEADERS ) print("[+] /setwelcome registered" if r.ok else f"[!] Failed: {r.text}") if __name__ == "__main__": print("Starting Welcome Bot...") register_commands() sio.connect(API_URL, auth={"token": BOT_TOKEN}) sio.wait()