<commit_before>"use strict";

const path = require('path');
const url = require('url');

const debug = require('debug')('cardinal:queued-media');
const https = require('follow-redirects').https;

const Types = require('./types');

const YOUTUBE_DL_STORAGE_DIRECTORY = process.env.YOUTUBE_DL_STORAGE_DIRECTORY || '/music';

let logger = null;

class QueuedMedia {
  constructor(musicPlayer, record) {
    Object.defineProperty(this, 'musicPlayer', {
      enumerable: false,
      value: musicPlayer,
    });

    this.corked = false;

    this.type = record.type;
    this.ownerId = record.ownerId;
    this.guildId = record.guildId;

    this.id = record.id || '';
    this.title = record.title || '';
    this.url = record.url || '';
    this.encoding = record.encoding || '';
    this.duration = record.duration || 0;
    this.stream = null;
    this.time = null;

    if (this.type === Types.YTDL) {
      // this.id = record.info.id;
      // this.duration = record.info.duration;
      // this.encoding = record.info.encoding;
      // this.url = record.info.url;

      /*
      // obsolete with new YTDL API
      this.formats = record.formats;
      this.formatIndex = 0;

      const format = this.formats[this.formatIndex];
      this.encoding = format.acodec;
      this.url = format.url;
      */
    } else if (this.type === Types.LOCAL) {
      // this.format = record.format;
      // this.encoding = record.encoding;
      // this.url = record.url;
    } else {
      throw new Error(`unknown type: ${this.type}`);
    }

    this.play = this.play.bind(this);
    this.stopPlaying = this.stopPlaying.bind(this);
    this.printString = this.printString.bind(this);
  }

  static initialize(container) {
    logger = container.get('logger');
  }

  hookEncoderEvents() {
    this.encoder.once('end', () => {
      logger.debug('encoder end', this.id || this.url, this.encoding);
      this.donePlaying();
    });
    this.encoder.once('unpipe', () => {
      logger.debug('encoder unpipe', this.id || this.url, this.encoding);
    });
    this.encoder.once('error', (err) => {
      logger.debug('encoder error', this.id || this.url, this.encoding, err);
    });
  }

  hookPlayEvents() {
    this.stream = this.encoder.play();

    this.stream.resetTimestamp();
    this.stream.removeAllListeners('timestamp');
    this.stream.on('timestamp', (time) => {
      // logger.debug('stream timestamp', this.id || this.url, this.encoding, time);
      this.time = time;
    });
    this.stream.once('end', () => {
      logger.debug('stream end', this.id || this.url, this.encoding);
    });
    this.stream.once('unpipe', () => {
      logger.debug('stream unpipe', this.id || this.url, this.encoding);
    });
  }

  play(voiceConnection) {
    if (this.type === Types.YTDL) {
      return this.playHTTPS(voiceConnection);
    } else if (this.type === Types.LOCAL) {
      return this.playLocal(voiceConnection);
    }
  }

  playHTTPS(voiceConnection, retry) {
/*
    if (this.encoding === 'opus') {
      this.playOpusHTTPS(voiceConnection);
    } else {
*/
      logger.debug(`playHTTPS: ${this.id} ${this.encoding}`);
      //logger.debug('audio is not opus, using ffmpeg');

      this.encoder = voiceConnection.createExternalEncoder({
        type: 'ffmpeg',
        source: this.url,
        format: 'opus',
        outputArgs: ['-ab', '64k'],
        debug: true,
        destroyOnUnpipe: false,
      });

      this.hookEncoderEvents();
      this.hookPlayEvents();
/*
    }
*/
  }

  playLocal(voiceConnection) {
    logger.debug(`playLocal: ${this.url} ${this.encoding}`);
/*
    if (this.encoding === 'opus') {
      this.encoder = voiceConnection.createExternalEncoder({
        type: 'WebmOpusPlayer',
        source: this.url,
      });
    } else {
*/
      this.encoder = voiceConnection.createExternalEncoder({
        type: 'ffmpeg',
        source: this.url,
        format: 'opus',
        debug: true,
      });
/*
    }
*/

    this.hookEncoderEvents();
    this.hookPlayEvents();
  }

