NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript==
// @name Youtube Mass Dislike Script
// @require https://code.jquery.com/jquery-1.11.3.min.js
// @require https://apis.google.com/js/client.js?v=1
// @require https://raw.githubusercontent.com/kimmobrunfeldt/progressbar.js/2af42a3a48979a72a93b989a00bf3e8e75f9f22d/dist/progressbar.js
// @namespace dislike-truck
// @description Source: https://github.com/1v/dislike-truck
// @include /^https?:\/\/(www\.|)youtube\.com[/]+[\s\S]*$/
// @version 1.5.4
// @author 1v
// @grant none
// @icon http://img-fotki.yandex.ru/get/17846/203537249.14/0_1356dd_5dfe78f0_orig.png
// @updateURL https://github.com/1v/dislike-truck/raw/master/dislike-truck.user.js
// @downloadURL https://github.com/1v/dislike-truck/raw/master/dislike-truck.user.js
// @run-at document-end
// ==/UserScript==
/* globals $:false, console:false, ProgressBar:false, gapi:false */
'use strict';
$(function() {
var CLIENT_ID = '595110168346-46igp17sotrer74ld1rbg4onc5smse60.apps.googleusercontent.com',
API_KEY = 'AIzaSyByJQv-QxraMe7iNFEszkcnNk8JfPRTljY',
SCOPES = 'https://www.googleapis.com/auth/youtube',
PER_PAGE = 50,
DELAY_TIME = 500,
DEBUG_ENABLED = false,
PROGRESS_BAR_WIDTH = 305,
I18N = { en: {} };
I18N.default = I18N.en;
I18N.en.register_button_name = 'Register';
I18N.en.dislike_button_name = 'Dislike';
var debug = function(msg) {
if (DEBUG_ENABLED) console.log(msg);
};
var getChannelURI = function() {
var re = /youtube\.com\/(user|channel)\/([^\/]+)/,
m;
if ((m = re.exec(window.location.href)) !== null) {
debug(m);
var that = {};
if (m[1] === 'user') {
that.user = m[2];
} else if (m[1] === 'channel') {
that.id = m[2];
}
return that;
} else {
debug('Not a user page.');
return false;
}
};
var Progress = function() {
var self = new ProgressBar.Line('.progressContainer', {
color: '#CC181E',
strokeWidth: 1,
text: {
value: '0',
style: {
left: '50%',
top: '10px',
margin: '0px',
padding: '2px 0px 0px 3px',
display: 'block',
width: PROGRESS_BAR_WIDTH + 'px',
},
},
step: function(state, bar) {
bar.setText((bar.value() * bar.max).toFixed(0) + ' / ' + bar.max);
},
duration: 500,
fill: '#CC181E',
trailColor: '#FFB7B9',
});
self.increase = function() {
self.animate(++self.current / self.max);
};
self.clear = function() {
self.max = 0;
self.current = 0;
};
self.clear();
self.animate(0);
return self;
}, progress = {};
/**
* Authorize Google Youtube API.
*/
var auth = function(immediate, callback) {
gapi.client.setApiKey(API_KEY);
gapi.auth.authorize({
client_id: CLIENT_ID,
scope: SCOPES,
immediate: immediate
}, callback);
};
function authorization(callback) {
auth(true, function(authResult) {
debug(authResult);
if (authResult && !authResult.error) {
// Authorization was successful. Hide authorization prompts and show
// content that should be visible after authorization succeeds.
loadAPIClientInterfaces(callback);
} else {
// Make the #login-link clickable. Attempt a non-immediate OAuth 2.0
// client flow. The current function is called when that flow completes.
auth(false, function() {
loadAPIClientInterfaces(callback);
});
}
});
}
function loadAPIClientInterfaces(callback) {
debug(gapi);
gapi.client.load('youtube', 'v3', function() {
debug('gapi loaded');
if (typeof callback === 'function') {
callback();
}
});
}
// appendUnloadingButton();
$(document).on('mouseover', function() {
if ($('.unload-trucks').length < 1 && getChannelURI()) {
debug(getChannelURI());
appendUnloadingButton();
}
});
function appendUnloadingButton() {
var button = $('<span style="float: left; margin-right: 5px;" class="yt-uix-button-subscription-container"><button class="yt-uix-button yt-uix-button-size-default yt-uix-button-subscribe-branded yt-uix-button-has-icon no-icon-markup yt-uix-subscription-button" type="button"><span class="yt-uix-button-content"><span class="subscribe-label">Подписаться</span></span></button></span>');
$('.channel-header-subscription-button-container')
.before(button.clone().addClass('register-loader').find('.subscribe-label').text(I18N.default.register_button_name).end())
.before(button.clone().addClass('unload-trucks').find('.subscribe-label').text(I18N.default.dislike_button_name).end())
.after('<div style="position: absolute; width: ' + PROGRESS_BAR_WIDTH + 'px; height: 30px; top: 95px; right: 15px"><div class="progressContainer"></div></div>');
progress = new Progress();
}
function appendSimonov(add) {
if ($('.simonov').length < 1 && add) {
$('.register-loader')
.before($('<img>').attr({'src': '//img-fotki.yandex.ru/get/9515/203537249.14/0_136180_483da1b3_orig.gif',
'class': 'simonov'})
.css({'float': 'left', 'margin-right': '5px'}));
} else {
$('.simonov').remove();
}
}
$(document).on('click', '.register-loader', function(e) {
e.preventDefault();
debug('.register-loader clicked');
auth(false, loadAPIClientInterfaces(function() {
setTimeout(function() {
beginDisliking(getChannelURI());
}, 15000);
}));
});
$(document).on('click', '.unload-trucks', function(e) {
e.preventDefault();
authorization(function() {
beginDisliking(getChannelURI());
});
});
function beginDisliking(user) {
progress.clear();
// if in page url "/channel/"
if (user.id) {
requestPlaylistId(user.id);
} else if (user.user) { // if in page url "/user/" request channel id
var request = gapi.client.youtube.channels.list({
forUsername: user.user,
part: 'id'
});
request.execute(function(response) {
requestPlaylistId(response.items[0].id);
});
}
}
function requestPlaylistId(channelId) {
appendSimonov(true);
var request = gapi.client.youtube.channels.list({
id: channelId,
part: 'contentDetails'
});
request.execute(function(response) {
requestVideos(response.items[0].contentDetails.relatedPlaylists.uploads);
});
}
// requesting videos from channel
// channelId -
function requestVideos(plId, responseObj) {
var q = {
playlistId: plId,
maxResults: PER_PAGE,
fields: 'items/snippet/title,items/snippet/resourceId/videoId,nextPageToken,pageInfo',
part: 'snippet'
};
q.pageToken = (responseObj !== undefined && responseObj.nextPageToken !== undefined) ? responseObj.nextPageToken : null;
var request = gapi.client.youtube.playlistItems.list(q);
request.execute(function(response) {
progress.max = response.pageInfo.totalResults;
proceedDislikes(plId, response);
});
}
function proceedDislikes(channelId, responseObj) {
var singleDislikeCallback = function(i) {
if (responseObj.nextPageToken === undefined &&
(responseObj.items.length - 1) === i) {
appendSimonov(false);
}
};
for (var i = 0; i < responseObj.items.length; i++) {
var q = {
id: responseObj.items[i].snippet.resourceId.videoId,
rating: 'dislike'
};
proceedSingleDislike(q, i, singleDislikeCallback(i));
}
if (responseObj !== undefined && responseObj.nextPageToken !== undefined) {
// should start all pages at same time, but actually starts in queue
setTimeout(function() {
requestVideos(channelId, responseObj);
}, DELAY_TIME * PER_PAGE);
}
}
function proceedSingleDislike(query, delay, callback) {
setTimeout(function(callback) {
var request = gapi.client.youtube.videos.rate(query);
request.execute(function() {
return true;
});
progress.increase();
if (typeof callback === 'function') {
callback.call(this, delay);
}
}, DELAY_TIME * delay, callback);
}
});