<commit_before>const selectors = {
  likeButton: [
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(1) yt-icon-button',
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(1) button',
    '#segmented-like-button button',
  ],
  dislikeButton: [
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(2) yt-icon-button',
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(2) button',
    '#segmented-dislike-button button',
  ],
  subscribeButton: [
    '#subscribe-button tp-yt-paper-button',
    '#subscribe-button button',
  ],
};

/**
 * Likes YouTube videos
 */
export default class Liker {
  /**
   * @param {Object} options
   */
  constructor({ options, log }) {
    this.options = options;
    this.log = log ? log : () => {};
    this.cache = {};
    this.start = this.start.bind(this);

    // Bail if we don't need to do anything
    // DEPRECATION: options.like_what = 'none' removed in 2.0.2. Replaced with options.disabled
    if (this.options.disabled || this.options.like_what === 'none') {
      this.log('liker is disabled');
      return this.pause();
    }

    /*
    We're hooking into YouTube's custom events to determine when the page changes.
     */
    document
      .querySelector('ytd-app')
      .addEventListener('yt-page-data-updated', this.start);

    this.start();
  }

  /**
   * Just helpful for debugging at the moment
   */
  pause() {
    this.log('paused');
    if (typeof this.onPause === 'function') {
      this.onPause();
    }
  }

  /**
   * Clears data for another round of slick liking action
   */
  reset() {
    this.cache = {};
  }

  /**
   * Detects when like/dislike buttons have loaded (so we can press them)
   */
  waitForButtons() {
    this.log('waiting for buttons...');

    return new Promise((resolve) => {
      const interval = setInterval(() => {
        const likeButton = document.querySelectorAll(selectors.likeButton)[0];
        const dislikeButton = document.querySelectorAll(
          selectors.dislikeButton
        )[0];
        // Make sure both buttons exist
        if (likeButton && dislikeButton) {
          // Store buttons
          this.cache.likeButton = likeButton;
          this.cache.dislikeButton = dislikeButton;

          this.log('...buttons ready');
          clearInterval(interval);
          resolve();
        }
      }, 1000);
    });
  }

  /**
   * Detects when the video player has loaded
   */
  waitForVideo() {
    this.log('waiting for video...');

    return new Promise((resolve) => {
      const interval = setInterval(() => {
        this.cache.video = document.querySelector('.video-stream');
        // Does the video exist?
        if (this.cache.video) {
          this.log('...video ready');
          clearInterval(interval);
          resolve();
        }
      }, 1000);
    });
  }

  /**
   * @return {Boolean} True if the like or dislike button is active
   */
  isVideoRated() {
    return (
      (this.cache.likeButton.classList.contains('style-default-active') &&
        !this.cache.likeButton.classList.contains('size-default')) ||
      this.cache.dislikeButton.classList.contains('style-default-active') ||
      this.cache.likeButton.getAttribute('aria-pressed') === 'true' ||
      this.cache.dislikeButton.getAttribute('aria-pressed') === 'true'
    );
  }

  /**
   * @return {Boolean} True if the user is subscribed to
   *                   the current video's channel
   */
  isUserSubscribed() {
    // Select the sub button
    const subscribeButton =
      this.cache.subscribeButton ||
      document.querySelectorAll(selectors.subscribeButton)[0];
    // Does the button exist?
    if (!subscribeButton) {
      this.log('no subscribe button found');
      return false;
    }
    // Is the button active?
    if (
      subscribeButton.hasAttribute('subscribed') ||
      subscribeButton.classList.contains('yt-spec-button-shape-next--filled')
    ) {
      this.cache.subscribeButton = subscribeButton;
      return true;
    }
    // TODO: If not, let's reinitialize the Liker if the user subscribes
    // else if (this.options.like_what === 'subscribed') {
    //   subButton.addEventListener('click', e => {
    //     e.target.removeEventListener(e.type, arguments.callee);
    //     this.init();
    //   });
    // }
    return false;
  }

  isAdPlaying() {
    return (
      this.cache.video &&
      ['ad-showing', 'ad-interrupting'].every((c) => {
        return this.cache.video
          .closest('.html5-video-player')
          .classList.contains(c);
      })
    );
  }

