Skip to content

Latest commit

 

History

History
869 lines (731 loc) · 40.3 KB

File metadata and controls

869 lines (731 loc) · 40.3 KB

@persian-caesar/discord-player

یک پخش‌کننده موسیقی سبک و ایمن برای بات‌های دیسکورد، ساخته‌شده با TypeScript و یکپارچه با discord.js. این بسته یک کلاس قدرتمند MusicPlayer برای پخش صوت از پلتفرم‌هایی مانند یوتیوب، ساندکلاد، اسپاتیفای و دیزر ارائه می‌دهد، با پشتیبانی اختیاری از Lavalink از طریق Erela.js برای عملکرد بهتر و مدیریت لیست پخش. بدون Lavalink، پخش مستقیم با استفاده از کتابخانه‌هایی مانند play-dl، soundcloud-downloader و yt-dlp-exec انجام می‌شود.

فهرست مطالب

مقدمه

@persian-caesar/discord-player برای ساده‌سازی پخش صوت در بات‌های دیسکورد طراحی شده است. این بسته از کتابخانه @discordjs/voice برای تعامل با کانال‌های صوتی استفاده می‌کند و از پخش از چندین پلتفرم پشتیبانی می‌کند. ادغام اختیاری با Lavalink (از طریق Erela.js) برای مقیاس‌پذیری بهتر، پشتیبانی از لیست پخش و عملکرد بهبودیافته ارائه می‌شود. بدون Lavalink، پخش‌کننده از پخش مستقیم برای انعطاف‌پذیری در تنظیمات کوچک‌تر استفاده می‌کند. این بسته کاملاً تایپ‌شده است و برای پروژه‌های TypeScript ایده‌آل است، همچنین شامل حاشیه‌نویسی‌های JSDoc برای کاربران JavaScript می‌باشد. کلاس MusicPlayer تمام جنبه‌های پخش موسیقی، از جمله جستجوی چندپلتفرمی، مدیریت صف، ردیابی تاریخچه و اعلان‌های مبتنی بر رویداد را مدیریت می‌کند.

این بسته توسط Sobhan-SRZA برای Persian Caesar توسعه یافته و تحت مجوز MIT منتشر شده و به‌صورت فعال نگهداری می‌شود.

ویژگی‌ها

  • پشتیبانی اختیاری از Lavalink: استفاده از Erela.js برای ویژگی‌های پیشرفته مانند بارگذاری لیست پخش و مدیریت بهتر صوت، یا بازگشت به پخش مستقیم بدون آن.
  • جستجو و پخش چندپلتفرمی: پشتیبانی از یوتیوب، ساندکلاد، اسپاتیفای و دیزر. جستجو به ترتیب اولویت پلتفرم‌ها (قابل تنظیم) انجام شده و لیستی از نتایج را برمی‌گرداند.
  • مدیریت پخش مستقیم: پخش مستقیم URLهای غیرپلتفرمی (مانند ایستگاه‌های رادیویی) بدون نیاز به جستجو.
  • پشتیبانی از لیست پخش: تشخیص، جستجو و بارگذاری لیست‌های پخش از تمام پلتفرم‌های پشتیبانی‌شده، افزودن خودکار آهنگ‌ها به صف.
  • مدیریت صف: افزودن آهنگ‌ها (تکی یا چندگانه)، به‌هم‌ریختن صف یا بازگشت به ترتیب اصلی.
  • گزینه‌های حلقه: فعال/غیرفعال کردن حلقه برای یک آهنگ یا کل صف.
  • کنترل صدا: تنظیم بلندی صدا (0–200٪).
  • دریافت متن آهنگ: بازیابی متن آهنگ از نتایج جستجوی گوگل با استفاده از html-to-text.
  • حالت رادیو: پخش لیست URLهای به‌هم‌ریخته در یک حلقه پیوسته.
  • سیستم رویدادها: رویدادهای تایپ‌شده قوی برای وضعیت پخش، تغییرات صف، خطاها و غیره.
  • قطع خودکار: گزینه‌های قابل تنظیم برای خروج از کانال‌های صوتی در صورت خالی بودن صف یا پس از زمان بی‌فعالی.
  • ایمنی تایپ: پشتیبانی کامل از TypeScript با رابط‌ها و شمارش‌های تعریف‌شده در types.ts.
  • سبک‌وزن: وابستگی‌های حداقلی بدون نیاز به چارچوب خارجی به جز discord.js.

