// ==UserScript==
// @name Chaturbate Enhancer
// @description Enhances Chaturbate by adding multiple new features.
// @version 1.1.0
// @author MoonDivision
// @license CC-BY-ND-4.0
// @namespace https://sleazyfork.org/en/users/884016-moondivision
// @contributionURL https://chaturbate.com/in/?tour=JpRf&campaign=Nb8Yz&track=enh-contrib&next=/tipping/purchase_tokens/
// @icon https://www.google.com/s2/favicons?sz=32&domain=chaturbate.com
// @icon64 https://www.google.com/s2/favicons?sz=64&domain=chaturbate.com
// @match https://chaturbate.com/*
// @match https://*.chaturbate.com/*
// @connect camschedule.com
// @grant GM_addElement
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @require https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js
// @run-at document-body
// @noframes
// ==/UserScript==
(function() {
'use strict';
let style = `
/* Hide media overlays */
.photoVideoDetailSection img {
filter: unset !important;
}
.userUpload div {
background: none !important;
}
.psContainer .lockOverlayBg, .smContainer .lockOverlayBg {
display: none !important;
}
.userUpload img[src$="lock.svg"] {
display: none !important;
}
/* Hide ads */
.ad, .vote-banner {
display: none !important;
}
.cb-enh-avatar {
margin-left: 10px;
border: 1px solid #bfbfbf;
width: 150px;
height: 150px;
background-color: #ebebeb;
margin-bottom: 5px;
background-size: 100% 100%;
position: relative;
}
.darkmode .cb-enh-avatar {
border-color: #2d3e50;
background-color: #202c39;
}
.cb-enh-avatar, .cb-enh-avatar img {
border-radius: 150px;
}
.cb-enh-avatar img {
width: 100%;
height: 100%;
opacity: 0;
position: absolute;
left: 0;
top: 0;
-webkit-user-drag: none;
-webkit-app-region: no-drag;
user-drag: none;
app-region: no-drag;
pointer-events: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.cb-enh-footer {
font-size: 14px;
color: #341b00;
font-weight: bold;
}
.darkmode .cb-enh-footer {
color: #efefef;
}
.cb-enh-footer a {
color: inherit !important;
text-decoration: underline;
}
/* Enlarge media in bio */
tr:not(.smContainer) .contentText .previewBorder {
width: 190px;
height: 135px;
}
tr:not(.smContainer) .contentText .tokenText {
top: 118px !important;
right: 5px !important;
}
/* Detach floaters in "about" */
tr:not(.smContainer):not(.psContainer) .contentText img, tr:not(.smContainer):not(.psContainer) .contentText li, tr:not(.smContainer):not(.psContainer) .contentText a, tr:not(.smContainer):not(.psContainer) .contentText p {
position: unset !important;
}
`;
GM_addStyle(style);
$(document).ready(function() {
if('initialRoomDossier' in unsafeWindow) {
enhanceRoom();
}
if(!$('#id_animate_thumbnails').is(':checked')) {
$(document).on('mouseenter', '.room_list_room img, .roomElement img, .roomCard img', function() {
if(window.currentHoverInterval) {
clearInterval(window.currentHoverInterval);
window.currentHoverInterval = null;
}
updateRoomThumb($(this));
window.currentHoverInterval = setInterval(() => {
updateRoomThumb($(this));
}, 100);
});
$(document).on('mouseleave', '.room_list_room img, .roomElement img, .roomCard img', function() {
if(window.currentHoverInterval) {
clearInterval(window.currentHoverInterval);
window.currentHoverInterval = null;
}
});
}
});
function updateRoomThumb($el) {
let uname = $el.parent().data('room');
$el.attr('src', 'https://roomimg.stream.highwebmedia.com/minifwap/' + uname + '.jpg?' + Math.random());
}
document.cookie = 'noads=1; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/';
document.cookie = 'agreeterms=1; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/';
document.cookie = 'fromaffiliate=1; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/';
document.cookie = 'affkey="eJyrViopylayUlBKzctQ0lFQSkxLA/HMiwsM03KTQCIFIL6RIYhZBGKCGCUgRnpRoQGIk5wLVuKXZBFZpVQLAEdlFCg="; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/';
document.cookie = 'noads=1; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/; domain=.chaturbate.com';
document.cookie = 'agreeterms=1; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/; domain=.chaturbate.com';
document.cookie = 'fromaffiliate=1; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/; domain=.chaturbate.com';
document.cookie = 'affkey="eJyrViopylayUlBKzctQ0lFQSkxLA/HMiwsM03KTQCIFIL6RIYhZBGKCGCUgRnpRoQGIk5wLVuKXZBFZpVQLAEdlFCg="; expires=Sun, 1 Jan 9999 00:00:00 UTC; path=/; domain=.chaturbate.com';
function enhanceRoom(ajaxTransition=false) {
$('.cb-enh-row').remove();
if(unsafeWindow.initialRoomDossier === '') {
// initialRoomDossier is set but is empty
// room might be banned or blocked for user
// Display video preview of non accessible room
let $baseRoomContentDiv = $("div.BaseRoomContents div")
if($baseRoomContentDiv.length > 0) {
if($baseRoomContentDiv.text().indexOf("Access denied") === 0) {
$baseRoomContentDiv.append("<br>Chaturbate Enhancer displays video preview of this room.<br><br>");
let $langForm = $("form[action='/set_language/'] input[name='next']");
if($langForm.length > 0) {
let username = $("form[action='/set_language/'] input[name='next']")[0].value.slice(1, -1);
$baseRoomContentDiv.append($("<img id='cb-enh-room-preview' src='https://cbjpeg.stream.highwebmedia.com/stream?room=" + username + "&f=" + Math.random() + "'>"));
setInterval(function() {
let $img = $("#cb-enh-room-preview");
if($img.length > 0) {
$img.attr("src", "https://cbjpeg.stream.highwebmedia.com/stream?room=" + username + "&f=" + Math.random());
}
}, 100);
}
}
}
return;
}
let intv = setInterval(function() {
if($('video.vjs-tech').length > 0) {
// Make clicking on live video feed don't pause it anymore
$('video.vjs-tech').on('pause', function() {
try {
$('video.vjs-tech')[0].play();
} catch(err) {}
});
clearInterval(intv);
// Watch for AJAX page transition
let currentUsername = $("a.nextCamBgColor")[0].getAttribute('href').slice(6, -1);
let pageTransitionIntv = setInterval(function() {
let uname = $("a.nextCamBgColor")[0].getAttribute('href').slice(6, -1);
if(currentUsername != uname) {
clearInterval(pageTransitionIntv);
enhanceRoom(true);
currentUsername = uname;
}
}, 25);
}
}, 25);
let userData;
let broadcasterName;
if(!ajaxTransition) {
userData = JSON.parse(unsafeWindow.initialRoomDossier);
broadcasterName = userData.broadcaster_username;
}
else {
broadcasterName = $("a.nextCamBgColor")[0].getAttribute('href').slice(6, -1);
}
let intervalId = setInterval(() => {
let $table = $('.BioContents > div > table');
if($table.length === 0) {
return;
}
clearInterval(intervalId);
// Add offline avatar
let $offlineNotice = $('.offlineRoomNotice');
if($offlineNotice.length > 0) {
$offlineNotice.prepend('<div class="cb-enh-avatar"></div>');
GM_addElement($('.cb-enh-avatar')[0], 'img', {
src: 'https://camschedule.com/assets/img/avatar.png',
alt: '',
onload: 'this.style.opacity=1'
});
GM_addElement($('.cb-enh-avatar')[0], 'img', {
src: 'https://thumbv.camschedule.com/av/' + broadcasterName + '.jpg',
alt: '',
onload: 'this.style.opacity=1'
});
}
let $divSchedule = addBioRow('Schedule', false, '<div id="cb-enh-iframe"></div>');
if(userData && userData.room_status === 'offline') {
addBioRow('Last Subject', true, userData.room_title);
}
let $divRegion = addBioRow('Region', false, '<a href=""></a>');
let $divOnlineFor = addBioRow('Online For', false);
let lang = $('html').attr('lang');
GM_xmlhttpRequest({
method: 'GET',
url: 'https://camschedule.com/api/room/' + broadcasterName + '?lang=' + lang,
timeout: 60*2*1000,
onload: function(responseDetails) {
let data;
try {
data = JSON.parse(responseDetails.responseText);
}
catch(SyntaxError) {
return;
}
// Populate "region" row
if(data['region'] !== '') {
let href = '#';
if(data['region_id'] == 0) {
href = '/asian-cams/';
}
else if(data['region_id'] == 1) {
href = '/euro-russian-cams/';
}
else if(data['region_id'] == 2) {
href = '/north-american-cams/';
}
else if(data['region_id'] == 3) {
href = '/south-american-cams/';
}
else if(data['region_id'] == 4) {
href = '/other-region-cams/';
}
let elA = $divRegion.children('.cb-enh-row-value').children('a')[0];
elA.innerHTML = data['region'];
elA.href = href;
$divRegion.show();
}
// Populate "online for" row
if(data['online_for'] !== '') {
$divOnlineFor.children('.cb-enh-row-value')[0].innerHTML = data['online_for'];
$divOnlineFor.show();
}
// Add schedule
if(data['has_schedule']) {
let darkMode = $('body').hasClass('darkmode') ? 1 : 0;
let iframeWrapper = document.getElementById('cb-enh-iframe');
GM_addElement(iframeWrapper, 'iframe', {
src: 'https://camschedule.com/embed/schedule/' + broadcasterName + '?dark=' + darkMode + '&lang=' + lang,
style: 'width: 100%; height: 350px; border: 0;',
});
$divSchedule.show();
}
}
});
}, 500);
}
function addBioRow(name, visible = true, value = '') {
let $el = $('<tr class="cb-enh-row" style="' + (visible ? '' : 'display: none; ') + 'font-size: 14px; font-weight: normal; line-height: 15px; vertical-align: top; text-align: left;"><td class="label" style="padding-bottom: 9px; font-family: UbuntuMedium, Arial, Helvetica, sans-serif; height: 16px;"><span>' + name + ':</span></td><td class="contentText cb-enh-row-value" style="font-size: 14px; line-height: 16px; font-family: UbuntuRegular, Arial, Helvetica, sans-serif;">' + value + '</td></tr>');
let $psContainers = $('.BioContents > div > table > .psContainer');
let $smContainers = $('.BioContents > div > table > .smContainer');
if($psContainers.length > 0) {
$psContainers.last().after($el);
}
else if($smContainers.length > 0) {
$smContainers.last().after($el);
}
else {
$('.BioContents > div > table > tr').slice(-2).first().after($el);
}
return $el;
}
})();