YouTube Auto-Liker

Automatically likes videos of channels you're subscribed to

  1. // ==UserScript==
  2. // @name YouTube Auto-Liker
  3. // @name:zh YouTube自動點讚
  4. // @name:ja YouTubeのような自動
  5. // @namespace https://github.com/HatScripts/YouTubeAutoLiker
  6. // @version 1.2.0
  7. // @description Automatically likes videos of channels you're subscribed to
  8. // @description:zh 對您訂閲的頻道視頻自動點讚
  9. // @description:ja このスクリプトは、あなたが購読しているチャンネルの動画を自動的に好きです
  10. // @description:ru Этот сценарий автоматически нравится видео каналов, на которые вы подписаны
  11. // @description:es A este script le gustan los videos de los canales a los que está suscrito
  12. // @description:pt Este script gosta automaticamente dos vídeos dos canais aos quais está inscrito
  13. // @author HatScripts
  14. // @icon https://cdn.rawgit.com/HatScripts/YouTubeAutoLiker/master/logo.svg
  15. // @match http://*.youtube.com/watch*
  16. // @match https://*.youtube.com/watch*
  17. // @require https://greasyfork.org/scripts/33864-debugger/code/Debugger.js
  18. // @run-at document-idle
  19. // @noframes
  20. // ==/UserScript==
  21.  
  22. (function () {
  23. 'use strict'
  24.  
  25. const DEBUG_ENABLED = GM_info.script.version === 'DEV_VERSION'
  26. const DEBUG = new Debugger(GM_info.script.name, DEBUG_ENABLED)
  27. const OPTIONS = {
  28. CHECK_FREQUENCY: 5000,
  29. WATCH_THRESHOLD: 0.5,
  30. }
  31. const SELECTORS = {
  32. PLAYER: '#movie_player',
  33. SUBSCRIPTION_BUTTON: '#subscribe-button paper-button, .yt-uix-subscription-button',
  34. LIKE_BUTTON: 'ytd-video-primary-info-renderer #top-level-buttons > ytd-toggle-button-renderer:nth-child(1), .like-button-renderer-like-button:not(.hid)',
  35. }
  36. const LIKE_BUTTON_CLICKED_CLASSES = ['style-default-active', 'like-button-renderer-like-button-clicked']
  37.  
  38. let autoLikedVideoIds = []
  39.  
  40. setTimeout(wait, OPTIONS.CHECK_FREQUENCY)
  41.  
  42. function getVideoId() {
  43. let elem = document.querySelector('#page-manager > ytd-watch-flexy')
  44. if (elem && elem.hasAttribute('video-id')) {
  45. return elem.getAttribute('video-id')
  46. } else {
  47. let queryString = window.location.search
  48. return queryString.substr(queryString.indexOf('v=') + 2, 11)
  49. }
  50. }
  51.  
  52. function watchThresholdReached() {
  53. let player = document.querySelector(SELECTORS.PLAYER)
  54. if (player) {
  55. return player.getCurrentTime() / player.getDuration() >= OPTIONS.WATCH_THRESHOLD
  56. }
  57. return true
  58. }
  59.  
  60. function isSubscribed() {
  61. DEBUG.info('Checking whether subscribed...')
  62. let subscriptionButton = document.querySelector(SELECTORS.SUBSCRIPTION_BUTTON)
  63. if (!subscriptionButton) {
  64. throw 'Couldn\'t find sub button'
  65. }
  66. return subscriptionButton.hasAttribute('subscribed') || subscriptionButton.dataset.isSubscribed
  67. }
  68.  
  69. function wait() {
  70. if (watchThresholdReached()) {
  71. try {
  72. if (isSubscribed()) {
  73. DEBUG.info('We are subscribed')
  74. like()
  75. } else {
  76. DEBUG.info('We are not subscribed')
  77. }
  78. } catch (e) {
  79. DEBUG.info('Failed to like video: ' + e + '. Will try again in 5 seconds...')
  80. }
  81. }
  82. setTimeout(wait, OPTIONS.CHECK_FREQUENCY)
  83. }
  84.  
  85. function like() {
  86. DEBUG.info('Trying to like video...')
  87. let likeButton = document.querySelector(SELECTORS.LIKE_BUTTON)
  88. if (!likeButton) {
  89. throw 'Couldn\'t find like button'
  90. }
  91. let videoId = getVideoId()
  92. if (LIKE_BUTTON_CLICKED_CLASSES.some(c => likeButton.classList.contains(c))) {
  93. DEBUG.info('Like button has already been clicked')
  94. autoLikedVideoIds.push(videoId)
  95. } else if (autoLikedVideoIds.includes(videoId)) {
  96. DEBUG.info('Video has already been auto-liked. User must ' +
  97. 'have un-liked it, so we won\'t like it again')
  98. } else {
  99. DEBUG.info('Found like button')
  100. DEBUG.info('It\'s unclicked. Clicking it...')
  101. likeButton.click()
  102. autoLikedVideoIds.push(videoId)
  103. DEBUG.info('Successfully liked video')
  104. }
  105. }
  106. }())