  /**<commit_msg>Update subscribed class<commit_after>const selectors = {
  likeButton: [
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(1) yt-icon-button',
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(1) button',
    '#segmented-like-button button',
  ],
  dislikeButton: [
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(2) yt-icon-button',
    '#top-level-buttons-computed > ytd-toggle-button-renderer:nth-child(2) button',
    '#segmented-dislike-button button',
  ],
  subscribeButton: [
    '#subscribe-button tp-yt-paper-button',
    '#subscribe-button button',
  ],
};

/**
 * Likes YouTube videos
 */
export default class Liker {
  /**
   * @param {Object} options
   */
  constructor({ options, log }) {
    this.options = options;
    this.log = log ? log : () => {};
    this.cache = {};
    this.start = this.start.bind(this);

    // Bail if we don't need to do anything
    // DEPRECATION: options.like_what = 'none' removed in 2.0.2. Replaced with options.disabled
    if (this.options.disabled || this.options.like_what === 'none') {
      this.log('liker is disabled');
      return this.pause();
    }

    /*
    We're hooking into YouTube's custom events to determine when the page changes.
     */
    document
      .querySelector('ytd-app')
      .addEventListener('yt-page-data-updated', this.start);

    this.start();
  }

  /**
   * Just helpful for debugging at the moment
   */
  pause() {
    this.log('paused');
    if (typeof this.onPause === 'function') {
      this.onPause();
    }
  }

  /**
   * Clears data for another round of slick liking action
   */
  reset() {
    this.cache = {};
  }

  /**
   * Detects when like/dislike buttons have loaded (so we can press them)
   */
  waitForButtons() {
    this.log('waiting for buttons...');

    return new Promise((resolve) => {
      const interval = setInterval(() => {
        const likeButton = document.querySelectorAll(selectors.likeButton)[0];
        const dislikeButton = document.querySelectorAll(
          selectors.dislikeButton
        )[0];
        // Make sure both buttons exist
        if (likeButton && dislikeButton) {
          // Store buttons
          this.cache.likeButton = likeButton;
          this.cache.dislikeButton = dislikeButton;

          this.log('...buttons ready');
          clearInterval(interval);
          resolve();
        }
      }, 1000);
    });
  }

  /**
   * Detects when the video player has loaded
   */
  waitForVideo() {
    this.log('waiting for video...');

    return new Promise((resolve) => {
      const interval = setInterval(() => {
        this.cache.video = document.querySelector('.video-stream');
        // Does the video exist?
        if (this.cache.video) {
          this.log('...video ready');
          clearInterval(interval);
          resolve();
        }
      }, 1000);
    });
  }

  /**
   * @return {Boolean} True if the like or dislike button is active
   */
  isVideoRated() {
    return (
      (this.cache.likeButton.classList.contains('style-default-active') &&
        !this.cache.likeButton.classList.contains('size-default')) ||
      this.cache.dislikeButton.classList.contains('style-default-active') ||
      this.cache.likeButton.getAttribute('aria-pressed') === 'true' ||
      this.cache.dislikeButton.getAttribute('aria-pressed') === 'true'
    );
  }

  /**
   * @return {Boolean} True if the user is subscribed to
   *                   the current video's channel
   */
  isUserSubscribed() {
    // Select the sub button
    const subscribeButton =
      this.cache.subscribeButton ||
      document.querySelectorAll(selectors.subscribeButton)[0];

    // Does the button exist?
    if (!subscribeButton) {
      this.log('no subscribe button found');
      return false;
    }

    // Is the button active?
    if (
      subscribeButton.hasAttribute('subscribed') ||
      subscribeButton.classList.contains('yt-spec-button-shape-next--tonal')
    ) {
      this.cache.subscribeButton = subscribeButton;
      return true;
    }
    // TODO: If not, let's reinitialize the Liker if the user subscribes
    // else if (this.options.like_what === 'subscribed') {
    //   subButton.addEventListener('click', e => {
    //     e.target.removeEventListener(e.type, arguments.callee);
    //     this.init();
    //   });
    // }
    return false;
  }

  isAdPlaying() {
    return (
      this.cache.video &&
      ['ad-showing', 'ad-interrupting'].every((c) => {
        return this.cache.video
          .closest('.html5-video-player')
          .classList.contains(c);
      })
    );
  }

  /**
{'fraction_non_alphanumeric': 0.14869087382825127, 'fraction_numerical': 0.004094386380777934, 'mean_word_length': 2.3814207650273223, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 25, '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': '3793007', 'n_tokens_mistral': 2829, 'n_tokens_neox': 2784, 'n_words': 578}