fix reordering
This commit is contained in:
179
bot/src/index.js
179
bot/src/index.js
@@ -32,6 +32,7 @@ let currentState = {
|
||||
position: 0,
|
||||
volume: 100,
|
||||
queue: [],
|
||||
history: [],
|
||||
shuffled: false
|
||||
};
|
||||
|
||||
@@ -39,6 +40,7 @@ let connection = null;
|
||||
let player = null;
|
||||
let startTime = 0;
|
||||
let currentResource = null;
|
||||
const MAX_HISTORY = 50; // Keep last 50 tracks in history
|
||||
|
||||
// Discord client
|
||||
const client = new Client({
|
||||
@@ -75,7 +77,22 @@ function initializeQueue() {
|
||||
}
|
||||
|
||||
// Play next track in queue
|
||||
function playNext() {
|
||||
function playNext(skipToNext = false) {
|
||||
// When skipping manually, add current track to history
|
||||
// When track finishes naturally, move current to end of queue (continuous loop)
|
||||
if (currentState.currentTrack) {
|
||||
if (skipToNext) {
|
||||
// Manual skip - add to history for "previous" functionality
|
||||
currentState.history.unshift(currentState.currentTrack);
|
||||
if (currentState.history.length > MAX_HISTORY) {
|
||||
currentState.history.pop();
|
||||
}
|
||||
} else {
|
||||
// Natural finish - move to end of queue for continuous loop
|
||||
currentState.queue.push(currentState.currentTrack);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentState.queue.length === 0) {
|
||||
logger.info('Queue empty, reloading library');
|
||||
initializeQueue();
|
||||
@@ -109,6 +126,43 @@ function playNext() {
|
||||
}
|
||||
}
|
||||
|
||||
// Play previous track from history
|
||||
function playPrevious() {
|
||||
if (currentState.history.length === 0) {
|
||||
logger.info('No previous track in history');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put current track back at the front of the queue
|
||||
if (currentState.currentTrack) {
|
||||
currentState.queue.unshift(currentState.currentTrack);
|
||||
}
|
||||
|
||||
// Get previous track from history
|
||||
const track = currentState.history.shift();
|
||||
currentState.currentTrack = track;
|
||||
currentState.position = 0;
|
||||
currentState.state = 'playing';
|
||||
startTime = Date.now();
|
||||
|
||||
logger.info(`Playing previous track: ${track.title}`);
|
||||
|
||||
try {
|
||||
currentResource = createAudioResource(track.filepath, {
|
||||
inlineVolume: true
|
||||
});
|
||||
currentResource.volume.setVolume(currentState.volume / 100);
|
||||
player.play(currentResource);
|
||||
return true;
|
||||
} catch (error) {
|
||||
logger.error(`Error playing previous track: ${error.message}`);
|
||||
currentResource = null;
|
||||
// If previous track fails, continue to next
|
||||
playNext();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Connect to voice channel
|
||||
async function connectToVoice() {
|
||||
try {
|
||||
@@ -177,10 +231,17 @@ app.get('/health', (req, res) => {
|
||||
|
||||
app.get('/state', (req, res) => {
|
||||
const elapsed = currentState.state === 'playing' ? Math.floor((Date.now() - startTime) / 1000) : 0;
|
||||
|
||||
// Queue includes current track + remaining tracks
|
||||
const fullQueue = currentState.currentTrack
|
||||
? [currentState.currentTrack, ...currentState.queue]
|
||||
: [...currentState.queue];
|
||||
|
||||
res.json({
|
||||
...currentState,
|
||||
position: currentState.position + elapsed,
|
||||
queueLength: currentState.queue.length
|
||||
queueLength: currentState.queue.length,
|
||||
fullQueue: fullQueue
|
||||
});
|
||||
});
|
||||
|
||||
@@ -208,10 +269,58 @@ app.post('/pause', (req, res) => {
|
||||
|
||||
app.post('/skip', (req, res) => {
|
||||
logger.info('Skipping to next track');
|
||||
playNext();
|
||||
|
||||
// Move current track to end of queue instead of history
|
||||
if (currentState.currentTrack) {
|
||||
currentState.queue.push(currentState.currentTrack);
|
||||
}
|
||||
|
||||
// Get next track from queue
|
||||
if (currentState.queue.length > 0) {
|
||||
const track = currentState.queue.shift();
|
||||
currentState.currentTrack = track;
|
||||
currentState.position = 0;
|
||||
currentState.state = 'playing';
|
||||
startTime = Date.now();
|
||||
|
||||
try {
|
||||
currentResource = createAudioResource(track.filepath, {
|
||||
inlineVolume: true
|
||||
});
|
||||
currentResource.volume.setVolume(currentState.volume / 100);
|
||||
player.play(currentResource);
|
||||
} catch (error) {
|
||||
logger.error(`Error playing track: ${error.message}`);
|
||||
currentResource = null;
|
||||
}
|
||||
}
|
||||
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
app.post('/previous', (req, res) => {
|
||||
logger.info('Playing previous track');
|
||||
const success = playPrevious();
|
||||
res.json({ success, hasHistory: currentState.history.length > 0 });
|
||||
});
|
||||
|
||||
app.post('/seek', (req, res) => {
|
||||
const { position } = req.body;
|
||||
|
||||
if (typeof position !== 'number' || position < 0) {
|
||||
return res.status(400).json({ error: 'Invalid position' });
|
||||
}
|
||||
|
||||
// Note: Discord.js voice doesn't support seeking within a track
|
||||
// This would require re-creating the audio resource from the seek position
|
||||
// For now, we'll return an error indicating this limitation
|
||||
logger.warn('Seek requested but not supported by Discord.js voice');
|
||||
res.status(501).json({
|
||||
error: 'Seek not supported',
|
||||
message: 'Discord.js voice library does not support seeking within tracks'
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/volume', (req, res) => {
|
||||
const { volume } = req.body;
|
||||
if (volume >= 0 && volume <= 100) {
|
||||
@@ -238,6 +347,70 @@ app.post('/queue/shuffle', (req, res) => {
|
||||
res.json({ success: true, shuffled: currentState.shuffled });
|
||||
});
|
||||
|
||||
app.post('/queue/reorder', (req, res) => {
|
||||
const { from, to } = req.body;
|
||||
|
||||
// Full queue includes current track + remaining queue
|
||||
const fullQueue = currentState.currentTrack
|
||||
? [currentState.currentTrack, ...currentState.queue]
|
||||
: [...currentState.queue];
|
||||
|
||||
if (typeof from !== 'number' || typeof to !== 'number' ||
|
||||
from < 0 || to < 0 ||
|
||||
from >= fullQueue.length || to >= fullQueue.length) {
|
||||
return res.status(400).json({ error: 'Invalid indices' });
|
||||
}
|
||||
|
||||
// Move the track
|
||||
const [track] = fullQueue.splice(from, 1);
|
||||
fullQueue.splice(to, 0, track);
|
||||
|
||||
// Update state: first track becomes current, rest becomes queue
|
||||
if (fullQueue.length > 0) {
|
||||
currentState.currentTrack = fullQueue[0];
|
||||
currentState.queue = fullQueue.slice(1);
|
||||
|
||||
// If we moved the current track and it's playing, restart it
|
||||
if (from === 0 && currentState.state === 'playing') {
|
||||
currentState.position = 0;
|
||||
startTime = Date.now();
|
||||
|
||||
try {
|
||||
currentResource = createAudioResource(currentState.currentTrack.filepath, {
|
||||
inlineVolume: true
|
||||
});
|
||||
currentResource.volume.setVolume(currentState.volume / 100);
|
||||
player.play(currentResource);
|
||||
} catch (error) {
|
||||
logger.error(`Error replaying track: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info(`Queue reordered: moved track from ${from} to ${to}`);
|
||||
res.json({ success: true, queue: fullQueue });
|
||||
});
|
||||
|
||||
|
||||
app.post('/queue/add', (req, res) => {
|
||||
const { trackId } = req.body;
|
||||
|
||||
if (!trackId) {
|
||||
return res.status(400).json({ error: 'Track ID required' });
|
||||
}
|
||||
|
||||
const library = loadMusicLibrary();
|
||||
const track = library.find(t => t.id === trackId);
|
||||
|
||||
if (!track) {
|
||||
return res.status(404).json({ error: 'Track not found' });
|
||||
}
|
||||
|
||||
currentState.queue.push(track);
|
||||
logger.info(`Added ${track.title} to queue`);
|
||||
res.json({ success: true, queue: currentState.queue });
|
||||
});
|
||||
|
||||
app.get('/channels', async (req, res) => {
|
||||
try {
|
||||
const guild = await client.guilds.fetch(DISCORD_GUILD_ID);
|
||||
|
||||
Reference in New Issue
Block a user