نصب

بسته را نصب کنید:

npm install @persian-caesar/discord-player

مطمئن شوید که از Node.js نسخه 16 یا بالاتر استفاده می‌کنید، همان‌طور که در package.json مشخص شده است.

وابستگی‌ها

وابستگی‌های زیر برای عملکرد صحیح بسته مورد نیاز هستند:

بسته نسخه هدف
@discordjs/voice ^0.18.0 مدیریت اتصال به کانال‌های صوتی و پخش صوت در دیسکورد.
@discordjs/opus ^0.10.0 ارائه کدگذاری/رمزگشایی صوتی Opus برای پخش صوت با کیفیت بالا.
erela.js ^2.4.0 اختیاری: دسترسی به Lavalink برای پشتیبانی پیشرفته از صوت و لیست پخش.
play-dl ^1.9.7 پخش صوت از اسپاتیفای، یوتیوب و دیزر با قابلیت جستجو (حالت بازگشتی).
soundcloud-downloader ^1.0.0 دانلود و پخش صوت از URLهای ساندکلاد (حالت بازگشتی).
html-to-text ^9.0.5 تبدیل HTML (از جستجوهای متن آهنگ گوگل) به متن ساده.
libsodium-wrappers ^0.7.15 مورد نیاز برای رمزگذاری امن صوت در @discordjs/voice.
ffmpeg-static (peer) ارائه FFmpeg برای پردازش صوت و تبدیل جریان.

چرا این وابستگی‌ها؟

  • @discordjs/voice و @discordjs/opus هسته اصلی عملکرد صوتی دیسکورد هستند و به بات امکان پیوستن به کانال‌ها و پخش صوت را می‌دهند.
  • erela.js ادغام اختیاری با Lavalink را برای مقیاس‌پذیری بهتر فراهم می‌کند.
  • play-dl و soundcloud-downloader پخش بازگشتی بدون Lavalink را ارائه می‌دهند.
  • html-to-text برای استخراج و تمیز کردن متن آهنگ از نتایج جستجوی گوگل استفاده می‌شود.
  • libsodium-wrappers و ffmpeg-static برای پردازش امن و کارآمد صوت مورد نیاز هستند.

نمونه‌های استفاده

در زیر نمونه‌هایی برای نشان دادن نحوه ادغام @persian-caesar/discord-player با discord.js در TypeScript و JavaScript ارائه شده است. این نمونه‌ها فرض می‌کنند که شما یک بات دیسکورد با discord.js راه‌اندازی کرده‌اید.

نمونه TypeScript با Lavalink

این نمونه از Lavalink برای پشتیبانی از لیست پخش و عملکرد بهتر استفاده می‌کند.

import { Client, GatewayIntentBits, TextChannel, VoiceChannel } from 'discord.js';
import { MusicPlayer, MusicPlayerEvent, LavalinkManager } from '@persian-caesar/discord-player';

// راه‌اندازی کلاینت دیسکورد با intentهای مورد نیاز
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildVoiceStates,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent
  ]
});

// راه‌اندازی مدیر Erela.js برای Lavalink
const manager = new LavalinkManager(client, {
  nodes: [
    {
      host: "lava-v4.ajieblogs.eu.org",
      port: 443,
      password: "https://dsc.gg/ajidevserver",
      secure: true
    }
  ]
});

// پیکربندی بات
const PREFIX = '!';
const TOKEN = 'YOUR_BOT_TOKEN'; // توکن بات خود را جایگزین کنید

client.on('ready', () => {
  console.log(`وارد شده به عنوان ${client.user?.tag}`);
});

