<commit_before>// Import libraries
const PlexAPI = require('plex-api');
const jsonfile = require('jsonfile');
require('tinylog');
const EventEmitter = require('events');

// Add server defaults
const SERVER_DEFAULT = {
  hostname: 'localhost',
  port: 32400,
  https: false,
}

// Define the main class
class Plexacious {
  constructor() {
    this.cache = this._readCache();
    this._eventEmitter = new EventEmitter();

    // Declare default listeners for logging purposes
    this
      .on('newListener', (event) => console.log(`Listener added to event '${event}'`))
      .on('removeListener', (event) => console.log(`Listener removed from event '${event}'`))
      .on('init', config => console.log(`Instantiating Plex API object to ${config.https ? 'https' : 'http'}://${config.hostname}:${config.port}...`))
      .on('startQuery', uri => console.log(`Getting data from ${uri}`))
      .on('endQuery', uri => console.log(`Finished getting data from ${uri}`))
      .on('startDigest', () => console.log('Starting digest...'))
      .on('endDigest', () => console.log('Digest complete.'))
      .on('newSession', session => console.log('Session', `${session.user.title} has started watching ${session.title} on ${session.player.title}`))
      .on('endSession', session => console.log('Session', `${session.user.title} has stopped watching ${session.title}`));
  }

  /***********************
  *                      *
  * Public API functions *
  *                      *
  ***********************/

  /**
   * Establish a connection to a specified Plex server
   * 
   * @param {Object} config - The Plex server
   * @param {?string} config.hostname - The server host name (eg localhost, plex.server.com), defaults to 'localhost'
   * @param {?number} config.port - The server port, defaults to 32400
   * @param {?boolean} config.https - Set to true if HTTPS connection is required, defaults to false
   * @param {token} config.token - The Plex Authentication token
   * @param {?number} config.refreshDuration - The refresh timer in minutes, defaults to 15
   * 
   * @return {Plexacious} - Returns the Plexacious object itself for method chaining
   */
  init (config) {
    this.config = {
      hostname: config.hostname || SERVER_DEFAULT.hostname,
      port: config.port || SERVER_DEFAULT.port,
      https: config.https || SERVER_DEFAULT.https,
      token: config.token,
      refreshDuration: config.refreshDuration || SERVER_DEFAULT.refreshDuration,
    }

    this._init = true;

    this._eventEmitter.emit('init', config);
    this.plex = new PlexAPI(this.config);

    this.setRefreshDuration(this.config.refreshDuration);

    return this;
  }

  /**
   * Modify the refresh duration (aka the digest timer), and runs the digest function immediately
   *
   * @param {integer} timer - The time between digest() calls in minutes
   * 
   * @return {Plexacious} - Returns the Plexacious object itself for method chaining
   */
  setRefreshDuration (timer = 15) {
    if (this._intervalObj) {
      // Clear the existing intervalObject if present
      clearInterval(this._intervalObj);
    }

    this._intervalObj = setInterval(this._digest.bind(this), timer * 60000);
    this._digest();

    return this;
  }

  /**
   * Bind or unbind a callback function to an event
   *
   * @param {string} event - The event to which to bind or unbind the callback function
   * @param {function} callback - The callback function to be called when the event occurs. If not provided, any existing callback function for the specified event will be removed.
   * 
   * @return {Plexacious} - Returns the Plexacious object itself for method chaining
   */
  on (eventName, callback) {
    if (eventName) {
      if (callback) {
        this._eventEmitter.on(eventName, callback);
      }
      else {
        this._eventEmitter.removeAllListeners(eventName);
      }
    }

    return this;
  }

  /*************************
  *                        *
  * THE DIGEST             *
  *                        *
  *************************/

  /**
   * The digest function which is run on an interval specified by the refreshDuration setting.
   *
   * It will check what's going on with the server periodically, pulling data from it and then calling the attached callback functions if any.
   */
  _digest () {
    this._eventEmitter.emit('startDigest');

    Promise.all([this._processSessions(), this._processSections()])
      .then(() => {
        this._init = false;
        this._writeCache();
        this._eventEmitter.emit('endDigest');
      })
      .catch(console.error.bind(console));
  }

