<commit_before>const path = require('path');
const fs  = require('fs');
const { requirePermission, requirePrefix, splitCommands } = require('../../handler');

const { PLAY_CLIP } = require('./constants');

const clipDir = path.resolve(__dirname, '../../content/clips');

const servers = new Map();

const getServerObject = function(serverID) {
  let obj = servers.get(serverID);
  if (!obj) {
    obj = {
      queue: [],
      playing: false
    };
    servers.set(serverID, obj);
  }

  return obj;
};

const clearQueue = function(serverID) {
  servers.delete(serverID);
};

const resolveClip = function(bot, clipName, serverID) {
  const { redis } = bot;

  return redis.hgetAsync(
    `shinobu_sound_clips:${serverID}`,
    clipName
  ).then(id => id
    ? redis.hgetAsync(`shinobu_sound_clips`, id)
    : Promise.reject("clip isn't in server")
  ).then(value => value
    ? JSON.parse(value)
    : Promise.reject("Clip doesn't exist")
  );
};

const playQueue = function(bot, serverID) {
  shouldPlay(bot, serverID).then(result => result 
    ? playNextFile(bot, serverID)
      .then(stream =>
        stream.once('done', () => playQueue(bot, serverID))
      )
    : getServerObject(serverID).playing = false);
};

const playNextFile = function(bot, serverID) {
  const { client } = bot;
  const voiceChannel = bot.currentServerVoice(serverID);

  return Promise.all([
    client.getAudioContextAsync(voiceChannel),
    Promise.resolve(getServerObject(serverID).queue.shift()),
    Promise.resolve(getServerObject(serverID).playing = true)<commit_msg>Leave voice channel after 60 seconds of inactivity<commit_after>const path = require('path');
const fs  = require('fs');
const { requirePermission, requirePrefix, splitCommands } = require('../../handler');

const { PLAY_CLIP } = require('./constants');

const clipDir = path.resolve(__dirname, '../../content/clips');

const servers = new Map();

const getServerObject = function(serverID) {
  let obj = servers.get(serverID);
  if (!obj) {
    obj = {
      queue: [],
      playing: false
    };
    servers.set(serverID, obj);
  }

  return obj;
};

const clearQueue = function(serverID) {
  servers.delete(serverID);
};

const resolveClip = function(bot, clipName, serverID) {
  const { redis } = bot;

  return redis.hgetAsync(
    `shinobu_sound_clips:${serverID}`,
    clipName
  ).then(id => id
    ? redis.hgetAsync(`shinobu_sound_clips`, id)
    : Promise.reject("clip isn't in server")
  ).then(value => value
    ? JSON.parse(value)
    : Promise.reject("Clip doesn't exist")
  );
};

const resetTimeout = function(bot, serverID) {
  const server = getServerObject(serverID);
  
  if (server.timeout) {
    clearTimeout(server.timeout);
  }

  server.timeout = setTimeout(() => bot.leaveServerVoice(), 60000);
};

const playQueue = function(bot, serverID) {
  shouldPlay(bot, serverID).then(result => result 
    ? playNextFile(bot, serverID)
      .then(stream =>
        stream.once('done', () => {
          resetTimeout(bot, serverID);
          return playQueue(bot, serverID);
        })
      )
    : getServerObject(serverID).playing = false);
};

const playNextFile = function(bot, serverID) {
  const { client } = bot;
  const voiceChannel = bot.currentServerVoice(serverID);

  return Promise.all([
    client.getAudioContextAsync(voiceChannel),
    Promise.resolve(getServerObject(serverID).queue.shift()),
    Promise.resolve(getServerObject(serverID).playing = true)
{'fraction_non_alphanumeric': 0.1506809620399884, 'fraction_numerical': 0.002028397565922921, 'mean_word_length': 3.781163434903047, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5741386', 'n_tokens_mistral': 1101, 'n_tokens_neox': 1082, 'n_words': 221}