client.on('messageCreate', async (message) => {
  if (!message.content.startsWith(PREFIX) || message.author.bot) return;

  const args = message.content.slice(PREFIX.length).trim().split(/ +/);
  const command = args.shift()?.toLowerCase();

  if (!message.guild || !message.member?.voice.channel) return;

  const voiceChannel = message.member.voice.channel as VoiceChannel;
  const player = new MusicPlayer(voiceChannel, message.channel as TextChannel, manager, {
    autoLeaveOnEmptyQueue: true,
    autoLeaveOnIdleMs: 300_000 // 5 دقیقه
  });

  // شنونده‌های رویداد برای پخش‌کننده موسیقی
  player.on(MusicPlayerEvent.Start, ({ metadata }) => {
    message.channel.send(`▶️ در حال پخش: ${metadata.title || metadata.url}`);
  });

  player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
    const added = metadatas ? metadatas.length + ' آهنگ' : metadata?.title || metadata?.url;
    message.channel.send(`➕ اضافه شد: ${added} (${queue.length} در صف)`);
  });

  player.on(MusicPlayerEvent.Error, (error) => {
    message.channel.send(`❌ خطا: ${error.message}`);
  });

  player.on(MusicPlayerEvent.Finish, () => {
    message.channel.send('⏹️ پخش پایان یافت.');
  });

  // مدیریت دستورات
  if (command === 'play') {
    const query = args.join(' ');
    if (!query) {
      message.channel.send('لطفاً یک URL یا پرس‌وجو ارائه دهید.');
      return;
    }
    await player.play(query);
  } 
  
  else if (command === 'search') {
    const query = args.join(' ');
    const results = await player.search(query, 'youtube');
    const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url}`).join('\n');
    message.channel.send(resultList || 'نتیجه‌ای یافت نشد.');
  } 
  
  else if (command === 'playlists') {
    const query = args.join(' ');
    const playlists = await player.searchPlaylists(query, 'spotify');
    const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} آهنگ): ${p.url}`).join('\n');
    message.channel.send(list || 'لیست پخشی یافت نشد.');
  } 
  
  else if (command === 'isplaylist') {
    const url = args[0];
    const isPlaylist = await player.isPlaylist(url);
    message.channel.send(isPlaylist ? 'بله، این یک لیست پخش است.' : 'خیر، این یک لیست پخش نیست.');
  } // دستورات دیگر را به نیاز اضافه کنید
});

client.login(TOKEN);

نمونه TypeScript بدون Lavalink

این نمونه از پخش مستقیم بدون Lavalink استفاده می‌کند.

import { Client, GatewayIntentBits, TextChannel, VoiceChannel } from 'discord.js';
import { MusicPlayer, MusicPlayerEvent } from '@persian-caesar/discord-player';

// راه‌اندازی کلاینت دیسکورد با intentهای مورد نیاز
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildVoiceStates,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent
  ]
});

// پیکربندی بات
const PREFIX = '!';
const TOKEN = 'YOUR_BOT_TOKEN'; // توکن بات خود را جایگزین کنید

client.on('ready', () => {
  console.log(`وارد شده به عنوان ${client.user?.tag}`);
});

