### Install @jubbio/voice Source: https://github.com/jubbio/jubbio.js/blob/main/voice/README.md The command to install the voice library via npm. ```bash npm install @jubbio/voice ``` -------------------------------- ### Install System Dependencies Source: https://github.com/jubbio/jubbio.js/blob/main/voice/README.md Commands to install FFmpeg and yt-dlp on various operating systems to ensure Jubbio.js functions correctly. ```bash # Ubuntu/Debian sudo apt install ffmpeg pip install yt-dlp # macOS brew install ffmpeg yt-dlp ``` -------------------------------- ### Install @jubbio/core Source: https://github.com/jubbio/jubbio.js/blob/main/core/README.md Installs the @jubbio/core package using npm. This is the first step to integrating the Jubbio bot library into your project. ```bash npm install @jubbio/core ``` -------------------------------- ### Implement Music Bot Playback Source: https://github.com/jubbio/jubbio.js/blob/main/voice/README.md A complete example showing how to handle a 'play' command, join a voice channel, and stream audio using @jubbio/voice. ```javascript import { Client, GatewayIntentBits, EmbedBuilder, Colors } from '@jubbio/core'; import { joinVoiceChannel, createAudioPlayer, createAudioResourceFromUrl, probeAudioInfo, getVoiceConnection, AudioPlayerStatus } from '@jubbio/voice'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates ] }); const players = new Map(); function getPlayer(guildId) { let player = players.get(guildId); if (!player) { player = createAudioPlayer(); players.set(guildId, player); } return player; } client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; if (interaction.commandName === 'play') { const url = interaction.options.getString('url', true); const voiceChannel = interaction.member?.voice?.channelId; if (!voiceChannel) { return interaction.reply('❌ Join a voice channel first!'); } await interaction.deferReply(); try { const info = await probeAudioInfo(url); let connection = getVoiceConnection(interaction.guildId); if (!connection) { connection = joinVoiceChannel({ channelId: voiceChannel, guildId: interaction.guildId, adapterCreator: client.voice.adapters.get(interaction.guildId) }); const player = getPlayer(interaction.guildId); connection.subscribe(player); } const player = getPlayer(interaction.guildId); const resource = createAudioResourceFromUrl(info.url); player.play(resource); const minutes = Math.floor(info.duration / 60); const seconds = info.duration % 60; const durationStr = `${minutes}:${seconds.toString().padStart(2, '0')}`; const embed = new EmbedBuilder() .setTitle('đŸŽĩ Now Playing') .setDescription(`**${info.title}**`) .setColor(Colors.Blue) .addFields({ name: 'Duration', value: durationStr, inline: true }) .setTimestamp(); if (info.thumbnail) { embed.setThumbnail(info.thumbnail); } await interaction.editReply({ embeds: [embed] }); } catch (error) { await interaction.editReply(`❌ Error: ${error.message}`); } } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Voice and Audio API Usage Source: https://github.com/jubbio/jubbio.js/blob/main/voice/README.md Examples for joining voice channels, creating audio players, and generating audio resources from files or URLs. ```typescript const connection = joinVoiceChannel({ channelId: '123456789', guildId: '987654321', adapterCreator: adapter, selfMute: false, selfDeaf: false }); const player = createAudioPlayer({ behaviors: { noSubscriber: 'pause' } }); const resource = createAudioResource('/path/to/audio.mp3', { metadata: { title: 'My Song' } }); const urlResource = createAudioResourceFromUrl('https://youtube.com/watch?v=...', { metadata: { title: 'YouTube Video' } }); ``` -------------------------------- ### Install Jubbio.js Packages Source: https://github.com/jubbio/jubbio.js/blob/main/README.md Installs the core Jubbio bot library and the optional voice support package using npm. The core library is required for all bots, while the voice package is needed for audio playback and LiveKit integration. ```bash # Core library (required) npm install @jubbio/core # Voice support (optional) npm install @jubbio/voice ``` -------------------------------- ### Handle 'ready' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides an example of how to listen for and handle the 'ready' event, which is emitted when the Jubbio client has successfully connected and is ready to operate. It logs the bot's username. ```javascript client.on('ready', () => { console.log(`Logged in as ${client.user.username}`); }); ``` -------------------------------- ### Handle User Typing Start in JavaScript Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Listens for the 'typingStart' event, emitted when a user begins typing in a channel. It logs the user ID and channel ID where the typing occurred. Requires a client instance. ```javascript client.on('typingStart', (data) => { console.log(`User ${data.userId} is typing in ${data.channelId}`); }); ``` -------------------------------- ### Implement Sharding for Scalability Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Covers the ShardingManager for spawning multiple bot processes and ShardClientUtil for inter-shard communication. Includes examples for broadcasting events, evaluating code across shards, and managing shard lifecycle events. ```javascript // ShardingManager setup import { ShardingManager } from '@jubbio/core'; const manager = new ShardingManager('./bot.js', { totalShards: 'auto', token: process.env.BOT_TOKEN }); manager.spawn(); // Broadcasting await manager.broadcast({ type: 'reload' }); // ShardClientUtil in bot.js import { ShardClientUtil } from '@jubbio/core'; const shardId = ShardClientUtil.shardIdForGuildId(guildId, totalShards); const allGuilds = await client.shard.fetchClientValues('guilds.size'); ``` -------------------------------- ### Probe Audio Metadata with Jubbio.js Source: https://github.com/jubbio/jubbio.js/blob/main/voice/README.md Retrieves metadata such as title, duration, and thumbnail from a given audio URL. Requires yt-dlp to be installed on the system. ```typescript const info = await probeAudioInfo('https://youtube.com/watch?v=...'); console.log(info.title); console.log(info.duration); console.log(info.thumbnail); ``` -------------------------------- ### Create a Basic Jubbio Bot Source: https://github.com/jubbio/jubbio.js/blob/main/README.md A basic Jubbio bot example using TypeScript. It connects to Jubbio, logs when online, and responds to text messages and slash commands. Requires the `@jubbio/core` package. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ] }); client.on('ready', () => { console.log(`✅ ${client.user?.username} is online!`); }); client.on('messageCreate', async (message) => { if (message.content === '!ping') { await message.reply('🏓 Pong!'); } }); client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; if (interaction.commandName === 'hello') { await interaction.reply('Hello! 👋'); } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Control Audio Playback with Jubbio Player Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides examples of controlling an `AudioPlayer` instance: playing, pausing, resuming, and stopping audio playback. It also shows how to check the current status of the player. ```javascript // Play player.play(resource); // Pause player.pause(); // Resume player.unpause(); // Stop player.stop(); // Check status player.state.status === AudioPlayerStatus.Playing player.state.status === AudioPlayerStatus.Idle player.state.status === AudioPlayerStatus.Paused player.state.status === AudioPlayerStatus.Buffering ``` -------------------------------- ### Define Jubbio Slash Command Source: https://github.com/jubbio/jubbio.js/blob/main/core/README.md Example of defining a slash command using SlashCommandBuilder. This allows for creating commands with descriptions and user options, making interactions more structured. Requires importing SlashCommandBuilder. ```typescript import { SlashCommandBuilder } from '@jubbio/core'; const command = new SlashCommandBuilder() .setName('greet') .setDescription('Greet a user') .addUserOption(option => option.setName('user') .setDescription('User to greet') .setRequired(true) ); ``` -------------------------------- ### Complete Music Bot Example with Jubbio.js Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md This JavaScript code implements a full-featured music bot for Discord. It handles commands like 'play', 'skip', 'stop', and 'queue'. The bot joins voice channels, plays audio from URLs, manages a song queue, and provides feedback to users via embeds. Dependencies include '@jubbio/core' and '@jubbio/voice'. ```javascript import { Client, GatewayIntentBits, EmbedBuilder, Colors } from '@jubbio/core'; import { joinVoiceChannel, getVoiceConnection, createAudioPlayer, createAudioResourceFromUrl, probeAudioInfo, AudioPlayerStatus } from '@jubbio/voice'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates ] }); // Store players and queues per guild const players = new Map(); const queues = new Map(); function getPlayer(guildId) { let player = players.get(guildId); if (!player) { player = createAudioPlayer(); players.set(guildId, player); // Auto-play next song when current ends player.on('stateChange', (oldState, newState) => { if (newState.status === AudioPlayerStatus.Idle && oldState.status !== AudioPlayerStatus.Idle) { playNext(guildId); } }); } return player; } async function playNext(guildId) { const queue = queues.get(guildId) || []; if (queue.length === 0) return; const song = queue.shift(); queues.set(guildId, queue); const resource = createAudioResourceFromUrl(song.url); const player = getPlayer(guildId); player.play(resource); } client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; const { commandName, guildId } = interaction; if (commandName === 'play') { const query = interaction.options.getString('query', true); const voiceChannel = interaction.member?.voice?.channelId; if (!voiceChannel) { return interaction.reply({ content: '❌ Join a voice channel first!', ephemeral: true }); } await interaction.deferReply(); try { const info = await probeAudioInfo(query); // Join if not connected let connection = getVoiceConnection(guildId); if (!connection) { connection = joinVoiceChannel({ channelId: voiceChannel, guildId: guildId, adapterCreator: client.voice.adapters.get(guildId) }); connection.subscribe(getPlayer(guildId)); } // Add to queue const queue = queues.get(guildId) || []; queue.push({ url: info.url, title: info.title, duration: info.duration }); queues.set(guildId, queue); // Start playing if idle const player = getPlayer(guildId); if (player.state.status === AudioPlayerStatus.Idle) { playNext(guildId); } const embed = new EmbedBuilder() .setTitle('đŸŽĩ Added to Queue') .setDescription(`**${info.title}**`) .setColor(Colors.Green) .setThumbnail(info.thumbnail) .setTimestamp(); await interaction.editReply({ embeds: [embed] }); } catch (error) { await interaction.editReply(`❌ Error: ${error.message}`); } } if (commandName === 'skip') { const player = getPlayer(guildId); player.stop(); // Triggers stateChange -> playNext await interaction.reply('â­ī¸ Skipped!'); } if (commandName === 'stop') { const player = getPlayer(guildId); player.stop(); queues.set(guildId, []); getVoiceConnection(guildId)?.disconnect(); await interaction.reply('âšī¸ Stopped!'); } if (commandName === 'queue') { const queue = queues.get(guildId) || []; if (queue.length === 0) { return interaction.reply('📭 Queue is empty!'); } const list = queue.slice(0, 10).map((s, i) => `${i + 1}. ${s.title}`).join('\n'); await interaction.reply(`đŸŽĩ **Queue:**\n${list}`); } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Handle 'channelCreate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to handle the 'channelCreate' event, which fires when a new channel is created in a guild the bot has access to. The example logs the name of the newly created channel. ```javascript client.on('channelCreate', (channel) => { console.log(`Channel created: ${channel.name}`); }); ``` -------------------------------- ### Handle 'messageCreate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Demonstrates how to handle the 'messageCreate' event, triggered whenever a new message is sent. This example logs the message content and replies to a '!ping' command. ```javascript client.on('messageCreate', async (message) => { // message: Message console.log(`${message.author.username}: ${message.content}`); if (message.content === '!ping') { await message.reply('Pong!'); } }); ``` -------------------------------- ### Handle 'guildCreate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to handle the 'guildCreate' event, emitted when the bot joins a new server (guild). The example logs the name of the newly joined guild. ```javascript client.on('guildCreate', (guild) => { console.log(`Joined guild: ${guild.name}`); }); ``` -------------------------------- ### Handle Jubbio.js Message Events and Commands Source: https://context7.com/jubbio/jubbio.js/llms.txt Sets up event listeners for 'messageCreate', 'messageUpdate', 'messageDelete', and 'messageDeleteBulk' to process incoming messages, respond to commands, and manage message lifecycle events. It includes examples for replying with text, embeds, deleting messages, and adding reactions. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent ] }); client.on('messageCreate', async (message) => { // Ignore bot messages if (message.author.bot) return; // Log message info console.log(`[${message.guildId}] ${message.author.username}: ${message.content}`); // Simple ping command if (message.content === '!ping') { await message.reply('Pong!'); } // Reply with embed if (message.content === '!info') { await message.reply({ content: 'Here is some info:', embeds: [{ title: 'Bot Information', description: 'This is an example embed', color: 0x3498db }] }); } // Delete a message if (message.content === '!delete') { await message.delete(); } // Add reaction if (message.content.includes('hello')) { await message.react(':wave:'); } }); // Handle message edits client.on('messageUpdate', (oldMessage, newMessage) => { console.log(`Message edited in ${newMessage.channelId}`); }); // Handle message deletions client.on('messageDelete', (message) => { console.log(`Message ${message.id} was deleted`); }); // Handle bulk deletions client.on('messageDeleteBulk', (messages) => { console.log(`${messages.length} messages were deleted`); }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Handle 'interactionCreate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Illustrates handling the 'interactionCreate' event, which is triggered by various user interactions like slash commands, button clicks, and select menus. The example includes placeholders for different interaction types. ```javascript client.on('interactionCreate', async (interaction) => { if (interaction.isCommand()) { // Handle slash command } else if (interaction.isButton()) { // Handle button click } else if (interaction.isSelectMenu()) { // Handle select menu } else if (interaction.isModalSubmit()) { // Handle modal submit } }); ``` -------------------------------- ### Handle Autocomplete Interaction Options and Respond Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to get the currently focused option in an autocomplete interaction using `getFocused` and how to respond with a list of choices. The `respond` method expects an array of choice objects. ```javascript const focused = interaction.options.getFocused(); // { name: 'query', value: 'user input' } await interaction.respond([ { name: 'Option 1', value: 'opt1' }, { name: 'Option 2', value: 'opt2' }, { name: 'Option 3', value: 'opt3' } ]); ``` -------------------------------- ### Create a Music Bot with Jubbio.js Source: https://github.com/jubbio/jubbio.js/blob/main/README.md A music bot example using JavaScript that leverages both `@jubbio/core` and `@jubbio/voice` packages. It allows users to play audio from URLs in voice channels, handling connections and audio playback. ```javascript import { Client, GatewayIntentBits, EmbedBuilder, Colors } from '@jubbio/core'; import { joinVoiceChannel, createAudioPlayer, createAudioResourceFromUrl, probeAudioInfo, getVoiceConnection, AudioPlayerStatus } from '@jubbio/voice'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates ] }); // Store players per guild const players = new Map(); function getPlayer(guildId) { let player = players.get(guildId); if (!player) { player = createAudioPlayer(); players.set(guildId, player); } return player; } client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; if (interaction.commandName === 'play') { const url = interaction.options.getString('url', true); const voiceChannel = interaction.member?.voice?.channelId; if (!voiceChannel) { return interaction.reply('❌ Join a voice channel first!'); } await interaction.deferReply(); try { const info = await probeAudioInfo(url); // Check for existing connection, only join if not connected let connection = getVoiceConnection(interaction.guildId); if (!connection) { connection = joinVoiceChannel({ channelId: voiceChannel, guildId: interaction.guildId, adapterCreator: client.voice.adapters.get(interaction.guildId) }); const player = getPlayer(interaction.guildId); connection.subscribe(player); } const player = getPlayer(interaction.guildId); const resource = createAudioResourceFromUrl(info.url); player.play(resource); const minutes = Math.floor(info.duration / 60); const seconds = info.duration % 60; const durationStr = `${minutes}:${seconds.toString().padStart(2, '0')}`; const embed = new EmbedBuilder() .setTitle('đŸŽĩ Now Playing') .setDescription(`**${info.title}**`) .setColor(Colors.Blue) .addFields({ name: 'Duration', value: durationStr, inline: true }) .setTimestamp(); if (info.thumbnail) { embed.setThumbnail(info.thumbnail); } await interaction.editReply({ embeds: [embed] }); } catch (error) { await interaction.editReply(`❌ Error: ${error.message}`); } } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Initialize Jubbio Client and Intents Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Sets up the Jubbio client with necessary intents for guild and voice state management. This is the initial step before interacting with voice channels. ```javascript import { Client, GatewayIntentBits } from '@jubbio/core'; import { joinVoiceChannel, getVoiceConnection, createAudioPlayer, createAudioResource, createAudioResourceFromUrl, probeAudioInfo, AudioPlayerStatus, VoiceConnectionStatus } from '@jubbio/voice'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates ] }); ``` -------------------------------- ### Initialize Jubbio.js Client and Handle Events Source: https://context7.com/jubbio/jubbio.js/llms.txt Initializes the Jubbio.js Client, sets up gateway intents, logs in using a bot token, and handles 'ready' and 'error' events. It also demonstrates accessing cached guild and channel data. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers ], // Optional: Custom gateway/API URLs // gatewayUrl: 'wss://custom-gateway.example.com/ws/bot', // apiUrl: 'https://custom-api.example.com/api/v1' }); client.on('ready', () => { console.log(`Logged in as ${client.user?.username}`); console.log(`Bot is in ${client.guilds.size} guilds`); }); client.on('error', (error) => { console.error('Client error:', error); }); // Connect to gateway await client.login(process.env.BOT_TOKEN); // Access cached data console.log('Guilds:', client.guilds.map(g => g.name)); console.log('Channels:', client.channels.size); // Cleanup when done // client.destroy(); ``` -------------------------------- ### Create Jubbio Client with Intents (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Demonstrates how to create a new Jubbio client instance and specify the necessary gateway intents for receiving events. This is a fundamental step for bot initialization. ```javascript import { Client, GatewayIntentBits } from '@jubbio/core'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildVoiceStates, GatewayIntentBits.GuildMembers ] }); ``` -------------------------------- ### Handle 'messageDelete' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides an example for handling the 'messageDelete' event, triggered when a message is deleted. The code logs the ID of the deleted message. ```javascript client.on('messageDelete', (message) => { console.log(`Message deleted: ${message.id}`); }); ``` -------------------------------- ### Handle 'guildMemberRemove' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Demonstrates handling the 'guildMemberRemove' event, emitted when a member leaves or is removed from a guild. The example logs the username of the departing member. ```javascript client.on('guildMemberRemove', (member) => { console.log(`${member.user.username} left`); }); ``` -------------------------------- ### Initialize Jubbio Client with Options Source: https://github.com/jubbio/jubbio.js/blob/main/README.md Demonstrates how to initialize the Jubbio Client with various configuration options, including gateway intents, shard configuration, and custom gateway/API URLs. This is essential for setting up your bot's connection and behavior. ```typescript const client = new Client({ intents: [...], // Required gateway intents shards: [0, 1], // Optional: [shard_id, total_shards] gatewayUrl: 'ws://...', // Optional: Custom gateway URL apiUrl: 'http://...' // Optional: Custom API URL }); ``` -------------------------------- ### Handle 'messageDeleteBulk' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Demonstrates how to handle the 'messageDeleteBulk' event, which is emitted when multiple messages are deleted simultaneously. The example logs the count of deleted messages. ```javascript client.on('messageDeleteBulk', (messages) => { console.log(`${messages.length} messages deleted`); }); ``` -------------------------------- ### Handle 'messageUpdate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to handle the 'messageUpdate' event, which is emitted when an existing message is edited. The example logs the new content of the edited message. ```javascript client.on('messageUpdate', (oldMessage, newMessage) => { console.log(`Message edited: ${newMessage.content}`); }); ``` -------------------------------- ### Create and Subscribe Audio Player in Jubbio Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Explains how to create an `AudioPlayer` instance, configure its behavior when no subscribers are present (e.g., 'pause'), and subscribe an existing voice connection to this player. ```javascript const player = createAudioPlayer({ behaviors: { noSubscriber: 'pause' // 'pause' | 'play' | 'stop' } }); // Subscribe connection to player connection.subscribe(player); ``` -------------------------------- ### Collect Messages and Interactions Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides examples for event-based collection using MessageCollector and InteractionCollector, as well as a promise-based approach with awaitMessages. These utilities allow for filtering and time-limited data collection. ```javascript import { MessageCollector, awaitMessages, InteractionCollector } from '@jubbio/core'; // MessageCollector const collector = new MessageCollector(client, channelId, { filter: (message) => message.author.id === userId, max: 5, time: 30000, idle: 10000 }); // awaitMessages const collected = await awaitMessages(client, channelId, { filter: (m) => m.author.id === userId, max: 1, time: 30000, errors: ['time'] }); // InteractionCollector const intCollector = new InteractionCollector(client, { filter: (i) => i.user.id === userId, componentType: 2, max: 1, time: 60000 }); ``` -------------------------------- ### Configure Gateway Intents for Jubbio Client Source: https://context7.com/jubbio/jubbio.js/llms.txt This snippet demonstrates how to initialize a Jubbio client with specific gateway intents. It includes both standard and privileged intents, which may require additional approval for production use. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildVoiceStates ] }); ``` -------------------------------- ### Handle 'channelUpdate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides an example for handling the 'channelUpdate' event, triggered when a channel's settings are modified. The code logs the updated name of the channel. ```javascript client.on('channelUpdate', (oldChannel, newChannel) => { console.log(`Channel updated: ${newChannel.name}`); }); ``` -------------------------------- ### Handle 'guildDelete' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Demonstrates handling the 'guildDelete' event, emitted when the bot is removed from or leaves a guild. The example logs the ID of the guild the bot left. ```javascript client.on('guildDelete', (guild) => { console.log(`Left guild: ${guild.id}`); }); ``` -------------------------------- ### Implement Audio Player with TypeScript Source: https://context7.com/jubbio/jubbio.js/llms.txt Shows how to create an audio player to stream content from URLs. It manages player instances per guild and provides controls for play, pause, resume, and stop operations. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; import { joinVoiceChannel, getVoiceConnection, createAudioPlayer, createAudioResource, createAudioResourceFromUrl, AudioPlayerStatus } from '@jubbio/voice'; const client = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates] }); const players = new Map(); function getPlayer(guildId) { if (!players.has(guildId)) { const player = createAudioPlayer({ behaviors: { noSubscriber: 'pause' } }); player.on('stateChange', (oldState, newState) => { console.log(`Player: ${oldState.status} -> ${newState.status}`); }); player.on('error', (error) => { console.error('Player error:', error.message); }); players.set(guildId, player); } return players.get(guildId); } client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; const { commandName, guildId } = interaction; if (commandName === 'play') { const url = interaction.options.getString('url', true); const voiceChannel = interaction.member?.voice?.channelId; if (!voiceChannel) { return interaction.reply({ content: 'Join a voice channel first!', ephemeral: true }); } await interaction.deferReply(); let connection = getVoiceConnection(guildId); if (!connection) { connection = joinVoiceChannel({ channelId: voiceChannel, guildId: guildId, adapterCreator: client.voice.adapters.get(guildId) }); } const player = getPlayer(guildId); connection.subscribe(player); const resource = createAudioResourceFromUrl(url, { metadata: { title: 'My Track' } }); player.play(resource); await interaction.editReply(`Now playing: ${url}`); } if (commandName === 'pause') { const player = getPlayer(guildId); if (player.pause()) { await interaction.reply('Paused!'); } else { await interaction.reply({ content: 'Nothing playing', ephemeral: true }); } } if (commandName === 'resume') { const player = getPlayer(guildId); if (player.unpause()) { await interaction.reply('Resumed!'); } else { await interaction.reply({ content: 'Not paused', ephemeral: true }); } } if (commandName === 'stop') { const player = getPlayer(guildId); player.stop(); await interaction.reply('Stopped!'); } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Handle 'guildUpdate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides an example for handling the 'guildUpdate' event, which is triggered when a guild's settings are modified. The code logs the updated name of the guild. ```javascript client.on('guildUpdate', (oldGuild, newGuild) => { console.log(`Guild updated: ${newGuild.name}`); }); ``` -------------------------------- ### Handle Interactions with interactionCreate in Jubbio.js Source: https://context7.com/jubbio/jubbio.js/llms.txt Demonstrates how to listen for interactionCreate events to process slash commands, button clicks, select menus, modal submissions, and autocomplete suggestions. It utilizes type guards to differentiate interaction types and provides methods for replying, deferring, and updating messages. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; const client = new Client({ intents: [GatewayIntentBits.Guilds] }); client.on('interactionCreate', async (interaction) => { if (interaction.isCommand()) { const { commandName } = interaction; if (commandName === 'ping') { await interaction.reply('Pong!'); } if (commandName === 'greet') { const user = interaction.options.getUser('user'); const message = interaction.options.getString('message') || 'Hello'; await interaction.reply(`${message}, <@${user}>!`); } if (commandName === 'info') { await interaction.reply({ content: 'This is only visible to you', ephemeral: true }); } if (commandName === 'process') { await interaction.deferReply(); await new Promise(r => setTimeout(r, 2000)); await interaction.editReply('Processing complete!'); } if (commandName === 'followup') { await interaction.reply('First response'); await interaction.followUp('Follow-up message'); await interaction.followUp({ content: 'Secret follow-up', ephemeral: true }); } } if (interaction.isButton()) { if (interaction.customId === 'confirm') { await interaction.update({ content: 'Confirmed!', components: [] }); } if (interaction.customId === 'cancel') { await interaction.reply({ content: 'Cancelled', ephemeral: true }); } } if (interaction.isSelectMenu()) { const selected = interaction.values.join(', '); await interaction.update({ content: `You selected: ${selected}` }); } if (interaction.isModalSubmit()) { const title = interaction.fields.getTextInputValue('title'); const description = interaction.fields.getTextInputValue('description'); await interaction.reply(`Received: ${title} - ${description}`); } if (interaction.isAutocomplete()) { const focused = interaction.options.getFocused(); const choices = ['apple', 'banana', 'cherry'] .filter(c => c.startsWith(focused.value)) .map(c => ({ name: c, value: c })); await interaction.respond(choices); } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Handle 'guildMemberAdd' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to handle the 'guildMemberAdd' event, which fires when a new user joins a guild the bot is in. The example logs the username of the new member and the guild name. ```javascript client.on('guildMemberAdd', (member) => { console.log(`${member.user.username} joined ${member.guild.name}`); }); ``` -------------------------------- ### Create Audio Resource from File Path in Jubbio Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to create an audio resource from a local file path using `createAudioResource`. This allows playing audio files stored on the server. Metadata can be attached to the resource. ```javascript const resource = createAudioResource('/path/to/audio.mp3', { metadata: { title: 'My Song' } }); player.play(resource); ``` -------------------------------- ### Create and Handle Discord Buttons with ButtonBuilder (TypeScript) Source: https://context7.com/jubbio/jubbio.js/llms.txt Demonstrates how to create various types of buttons (primary, secondary, success, danger, link, disabled) using ButtonBuilder. It also shows how to group them into ActionRows and handle button click interactions. ```typescript import { ButtonBuilder, ButtonStyle, ActionRowBuilder } from '@jubbio/core'; // Primary button const confirmButton = new ButtonBuilder() .setCustomId('confirm') .setLabel('Confirm') .setStyle(ButtonStyle.Primary) .setEmoji(':white_check_mark:'); // Secondary button const cancelButton = new ButtonBuilder() .setCustomId('cancel') .setLabel('Cancel') .setStyle(ButtonStyle.Secondary); // Success button const successButton = new ButtonBuilder() .setCustomId('approve') .setLabel('Approve') .setStyle(ButtonStyle.Success); // Danger button const deleteButton = new ButtonBuilder() .setCustomId('delete') .setLabel('Delete') .setStyle(ButtonStyle.Danger); // Link button (no customId needed) const linkButton = new ButtonBuilder() .setLabel('Visit Website') .setStyle(ButtonStyle.Link) .setURL('https://jubbio.com'); // Disabled button const disabledButton = new ButtonBuilder() .setCustomId('disabled') .setLabel('Unavailable') .setStyle(ButtonStyle.Secondary) .setDisabled(true); // Create action row with buttons (max 5 per row) const row = new ActionRowBuilder() .addComponents(confirmButton, cancelButton, linkButton); const row2 = new ActionRowBuilder() .addComponents(successButton, deleteButton, disabledButton); // Send message with buttons (max 5 rows) await interaction.reply({ content: 'Please choose an action:', components: [row, row2] }); // Handle button click client.on('interactionCreate', async (interaction) => { if (!interaction.isButton()) return; if (interaction.customId === 'confirm') { await interaction.update({ content: 'Action confirmed!', components: [] // Remove buttons }); } }); ``` -------------------------------- ### Handle 'guildMemberUpdate' Event in Jubbio (JavaScript) Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Provides an example for handling the 'guildMemberUpdate' event, triggered when a member's information (like roles or nickname) changes within a guild. It logs the updated username. ```javascript client.on('guildMemberUpdate', (oldMember, newMember) => { console.log(`Member updated: ${newMember.user.username}`); }); ``` -------------------------------- ### Probe and Play Audio with @jubbio/voice Source: https://context7.com/jubbio/jubbio.js/llms.txt Demonstrates how to retrieve audio metadata using probeAudioInfo and stream audio using createAudioResourceFromUrl. This implementation covers direct URL fetching, search queries, and integration within a Discord.js command interaction. ```typescript import { probeAudioInfo, createAudioResourceFromUrl } from '@jubbio/voice'; // Get info from YouTube URL const info = await probeAudioInfo('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); console.log('Title:', info.title); console.log('Duration:', info.duration, 'seconds'); console.log('Thumbnail:', info.thumbnail); console.log('URL:', info.url); // Search YouTube by query const searchResult = await probeAudioInfo('never gonna give you up'); console.log('Found:', searchResult.title); // Use in a music bot client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; if (interaction.commandName === 'play') { const query = interaction.options.getString('query', true); await interaction.deferReply(); try { const info = await probeAudioInfo(query); const minutes = Math.floor(info.duration / 60); const seconds = info.duration % 60; const embed = new EmbedBuilder() .setTitle('Now Playing') .setDescription(`**${info.title}**`) .addFields({ name: 'Duration', value: `${minutes}:${seconds.toString().padStart(2, '0')}` }) .setThumbnail(info.thumbnail) .setColor(Colors.Blue); // Play the audio const resource = createAudioResourceFromUrl(info.url); player.play(resource); await interaction.editReply({ embeds: [embed] }); } catch (error) { await interaction.editReply(`Error: ${error.message}`); } } }); ``` -------------------------------- ### Handle Audio and Connection Events Source: https://github.com/jubbio/jubbio.js/blob/main/voice/README.md Demonstrates how to listen for state changes and error events on both the AudioPlayer and VoiceConnection instances. ```typescript player.on('stateChange', (oldState, newState) => { console.log(`${oldState.status} -> ${newState.status}`); }); player.on('error', (error) => { console.error('Player error:', error); }); connection.on('stateChange', (oldState, newState) => { if (newState.status === VoiceConnectionStatus.Disconnected) { console.log('Disconnected from voice channel'); } }); connection.on('error', (error) => { console.error('Connection error:', error); }); ``` -------------------------------- ### Create Audio Resource from URL in Jubbio Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Demonstrates creating an audio resource from a URL, such as from YouTube. The `createAudioResourceFromUrl` function handles fetching and preparing the audio stream for playback. ```javascript const resource = createAudioResourceFromUrl('https://youtube.com/watch?v=...', { metadata: { title: 'YouTube Video' } }); player.play(resource); ``` -------------------------------- ### Connect to Voice Channels with TypeScript Source: https://context7.com/jubbio/jubbio.js/llms.txt Demonstrates how to join and leave voice channels using the @jubbio/voice package. It includes handling connection state changes and error events within a Discord-like interaction flow. ```typescript import { Client, GatewayIntentBits } from '@jubbio/core'; import { joinVoiceChannel, getVoiceConnection, VoiceConnectionStatus } from '@jubbio/voice'; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildVoiceStates ] }); client.on('interactionCreate', async (interaction) => { if (!interaction.isCommand()) return; if (interaction.commandName === 'join') { const voiceChannelId = interaction.member?.voice?.channelId; if (!voiceChannelId) { return interaction.reply({ content: 'Join a voice channel first!', ephemeral: true }); } const connection = joinVoiceChannel({ channelId: voiceChannelId, guildId: interaction.guildId, adapterCreator: client.voice.adapters.get(interaction.guildId), selfMute: false, selfDeaf: false }); connection.on('stateChange', (oldState, newState) => { console.log(`Connection: ${oldState.status} -> ${newState.status}`); if (newState.status === VoiceConnectionStatus.Ready) { console.log('Connected to voice channel!'); } if (newState.status === VoiceConnectionStatus.Disconnected) { console.log('Disconnected from voice channel'); } }); connection.on('error', (error) => { console.error('Voice connection error:', error); }); await interaction.reply('Joined voice channel!'); } if (interaction.commandName === 'leave') { const connection = getVoiceConnection(interaction.guildId); if (connection) { connection.disconnect(); await interaction.reply('Left voice channel!'); } else { await interaction.reply({ content: 'Not in a voice channel!', ephemeral: true }); } } }); client.login(process.env.BOT_TOKEN); ``` -------------------------------- ### Get Existing Voice Connection in Jubbio Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Retrieves an existing voice connection for a given guild ID. If no connection exists, it falls back to joining a new voice channel. This is useful for re-establishing or checking current connections. ```javascript let connection = getVoiceConnection(guildId); if (!connection) { connection = joinVoiceChannel({ ... }); } ``` -------------------------------- ### Manage Roles and Channels with TypeScript Source: https://context7.com/jubbio/jubbio.js/llms.txt Demonstrates how to create, edit, and delete guild roles and channels. Includes support for permission overrides and channel types. ```typescript const { rest } = client; // Get all roles const roles = await rest.getRoles(guildId); // Create a role const newRole = await rest.createRole(guildId, { name: 'Moderator', color: 0x3498db, hoist: true, // Show separately in member list mentionable: true, permissions: '8' // Permission bits as string }); // Edit a role await rest.editRole(guildId, roleId, { name: 'Senior Moderator', color: 0xe74c3c }); // Delete a role await rest.deleteRole(guildId, roleId); // Get all channels const channels = await rest.getGuildChannels(guildId); // Create text channel const textChannel = await rest.createChannel(guildId, { name: 'general-chat', type: 0, // 0 = text channel category_id: categoryId }); // Create voice channel const voiceChannel = await rest.createChannel(guildId, { name: 'Music Room', type: 2 // 2 = voice channel }); // Create category const category = await rest.createChannel(guildId, { name: 'Gaming', type: 4 // 4 = category }); // Create channel with permission overwrites const privateChannel = await rest.createChannel(guildId, { name: 'staff-only', type: 0, permission_overwrites: [ { id: everyoneRoleId, type: 0, // 0 = role deny: '1024' // VIEW_CHANNEL }, { id: staffRoleId, type: 0, allow: '1024' } ] }); // Delete channel await rest.deleteChannel(guildId, channelId); // Edit channel permissions await rest.editChannelPermissions(channelId, roleId, { type: 0, allow: '3072', // VIEW_CHANNEL + SEND_MESSAGES deny: '0' }); ``` -------------------------------- ### Manage Invites and Webhooks with TypeScript Source: https://context7.com/jubbio/jubbio.js/llms.txt Covers the lifecycle management of server invites and webhooks. Allows for creation, retrieval, and deletion of these integration resources. ```typescript const { rest } = client; // Get guild invites const invites = await rest.getGuildInvites(guildId); // Create invite const invite = await rest.createInvite(guildId, channelId, { max_age: 86400, // 24 hours (0 = never expire) max_uses: 10, // 0 = unlimited temporary: false, // Kick when disconnected unique: true // Create new invite }); console.log(`Invite code: ${invite.code}`); // Get invite info const inviteInfo = await rest.getInvite('invite-code'); // Delete invite await rest.deleteInvite('invite-code'); // Get channel webhooks const webhooks = await rest.getChannelWebhooks(guildId, channelId); // Get all guild webhooks const allWebhooks = await rest.getGuildWebhooks(guildId); // Create webhook const webhook = await rest.createWebhook(guildId, channelId, { name: 'GitHub Notifications', avatar: 'base64-encoded-image' // Optional }); // Update webhook await rest.updateWebhook(guildId, webhookId, { name: 'Updated Name', avatar_url: 'https://example.com/avatar.png' }); // Delete webhook await rest.deleteWebhook(guildId, webhookId); ``` -------------------------------- ### Build Dropdown Select Menus with StringSelectMenuBuilder Source: https://github.com/jubbio/jubbio.js/blob/main/docs/API.md Shows how to create dropdown select menus using `StringSelectMenuBuilder`. This includes setting a custom ID, placeholder text, minimum and maximum selectable options, and adding individual options with labels, values, descriptions, and default status. ```javascript import { StringSelectMenuBuilder, ActionRowBuilder } from '@jubbio/core'; const select = new StringSelectMenuBuilder() .setCustomId('my-select') .setPlaceholder('Choose an option') .setMinValues(1) // Minimum selections .setMaxValues(3) // Maximum selections .addOptions( { label: 'Option 1', value: 'opt1', description: 'First option', emoji: '1ī¸âƒŖ' }, { label: 'Option 2', value: 'opt2', description: 'Second option', emoji: '2ī¸âƒŖ' }, { label: 'Option 3', value: 'opt3', description: 'Third option', default: true } ); const row = new ActionRowBuilder().addComponents(select); await interaction.reply({ content: 'Select options:', components: [row] }); ```