  /*************************
  *                        *
  * Data Getters           *<commit_msg>Add some comments to the digest function<commit_after>// Import libraries
const PlexAPI = require('plex-api');
const jsonfile = require('jsonfile');
require('tinylog');
const EventEmitter = require('events');

// Add server defaults
const SERVER_DEFAULT = {
  hostname: 'localhost',
  port: 32400,
  https: false,
}

// Define the main class
class Plexacious {
  constructor() {
    this.cache = this._readCache();
    this._eventEmitter = new EventEmitter();

    // Declare default listeners for logging purposes
    this
      .on('newListener', (event) => console.log(`Listener added to event '${event}'`))
      .on('removeListener', (event) => console.log(`Listener removed from event '${event}'`))
      .on('init', config => console.log(`Instantiating Plex API object to ${config.https ? 'https' : 'http'}://${config.hostname}:${config.port}...`))
      .on('startQuery', uri => console.log(`Getting data from ${uri}`))
      .on('endQuery', uri => console.log(`Finished getting data from ${uri}`))
      .on('startDigest', () => console.log('Starting digest...'))
      .on('endDigest', () => console.log('Digest complete.'))
      .on('newSession', session => console.log('Session', `${session.user.title} has started watching ${session.title} on ${session.player.title}`))
      .on('endSession', session => console.log('Session', `${session.user.title} has stopped watching ${session.title}`));
  }

  /***********************
  *                      *
  * Public API functions *
  *                      *
  ***********************/

  /**
   * Establish a connection to a specified Plex server
   * 
   * @param {Object} config - The Plex server
   * @param {?string} config.hostname - The server host name (eg localhost, plex.server.com), defaults to 'localhost'
   * @param {?number} config.port - The server port, defaults to 32400
   * @param {?boolean} config.https - Set to true if HTTPS connection is required, defaults to false
   * @param {token} config.token - The Plex Authentication token
   * @param {?number} config.refreshDuration - The refresh timer in minutes, defaults to 15
   * 
   * @return {Plexacious} - Returns the Plexacious object itself for method chaining
   */
  init (config) {
    this.config = {
      hostname: config.hostname || SERVER_DEFAULT.hostname,
      port: config.port || SERVER_DEFAULT.port,
      https: config.https || SERVER_DEFAULT.https,
      token: config.token,
      refreshDuration: config.refreshDuration || SERVER_DEFAULT.refreshDuration,
    }

    this._init = true;

    this._eventEmitter.emit('init', config);
    this.plex = new PlexAPI(this.config);

    this.setRefreshDuration(this.config.refreshDuration);

    return this;
  }

  /**
   * Modify the refresh duration (aka the digest timer), and runs the digest function immediately
   *
   * @param {integer} timer - The time between digest() calls in minutes
   * 
   * @return {Plexacious} - Returns the Plexacious object itself for method chaining
   */
  setRefreshDuration (timer = 15) {
    if (this._intervalObj) {
      // Clear the existing intervalObject if present
      clearInterval(this._intervalObj);
    }

    this._intervalObj = setInterval(this._digest.bind(this), timer * 60000);
    this._digest();

    return this;
  }

  /**
   * Bind or unbind a callback function to an event
   *
   * @param {string} event - The event to which to bind or unbind the callback function
   * @param {function} callback - The callback function to be called when the event occurs. If not provided, any existing callback function for the specified event will be removed.
   * 
   * @return {Plexacious} - Returns the Plexacious object itself for method chaining
   */
  on (eventName, callback) {
    if (eventName) {
      if (callback) {
        this._eventEmitter.on(eventName, callback);
      }
      else {
        this._eventEmitter.removeAllListeners(eventName);
      }
    }

    return this;
  }

  /*************************
  *                        *
  * THE DIGEST             *
  *                        *
  *************************/

  /**
   * The digest function which is run on an interval specified by the refreshDuration setting.
   *
   * It will check what's going on with the server periodically, pulling data from it and then calling the attached callback functions if any.
   */
  _digest () {
    this._eventEmitter.emit('startDigest');

    Promise.all([this._processSessions(), this._processSections()])
      .then(() => {
        // this._init is used to tell if this is the first time running the digest function. On the first time, event listeners are not called as the bot is gathering the initial data
        this._init = false;
        this._writeCache();
        // Write all the data to cache
        // Emit the final event
        this._eventEmitter.emit('endDigest');
      })
      .catch(console.error.bind(console));
  }

  /*************************
  *                        *
  * Data Getters           *
{'fraction_non_alphanumeric': 0.14519785655399836, 'fraction_numerical': 0.0039159109645507005, 'mean_word_length': 2.89446227929374, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, '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': '1497740', 'n_tokens_mistral': 2733, 'n_tokens_neox': 2664, 'n_words': 826}