<commit_before>import Response from './Response';

/**
 * The type of method to use when sending audio responses. One of `'convertedStream'`,
 *   `'file'`, or `'stream'`.
 * @typedef {string} StreamType
 */

/**
 * @external {ReadableStream} https://nodejs.org/dist/latest/docs/api/stream.html#stream_class_stream_readable
 */

/**
 * @external {StreamOptions} https://discord.js.org/#/docs/main/master/typedef/StreamOptions
 */

/**
 * @desc Wrapper for voice channel audio responses.
 */
export default class VoiceResponse extends Response {
  /**
   * Constructor.
   * @param {Object} context - The handler context.
   * @param {StreamType} streamType - The type of stream to use.
   * @param {(ReadableStream|string)} stream - The stream to play, or a string
   *   containing the path to a file.
   * @param {StreamOptions} [options={}] - The options for playing the stream.
   */
  constructor(context, streamType, stream, options = {}) {
    const { message } = context;

    super(async () => {
      if (!message.guild) {
        throw new Error('Cannot send audio replies outside of a guild.');
      }

      const connection = message.guild.voiceConnection;

      if (!connection) {
        throw new Error('Cannot send audio replies without a voice connection.');
      }

      switch (streamType) {
        case 'convertedStream':
          return connection.playConvertedStream(stream, options);
        case 'file':
          return connection.playFile(stream, options);
        case 'stream':
          return connection.playStream(stream, options);
        default:
          throw new Error(`Invalid stream type: ${streamType}.`);
      }
    });
  }
}<commit_msg>Add support for additional voice methods.<commit_after>import { upperFirst } from 'lodash/string';
import Response from './Response';

/**
 * Valid voice input methods.
 * @type {Object}
 * @const
 * @ignore
 */
export const VoiceInputMethods = {
  ARBITARY_INPUT: 'arbitraryInput',
  BROADCAST: 'broadcast',
  CONVERTED_STREAM: 'convertedStream',
  FILE: 'file',
  OPUS_STREAM: 'opusStream',
  STREAM: 'stream',
};

/**
 * @desc Wrapper for voice channel audio responses.
 */
export default class VoiceResponse extends Response {
  /**
   * The type of method to use when sending audio responses. Must be one of:
   *   - `arbitraryInput`
   *   - `broadcast`
   *   - `convertedStream`
   *   - `file`
   *   - `opusStream`
   *   - `stream`
   * @typedef {string} VoiceInputMethod
   */

  /**
   * @external {StreamOptions} https://discord.js.org/#/docs/main/master/typedef/StreamOptions
   */

  /**
   * Constructor.
   * @param {Object} context - The handler context.
   * @param {VoiceInputMethod} inputMethod - The method of voice input to use.
   * @param {*} payload - The source of the voice input.
   * @param {StreamOptions} [options={}] - The options for playing the stream.
   */
  constructor(context, inputMethod, payload, options = {}) {
    const { message } = context;

    super(async () => {
      if (!message.guild) {
        throw new Error('Cannot send audio replies outside of a guild.');
      }

      const connection = message.guild.voiceConnection;

      if (!connection) {
        throw new Error('Cannot send audio replies without a voice connection.');
      }

      const isValidInputMethod = Object.values(VoiceInputMethods)
        .filter(method => method === inputMethod)
        .length;

      if (!isValidInputMethod) {
        throw new Error(`Invalid voice input method: ${inputMethod}.`);
      }

      return connection[`play${upperFirst(inputMethod)}`](payload, options);
    });
  }
}
{'fraction_non_alphanumeric': 0.12969094922737306, 'fraction_numerical': 0.0, 'mean_word_length': 2.9402173913043477, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 3, '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': '5986669', 'n_tokens_mistral': 1046, 'n_tokens_neox': 1017, 'n_words': 305}