  playOpusHTTPS(voiceConnection, retry) {
    logger.debug(`playOpusHTTPS: ${this.id} ${this.encoding}`);

    const parsed = url.parse(this.url);<commit_msg>QueuedMedia: remove really old code<commit_after>"use strict";

const path = require('path');
const url = require('url');

const https = require('follow-redirects').https;

const Types = require('./types');

const YOUTUBE_DL_STORAGE_DIRECTORY = process.env.YOUTUBE_DL_STORAGE_DIRECTORY || '/music';

let logger = null;

class QueuedMedia {
  constructor(musicPlayer, record) {
    Object.defineProperty(this, 'musicPlayer', {
      enumerable: false,
      value: musicPlayer,
    });

    this.corked = false;

    this.type = record.type;
    this.ownerId = record.ownerId;
    this.guildId = record.guildId;

    this.id = record.id || '';
    this.title = record.title || '';
    this.url = record.url || '';
    this.encoding = record.encoding || '';
    this.duration = record.duration || 0;
    this.stream = null;
    this.time = null;

    if (this.type !== Types.YTDL && this.type !== Types.LOCAL) {
      throw new Error(`unknown type: ${this.type}`);
    }

    this.play = this.play.bind(this);
    this.stopPlaying = this.stopPlaying.bind(this);
    this.printString = this.printString.bind(this);
  }

  static initialize(container) {
    logger = container.get('logger');
  }

  hookEncoderEvents() {
    this.encoder.once('end', () => {
      logger.debug('encoder end', this.id || this.url, this.encoding);
      this.donePlaying();
    });
    this.encoder.once('unpipe', () => {
      logger.debug('encoder unpipe', this.id || this.url, this.encoding);
    });
    this.encoder.once('error', (err) => {
      logger.debug('encoder error', this.id || this.url, this.encoding, err);
    });
  }

  hookPlayEvents() {
    this.stream = this.encoder.play();

    this.stream.resetTimestamp();
    this.stream.removeAllListeners('timestamp');
    this.stream.on('timestamp', (time) => {
      // logger.debug('stream timestamp', this.id || this.url, this.encoding, time);
      this.time = time;
    });
    this.stream.once('end', () => {
      logger.debug('stream end', this.id || this.url, this.encoding);
    });
    this.stream.once('unpipe', () => {
      logger.debug('stream unpipe', this.id || this.url, this.encoding);
    });
  }

  play(voiceConnection) {
    if (this.type === Types.YTDL) {
      return this.playHTTPS(voiceConnection);
    } else if (this.type === Types.LOCAL) {
      return this.playLocal(voiceConnection);
    }
  }

  playHTTPS(voiceConnection, retry) {
    logger.debug(`playHTTPS: ${this.id} ${this.encoding}`);
    //logger.debug('audio is not opus, using ffmpeg');

    this.encoder = voiceConnection.createExternalEncoder({
      type: 'ffmpeg',
      source: this.url,
      format: 'opus',
      outputArgs: ['-ab', '64k'],
      debug: true,
      destroyOnUnpipe: false,
    });

    this.hookEncoderEvents();
    this.hookPlayEvents();
  }

  playLocal(voiceConnection) {
    logger.debug(`playLocal: ${this.url} ${this.encoding}`);

    this.encoder = voiceConnection.createExternalEncoder({
      type: 'ffmpeg',
      source: this.url,
      format: 'opus',
      debug: true,
    });

    this.hookEncoderEvents();
    this.hookPlayEvents();
  }

  playOpusHTTPS(voiceConnection, retry) {
    logger.debug(`playOpusHTTPS: ${this.id} ${this.encoding}`);

    const parsed = url.parse(this.url);
{'fraction_non_alphanumeric': 0.16926593170207044, 'fraction_numerical': 0.0009411132024737832, 'mean_word_length': 2.8286155429747812, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 15, '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': '2068079', 'n_tokens_mistral': 2411, 'n_tokens_neox': 2359, 'n_words': 428}