MaShowMagic
Blog

Building a queue people trust

ระบบ queue ของบอทเพลงดูเหมือนง่าย — เก็บ list ของเพลง เล่นทีละอัน จบก็ไปต่อ แต่ความจริงคือถ้าทำไม่ดี ผู้ใช้จะเจอเพลงหาย คิวสลับ หรือบอทข้ามเพลงไปเองโดยไม่มีสาเหตุ ผมเจอปัญหาพวกนี้มาหมดแล้วครับ

โครงสร้างที่ใช้

ผมเก็บ queue ในรูปแบบ Map<guildId, Queue> แต่ละ Queue มี:

interface Queue {
  current: Track | null;
  tracks: Track[];
  loop: 'none' | 'track' | 'queue';
  volume: number;
}

จุดที่คนมักทำผิด

ปัญหาใหญ่ที่สุดคือการ advance queue ในที่ที่ผิด หลายคนเขียน logic ไว้ใน skip command แต่นั่นคือหายนะ เพราะถ้าเพลงจบเองตามธรรมชาติ ก็จะมีการ advance สองครั้ง หรือถ้า skip กับ trackEnd เกิดขึ้นใกล้กัน คิวก็จะเพี้ยน

ให้ Lavalink event เป็นตัวขับเคลื่อน queue เสมอ — trackEnd คือจุดเดียวที่ควร advance
shoukaku.on('trackEnd', (player, track, reason) => {
  if (reason === 'REPLACED') return; // skip command จัดการแล้ว
  const queue = queues.get(player.guildId);
  if (!queue) return;
  queue.advance();
  if (queue.current) player.playTrack({ track: queue.current });
  else player.stopTrack();
});

ทำให้ผู้ใช้วางใจได้

สิ่งที่ทำให้คิวน่าเชื่อถือไม่ใช่แค่โค้ดถูกต้อง แต่คือการแสดงผลที่ชัดเจน ผมเพิ่ม embed ที่อัปเดตแบบ real-time บอกว่ากำลังเล่นอะไร ถัดไปคืออะไร และเหลืออีกกี่เพลง — ผู้ใช้ไม่ต้องเดาว่าคิวทำงานอยู่หรือเปล่า


Queue ที่ดีคือ Queue ที่ผู้ใช้ไม่ต้องคิดถึง มันแค่ทำงาน ถ้าใครมีคำถามหรืออยากแชร์ approach ของตัวเองมาคุยกันได้เลยครับที่ Discord