client.on('messageCreate', async (message) => {
  if (!message.content.startsWith(PREFIX) || message.author.bot) return;

  const args = message.content.slice(PREFIX.length).trim().split(/ +/);
  const command = args.shift()?.toLowerCase();

  if (!message.guild || !message.member?.voice.channel) return;

  const voiceChannel = message.member.voice.channel as VoiceChannel;
  const player = new MusicPlayer(voiceChannel, message.channel as TextChannel, undefined, {
    autoLeaveOnEmptyQueue: true,
    autoLeaveOnIdleMs: 300_000, // 5 دقیقه
    youtubeCookie: 'YOUR_YOUTUBE_COOKIE', // اختیاری برای محتوای محدود شده با سن
  });

  // شنونده‌های رویداد برای پخش‌کننده موسیقی
  player.on(MusicPlayerEvent.Start, ({ metadata }) => {
    message.channel.send(`▶️ در حال پخش: ${metadata.title || metadata.url}`);
  });

  player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
    const added = metadatas ? metadatas.length + ' آهنگ' : metadata?.title || metadata?.url;
    message.channel.send(`➕ اضافه شد: ${added} (${queue.length} در صف)`);
  });

  player.on(MusicPlayerEvent.Error, (error) => {
    message.channel.send(`❌ خطا: ${error.message}`);
  });

  player.on(MusicPlayerEvent.Finish, () => {
    message.channel.send('⏹️ پخش پایان یافت.');
  });

  // مدیریت دستورات
  if (command === 'play') {
    const query = args.join(' ');
    if (!query) {
      message.channel.send('لطفاً یک URL یا پرس‌وجو ارائه دهید.');
      return;
    }
    await player.play(query);
  } 
  
  else if (command === 'search') {
    const query = args.join(' ');
    const results = await player.search(query, 'spotify'); // پلتفرم اختیاری
    const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url}`).join('\n');
    message.channel.send(resultList || 'نتیجه‌ای یافت نشد.');
  } 
  
  else if (command === 'playlists') {
    const query = args.join(' ');
    const playlists = await player.searchPlaylists(query, 'deezer');
    const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} آهنگ): ${p.url}`).join('\n');
    message.channel.send(list || 'لیست پخشی یافت نشد.');
  } 
  
  else if (command === 'isplaylist') {
    const url = args[0];
    const isPlaylist = await player.isPlaylist(url);
    message.channel.send(isPlaylist ? 'بله، این یک لیست پخش است.' : 'خیر، این یک لیست پخش نیست.');
  } // دستورات دیگر را به نیاز اضافه کنید
});

client.login(TOKEN);

نمونه JavaScript

این نمونه از JavaScript خالص با Lavalink اختیاری استفاده می‌کند.

const { Client, GatewayIntentBits } = require('discord.js');
const { MusicPlayer, MusicPlayerEvent, LavalinkManager } = require('@persian-caesar/discord-player');

// راه‌اندازی کلاینت دیسکورد با intentهای مورد نیاز
const client = new Client({
  intents: [
    GatewayIntentBits.Guilds,
    GatewayIntentBits.GuildVoiceStates,
    GatewayIntentBits.GuildMessages,
    GatewayIntentBits.MessageContent
  ]
});

// مدیر Lavalink اختیاری
const manager = new LavalinkManager(client, {
  nodes: [
    {
      host: "lava-v4.ajieblogs.eu.org",
      port: 443,
      password: "https://dsc.gg/ajidevserver",
      secure: true
    }
  ]
});

// پیکربندی بات
const PREFIX = '!';
const TOKEN = 'YOUR_BOT_TOKEN'; // توکن بات خود را جایگزین کنید

client.on('ready', () => {
  console.log(`وارد شده به عنوان ${client.user?.tag}`);
});

client.on('messageCreate', async (message) => {
  if (!message.content.startsWith(PREFIX) || message.author.bot) return;

  const args = message.content.slice(PREFIX.length).trim().split(/ +/);
  const command = args.shift()?.toLowerCase();

  if (!message.guild || !message.member?.voice.channel) return;

  /** @type {import('@persian-caesar/discord-player').VoiceChannel} */
  const voiceChannel = message.member.voice.channel;
  const player = new MusicPlayer(voiceChannel, message.channel, manager, { // اگر از Lavalink استفاده می‌کنید، manager را ارسال کنید
    autoLeaveOnEmptyQueue: true,
    autoLeaveOnIdleMs: 300_000 // 5 دقیقه
  });

  // شنونده‌های رویداد برای پخش‌کننده موسیقی
  player.on(MusicPlayerEvent.Start, ({ metadata }) => {
    message.channel.send(`▶️ در حال پخش: ${metadata.title || metadata.url}`);
  });

  player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
    const added = metadatas ? metadatas.length + ' آهنگ' : metadata?.title || metadata?.url;
    message.channel.send(`➕ اضافه شد: ${added} (${queue.length} در صف)`);
  });

  player.on(MusicPlayerEvent.Error, (error) => {
    message.channel.send(`❌ خطا: ${error.message}`);
  });

  player.on(MusicPlayerEvent.Finish, () => {
    message.channel.send('⏹️ پخش پایان یافت.');
  });

  // مدیریت دستورات
  if (command === 'play') {
    const query = args.join(' ');
    if (!query) {
      message.channel.send('لطفاً یک URL یا پرس‌وجو ارائه دهید.');
      return;
    }
    await player.play(query);
  } 
  
  else if (command === 'search') {
    const query = args.join(' ');
    const results = await player.search(query);
    const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url}`).join('\n');
    message.channel.send(resultList || 'نتیجه‌ای یافت نشد.');
  } 
  
  else if (command === 'playlists') {
    const query = args.join(' ');
    const playlists = await player.searchPlaylists(query);
    const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} آهنگ): ${p.url}`).join('\n');
    message.channel.send(list || 'لیست پخشی یافت نشد.');
  } 
  
  else if (command === 'isplaylist') {
    const url = args[0];
    const isPlaylist = await player.isPlaylist(url);
    message.channel.send(isPlaylist ? 'بله، این یک لیست پخش است.' : 'خیر، این یک لیست پخش نیست.');
  } // دستورات دیگر را به نیاز اضافه کنید
});

client.login(TOKEN);

مرجع API

کلاس MusicPlayer

سازنده:

new MusicPlayer(
  channel: VoiceChannel,
  textChannel: TextChannel,
  lavaLinkManager?: Manager, // مدیر Erela.js اختیاری برای Lavalink
  options?: MusicPlayerOptions // { initialVolume?: number, autoLeaveOnEmptyQueue?: boolean, autoLeaveOnIdleMs?: number, youtubeCookie?: string, logError?: boolean }
)

متدها:

متد توضیحات
isPlaylist(url: string): Promise<boolean> بررسی می‌کند که آیا URL داده‌شده یک لیست پخش است.
searchPlaylists(query: string, platform?: SearchPlatform, limit?: number): Promise<PlaylistMetadata[]> جستجوی لیست‌های پخش در پلتفرم‌ها.
search(query: string, platform?: SearchPlatform, limit?: number): Promise<TrackMetadata[]> جستجوی آهنگ‌ها در پلتفرم‌ها.
`play(input: string TrackMetadata
pause(): void مکث آهنگ فعلی.
resume(): void ادامه پخش.
setVolume(percent: number): number تنظیم صدا (0–200٪)، مقدار جدید را برمی‌گرداند.
skip(): void پرش به آهنگ بعدی در صف.
previous(): Promise<void> پخش آهنگ قبلی از تاریخچه.
shuffle(): void به‌هم‌ریختن صف، ذخیره ترتیب اصلی.
undoShuffle(): void بازگرداندن صف به ترتیب پیش از به‌هم‌ریختن.
toggleLoopQueue(): boolean فعال/غیرفعال کردن حلقه صف، وضعیت جدید را برمی‌گرداند.
toggleLoopTrack(): boolean فعال/غیرفعال کردن حلقه آهنگ، وضعیت جدید را برمی‌گرداند.
startRadio(urls: string[]): Promise<void> شروع حالت رادیو با URLهای به‌هم‌ریخته.
stop(noLeave?: boolean): void توقف پخش، به‌صورت اختیاری قطع اتصال می‌کند.
disconnect(): void قطع اتصال از کانال صوتی.
join(): VoiceConnection پیوستن به کانال صوتی بدون اشتراک پخش‌کننده.
getQueue(): TrackMetadata[] کپی صف فعلی را برمی‌گرداند.
getVolume(): number بلندی صدای فعلی (0–200٪) را برمی‌گرداند.
isPlaying(): boolean بررسی می‌کند که آیا آهنگی در حال پخش است.
isPaused(): boolean بررسی می‌کند که آیا پخش مکث شده است.
isShuffiled(): boolean بررسی می‌کند که آیا صف به‌هم‌ریخته است.
isConnected(guildId?: string): boolean بررسی می‌کند که آیا به کانال صوتی متصل است.
`searchLyrics(title: string, artist?: string): Promise<string null>`

شمارش MusicPlayerEvent

export enum MusicPlayerEvent {
  Start = "start",
  QueueAdd = "queueAdd",
  Pause = "pause",
  Resume = "resume",
  Stop = "stop",
  Skip = "skip",
  Previous = "previous",
  Shuffle = "shuffle",
  LoopQueue = "loopQueue",
  LoopTrack = "loopTrack",
  VolumeChange = "volumeChange",
  Finish = "finish",
  Disconnect = "disconnect",
  Error = "error"
}

محتوای رویدادها:

  • Start: { metadata: TrackMetadata, queue: TrackMetadata[] }
  • QueueAdd: { metadata?: TrackMetadata, metadatas?: TrackMetadata[], queue: TrackMetadata[] }
  • VolumeChange: { volume: number }
  • Skip: { queue: TrackMetadata[], history: string[] }
  • Previous: { metadata: TrackMetadata, queue: TrackMetadata[], history: string[] }
  • Shuffle: { queue: TrackMetadata[] }
  • LoopQueue: { enabled: boolean }
  • LoopTrack: { enabled: boolean }
  • Finish: { queue: TrackMetadata[], history: string[] }
  • Error: Error
  • سایرین: بدون محتوا

برای تعاریف کامل تایپ، به types.ts مراجعه کنید.

استفاده و نمونه‌های متدها

این بخش توضیحات مفصل و نمونه‌های کد برای هر متد MusicPlayer ارائه می‌دهد و استفاده از آن‌ها را در زمینه بات دیسکورد با استفاده از discord.js نشان می‌دهد. نمونه‌ها فرض می‌کنند که یک نمونه MusicPlayer همان‌طور که در بخش نمونه‌های استفاده نشان داده شده، ایجاد شده است.

isPlaylist(url: string): Promise<boolean>

بررسی می‌کند که آیا URL داده‌شده یک لیست پخش است.

نمونه:

if (command === 'isplaylist') {
  const url = args[0];
  const isPlaylist = await player.isPlaylist(url);
  message.channel.send(isPlaylist ? 'بله، این یک لیست پخش است.' : 'خیر، این یک لیست پخش نیست.');
}

searchPlaylists(query: string, platform?: SearchPlatform, limit?: number): Promise<PlaylistMetadata[]>

جستجوی لیست‌های پخش در پلتفرم‌ها.

نمونه:

if (command === 'playlists') {
  const query = args.join(' ');
  const playlists = await player.searchPlaylists(query, 'spotify', 5);
  if (playlists.length === 0) {
    message.channel.send('لیست پخشی یافت نشد.');
    return;
  }
  const list = playlists.map((p, i) => `${i + 1}. ${p.title} (${p.trackCount} آهنگ): ${p.url}`).join('\n');
  message.channel.send(`لیست‌های پخش:\n${list}`);
}

search(query: string, platform?: SearchPlatform, limit?: number): Promise<TrackMetadata[]>

جستجوی آهنگ‌ها در پلتفرم‌ها.

نمونه:

if (command === 'search') {
  const query = args.join(' ');
  const results = await player.search(query, 'youtube', 5);
  if (results.length === 0) {
    message.channel.send('نتیجه‌ای یافت نشد.');
    return;
  }
  const resultList = results.map((r, i) => `${i + 1}. ${r.title || r.url} (${r.source})`).join('\n');
  message.channel.send(`نتایج:\n${resultList}`);
}

play(input: string | TrackMetadata | TrackMetadata[], radio?: boolean): Promise<void>

پخش ورودی. اگر رشته باشد، اولین نتیجه را جستجو و پخش می‌کند یا لیست پخش را بارگذاری می‌کند. اگر متادیتا یا آرایه باشد، مستقیم پخش می‌شود.

نمونه:

if (command === 'play') {
  const query = args.join(' ');
  if (!query) {
    message.channel.send('لطفاً یک URL یا پرس‌وجو ارائه دهید.');
    return;
  }
  await player.play(query);
}
player.on(MusicPlayerEvent.Start, ({ metadata }) => {
  message.channel.send(`▶️ در حال پخش: ${metadata.title || metadata.url}`);
});
player.on(MusicPlayerEvent.QueueAdd, ({ metadata, metadatas, queue }) => {
  const added = metadatas ? metadatas.length + ' آهنگ' : metadata?.title || metadata?.url;
  message.channel.send(`➕ اضافه شد: ${added} (${queue.length} در صف)`);
});

pause(): void

مکث آهنگ فعلی.

نمونه:

if (command === 'pause') {
  player.pause();
  message.channel.send('⏸️ پخش مکث شد.');
}

resume(): void

ادامه پخش.

نمونه:

if (command === 'resume') {
  player.resume();
  message.channel.send('▶️ پخش ادامه یافت.');
}

setVolume(percent: number): number

تنظیم صدا (0–200٪)، مقدار جدید را برمی‌گرداند.

نمونه:

if (command === 'volume') {
  const volume = parseInt(args[0]);
  if (isNaN(volume)) {
    message.channel.send('لطفاً یک مقدار صدای معتبر (0–200) ارائه دهید.');
    return;
  }
  const newVolume = player.setVolume(volume);
  message.channel.send(`🔊 صدا تنظیم شد به ${newVolume}%`);
}
player.on(MusicPlayerEvent.VolumeChange, ({ volume }) => {
  message.channel.send(`🔊 صدا تغییر کرد به ${volume}%`);
});

skip(): void

پرش به آهنگ بعدی در صف.

نمونه:

if (command === 'skip') {
  player.skip();
  message.channel.send('⏭️ به آهنگ بعدی پرش شد.');
}
player.on(MusicPlayerEvent.Skip, ({ queue }) => {
  message.channel.send(`⏭️ پرش شد. ${queue.length} آهنگ باقی مانده.`);
});

previous(): Promise<void>

پخش آهنگ قبلی از تاریخچه.

نمونه:

if (command === 'previous') {
  await player.previous();
}
player.on(MusicPlayerEvent.Previous, ({ metadata }) => {
  message.channel.send(`⏮️ پخش قبلی: ${metadata.title || metadata.url}`);
});

shuffle(): void

به‌هم‌ریختن صف.

نمونه:

if (command === 'shuffle') {
  player.shuffle();
  message.channel.send('🔀 صف به‌هم‌ریخته شد.');
}
player.on(MusicPlayerEvent.Shuffle, ({ queue }) => {
  message.channel.send(`🔀 به‌هم‌ریخته شد. ${queue.length} آهنگ در ترتیب جدید.`);
});

undoShuffle(): void

بازگرداندن صف به ترتیب پیش از به‌هم‌ریختن.

نمونه:

if (command === 'unshuffle') {
  player.undoShuffle();
  message.channel.send('🔄 صف بازگردانی شد.');
}

toggleLoopQueue(): boolean

فعال/غیرفعال کردن حلقه صف، وضعیت جدید را برمی‌گرداند.

نمونه:

if (command === 'loopqueue') {
  const enabled = player.toggleLoopQueue();
  message.channel.send(`🔁 حلقه صف ${enabled ? 'فعال' : 'غیرفعال'} شد.`);
}
player.on(MusicPlayerEvent.LoopQueue, ({ enabled }) => {
  message.channel.send(`🔁 حلقه صف ${enabled ? 'فعال' : 'غیرفعال'} شد.`);
});

toggleLoopTrack(): boolean

فعال/غیرفعال کردن حلقه آهنگ، وضعیت جدید را برمی‌گرداند.

نمونه:

if (command === 'looptrack') {
  const enabled = player.toggleLoopTrack();
  message.channel.send(`🔂 حلقه آهنگ ${enabled ? 'فعال' : 'غیرفعال'} شد.`);
}
player.on(MusicPlayerEvent.LoopTrack, ({ enabled }) => {
  message.channel.send(`🔂 حلقه آهنگ ${enabled ? 'فعال' : 'غیرفعال'} شد.`);
});

startRadio(urls: string[]): Promise<void>

شروع حالت رادیو.

نمونه:

if (command === 'radio') {
  const urls = args; // آرایه URLها
  await player.startRadio(urls);
  message.channel.send('📻 حالت رادیو شروع شد.');
}

stop(noLeave?: boolean): void

توقف پخش.

نمونه:

if (command === 'stop') {
  player.stop(true); // متصل باقی بماند
  message.channel.send('⏹️ متوقف شد.');
}
player.on(MusicPlayerEvent.Stop, () => {
  message.channel.send('⏹️ متوقف شد.');
});

disconnect(): void

قطع اتصال از کانال صوتی.

نمونه:

if (command === 'leave') {
  player.disconnect();
  message.channel.send('🔌 قطع اتصال شد.');
}
player.on(MusicPlayerEvent.Disconnect, () => {
  message.channel.send('🔌 قطع اتصال شد.');
});

join(): VoiceConnection

پیوستن به کانال صوتی بدون اشتراک پخش‌کننده.

نمونه:

if (command === 'join') {
  const connection = player.join();
  message.channel.send('🔗 به کانال صوتی پیوسته شد.');
}

getQueue(): TrackMetadata[]

کپی صف فعلی را برمی‌گرداند.

نمونه:

if (command === 'queue') {
  const queue = player.getQueue();
  const list = queue.map((t, i) => `${i + 1}. ${t.title || t.url}`).join('\n');
  message.channel.send(`📃 صف:\n${list || 'خالی'}`);
}

getVolume(): number

بلندی صدای فعلی را برمی‌گرداند.

نمونه:

if (command === 'volume') {
  message.channel.send(`🔊 صدا: ${player.getVolume()}%`);
}

isPlaying(): boolean

بررسی می‌کند که آیا آهنگی در حال پخش است.

نمونه:

if (command === 'status') {
  message.channel.send(`🎵 ${player.isPlaying() ? 'در حال پخش' : 'در حال پخش نیست'}.`);
}

isPaused(): boolean

بررسی می‌کند که آیا پخش مکث شده است.

نمونه:

if (command === 'status') {
  message.channel.send(`⏯️ ${player.isPaused() ? 'مکث شده' : 'مکث نشده'}.`);
}

isShuffiled(): boolean

بررسی می‌کند که آیا صف به‌هم‌ریخته است.

نمونه:

if (command === 'status') {
  message.channel.send(`🔀 صف ${player.isShuffiled() ? 'به‌هم‌ریخته' : 'به‌هم‌ریخته نیست'}.`);
}

isConnected(guildId?: string): boolean

بررسی می‌کند که آیا به کانال صوتی متصل است.

نمونه:

if (command === 'status') {
  message.channel.send(`🔗 ${player.isConnected() ? 'متصل' : 'متصل نیست'}.`);
}

searchLyrics(title: string, artist?: string): Promise<string | null>

بازیابی متن آهنگ.

نمونه:

if (command === 'lyrics') {
  const title = args.join(' ');
  const lyrics = await player.searchLyrics(title, 'artist');
  message.channel.send(lyrics ? `🎵 متن آهنگ:\n${lyrics}` : 'متن آهنگی یافت نشد.');
}

پشتیبانی و مشارکت

مجوز

این پروژه تحت مجوز MIT منتشر شده است. برای جزئیات، فایل LICENSE یا مخزن را ببینید.


⌨️ ساخته‌شده با ❤️ توسط Sobhan-SRZA برای Persian Caesar. اگر مفید بود، به مخزن ستاره دهید!

تماس