// ==UserScript==
// @name Hentai Heroes image viewer
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Allows you to display any stage image of any harem girl, owned ones or not. Works also in event display and Places of Power. Includes zoom-in feature to display full-size girl images gallery (lightbox).
// @author randomfapper34
// @match http*://nutaku.haremheroes.com/*
// @match http*://*.hentaiheroes.com/*
// @match http*://*.gayharem.com/*
// @match http*://*.comixharem.com/*
// @require https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js
// @grant none
// @license MIT
// ==/UserScript==
// gayharem image link head: gh1
// hentaiharem image link head: hh2
// comixharem image link head: ch
var $ = window.jQuery;
var haremHead = (function() {
var haremType = ($('body#hh_gay').length > 0) ?
'gh1' :
($('body#hh_comix').length > 0) ? 'ch' : 'hh2';
return 'https://' + haremType;
})();
var wikiLink = (function() {
var haremType = ($('body#hh_gay').length > 0) ?
'harem-battle.club/wiki/Gay-Harem/GH:' :
($('body#hh_comix').length > 0) ? '' : 'harem-battle.club/wiki/Harem-Heroes/HH:';
return haremType;
})();
var CurrentPage = window.location.pathname;
var sheet = (function() {
var style = document.createElement('style');
document.head.appendChild(style);
return style.sheet;
})();
var imageExt = '-1200x.webp'; //old ext: '.png';
var icoExt = '-300x.webp';
$(document).ready(function() {
//include lightbox css
$(document.head).append(
'<link href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.css" rel="stylesheet" type="text/css">'
);
//define own css
defineCss();
});
// current page: Activities (PoP)
if (CurrentPage.indexOf('activities') != -1)
{
if ($('.pop_list').css('display') != 'none') return;
setTimeout(async function () {
var popElement = $('#activities #pop.canvas');
var popImage = popElement.find('.pop_left_part img');
var popRewardInfo = popElement.find('.pop_rewards_display.reward_wrap').attr('data-reward-display');
var popImageIcon = popElement.find('.pop_rewards_display .shards_girl_ico img');
//if girl is won, there is no shards data in popRewardInfo, and therefore no id. Use regex to get girl id from image link?
var jsonReward = JSON.parse(popRewardInfo);
if (!jsonReward.hasOwnProperty('shards')) return;
var girlInfo = jsonReward.shards[0];
var girlId = girlInfo.id_girl;
var girlGrades = girlInfo.graded2.split('<g').length - 1;
//check for image existance with high grades (always work no matter the webpage display chages)
if (girlGrades == 0) {
girlGrades = 5;
var checkImageLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ava5' + imageExt;
if (await checkUrlResponse(checkImageLink) === false) girlGrades = 3;
}
//create diamonds on the top part
popElement.find('.diamond-bar').remove();
var allDiamonds = '';
for (var i = 0; i <= girlGrades; i++) {
var diamondToAdd = '<div class="diamond unlocked" grade="' + i + '"></div>';
allDiamonds += diamondToAdd;
}
popImage.before('<div class="diamond-bar-container"><div class="diamond-bar">' + allDiamonds + '</div></div>');
//connect diamonds to image links
var allLinks = popElement.find('.diamond');
var linksArray = [];
for (i = 0; i <= girlGrades; i++) {
var imgLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ava' + i + imageExt;
var icoLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ico' + i + icoExt;
linksArray.push(imgLink);
$(allLinks.get(i)).attr("link", imgLink);
$(allLinks.get(i)).attr("icoLink", icoLink);
}
$( ".pop_left_part .diamond-bar .diamond" ).on('mouseenter', function() {
var girlAvatarLink = $(this).attr('link');
var girlIconLink = $(this).attr('icoLink');
popImage.attr('src', girlAvatarLink);
popImageIcon.attr('src', girlIconLink);
});
//create zooming event
$(popImage).removeData('allImages');
$(popImage).data('allImages', linksArray);
$(popImage).on('mouseup', zoomIntoImage);
}, 50);
}
// current page: Event box
if (CurrentPage.indexOf('event') != -1)
{
var eventGirlElementSelector = ".nc-event-list-rewards-container .nc-event-list-reward-container"
var rewardBox = ".nc-event-reward-container.selected ";
var eventGirlImageSelector = ".canvas " + rewardBox + " .nc-event-reward-preview";
var eventGirlInfoSelector = ".canvas " + rewardBox + " .nc-event-reward-info";
setTimeout(function () {
$(eventGirlElementSelector + ".selected").click();
}, 50);
$(eventGirlElementSelector).on('click', function() {
setTimeout(async function () {
var girlImageDiv = $(eventGirlImageSelector);
var girlInfoDiv = $(eventGirlInfoSelector);
var girlInfo = girlInfoDiv.find('.new_girl_info .girl_tooltip_grade');
var girlGrades = girlInfo.find('g').length;
var girlIconImage = $(".nc-event-list-rewards-container > .nc-event-list-reward-container.selected img");
var girlImage = girlImageDiv.children('img');
girlImageDiv.find('.diamond-bar').remove();
//find girl id from image src
var girlImageSrc = girlImage.attr('src');
var startPosition = girlImageSrc.indexOf('pictures/girls/') + 'pictures/girls/'.length;
var girlIdStr = girlImageSrc.substring(startPosition, girlImageSrc.lastIndexOf('/ava'));
if (isNaN(girlIdStr))
return;
var girlId = parseInt(girlIdStr);
//check for image existance with high grades (always work no matter the webpage display chages)
if (girlGrades == 0) {
girlGrades = 5;
var checkImageLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ava' + girlGrades + imageExt;
if (await checkUrlResponse(checkImageLink) === false) girlGrades = 3;
}
//create diamonds on the top part
var allDiamonds = '';
for (var i = 0; i <= girlGrades; i++) {
var diamondToAdd = '<div class="diamond unlocked" grade="' + i + '"></div>';
allDiamonds += diamondToAdd;
}
girlImage.before('<div class="diamond-bar">' + allDiamonds + '</div>');
//connect diamonds to image links
var allLinks = girlImageDiv.find('.diamond');
var linksArray = [];
for (i = 0; i <= girlGrades; i++) {
var imgLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ava' + i + imageExt;
var icoLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ico' + i + icoExt;
linksArray.push(imgLink);
$(allLinks.get(i)).attr("link", imgLink);
$(allLinks.get(i)).attr("icoLink", icoLink);
}
$( rewardBox + " .diamond-bar .diamond" ).on('mouseenter', function() {
var girlAvatarLink = $(this).attr('link');
var girlIconLink = $(this).attr('icoLink');
girlImage.attr('src', girlAvatarLink);
girlIconImage.attr('src', girlIconLink);
});
//create zooming event
$(girlImage).removeData('allImages');
$(girlImage).data('allImages', linksArray);
$(girlImage).off('mouseup', zoomIntoImage);
$(girlImage).on('mouseup', zoomIntoImage);
}, 10);
});
}
// current page: Harem
if (CurrentPage.indexOf('harem') != -1)
{
var callback = function(mutationsList) {
for (let mutation of mutationsList) {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node.outerHTML) {
node.addEventListener('click', onGirlClick, false);
}
});
}
}
};
const targetNode = document.querySelector('#harem_left div.girls_list');
const config = { childList: true };
const observer = new MutationObserver(callback);
observer.observe(targetNode, config);
$( ".girls_list div[id_girl]" ).on('click', onGirlClick);
function onGirlClick(event) {
var girlId = $(this).children('[girl]').attr('girl');
var girlGrades = $(this).find('.graded').children().length;
var girlName = $(this).find('div.right h4')[0].innerText;
updateInfo(girlId, girlGrades, girlName);
}
setTimeout(function () {
//update view of girl currently selected when loading the harem
$("#harem_left div.girls_list div[girl].opened").click();
}, 200);
function updateInfo(girlId, girlGrades, girlName)
{
setTimeout(function () {
var haremRight = $('#harem_right');
haremRight.children('[girl]').each( function() {
if (girlId == 0) girlId = $(this).attr('girl');
var notOwned = $(this).children('.missing_girl');
var girlImageDiv = $(this).find('.avatar-box');
var girlIconDiv = $("#harem_left div.girls_list div[girl].opened div.left img");
if (notOwned.length > 0) {
//create diamonds on the bottom part
var allDiamonds = '';
for (var i = 0; i <= girlGrades; i++) {
var diamondToAdd = '<div class="diamond locked" grade="' + i + '"></div>';
allDiamonds += diamondToAdd;
}
$(this).find('.middle_part').css('margin', '0');
$(this).find('.dialog-box').after('<h3>' + girlName + '</h3>');
$(this).find('img.avatar').wrap('<div class="avatar-box"></div>');
$(this).find('.avatar-box').css('margin-top', '23px');
$(this).find('.avatar-box').after('<div class="diamond-bar">' + allDiamonds + '</div>');
}
//update for any girl (owned or not)
var wikiBase = wikiLink;
if (wikiBase != '') {
$(this).find('h3').wrap('<div class="WikiLink"></div>').wrap('<a href="https://' + wikiBase + girlName + '" target="_blank"></a>');
}
var allLinks = $(this).find('.diamond');
var linksArray = [];
for (i = 0; i <= girlGrades; i++) {
var imgLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ava' + i + imageExt;
var icoLink = haremHead + '.hh-content.com/pictures/girls/' + girlId + '/ico' + i + icoExt;
linksArray.push(imgLink);
$(allLinks.get(i)).attr("link", imgLink);
$(allLinks.get(i)).attr("icoLink", icoLink);
}
$('.avatar-box img.avatar').removeData('allImages');
$('.avatar-box img.avatar').data('allImages', linksArray);
if (notOwned) $('.avatar-box img.avatar').attr('src', linksArray[0]);
$('.variation_block .big_border').on('click', function() {
var girlId = $(this).children('[girl]').attr('girl');
var girlGrades = $(this).find('.graded').children().length;
setTimeout(function() {
updateInfo(girlId, girlGrades, girlName);
}, 50);
});
$( ".diamond-bar .diamond" ).on('mouseenter', function() {
var mainParent = $(this).closest('.middle_part');
var girlAvatar = mainParent.find('img.avatar');
var girlAvatarLink = $(this).attr('link');
var girlIconLink = $(this).attr('icoLink');
girlIconDiv.attr('src', girlIconLink);
girlAvatar.attr('src', girlAvatarLink);
});
$('.avatar-box img.avatar').on('mouseup', zoomIntoImage);
});
}, 0);
}
}
//zoom into image with lightbox, event only on left click
function zoomIntoImage(e)
{
if (e.which != 1) return;
var linksArray = $(this).data('allImages');
var girlAvatarLink = $(this).attr('src');
var indexOfQuestion = girlAvatarLink.lastIndexOf('?');
if (indexOfQuestion >= 0) girlAvatarLink = girlAvatarLink.slice(0, indexOfQuestion);
var indexOfCurrent = linksArray.indexOf(girlAvatarLink);
var allImages = [];
for (var i = 0; i < linksArray.length; i++) {
allImages.push({
src : linksArray[i].toString(),
type : 'image',
opts : {
caption : i == 0 ? 'Default' : 'Stage ' + i
}
});
}
$.fancybox.open(allImages, {
loop : true,
keyboard: true,
transitionEffect: "tube"
}, indexOfCurrent);
}
//checks for any errors in url (like image 404)
async function checkUrlResponse(url)
{
let result = false;
await fetch(url.toString())
.then(function(response) {
if (response.status >= 200 && response.status <= 299) {
return response;
} else {
throw Error(response.statusText);
}
}).then(function(response) {
result = true;
}).catch(function(error) {
});
return result;
}
function defineCss()
{
sheet.insertRule('#harem_left div[girl]>.left>img, #harem_right>div[girl] .middle_part div.avatar-box img.avatar, #shops #girls_list .g1 .girl-ico>img {'
+ 'image-rendering: initial; }');
sheet.insertRule('#harem_right .WikiLink a {'
+ 'text-decoration: none; }');
sheet.insertRule('#harem_right .diamond-bar {'
+ 'margin-top: 4px; }');
sheet.insertRule('.rewards-stats .diamond-bar {'
+ 'position: static;'
+ 'justify-content: center;'
+ 'margin-top: 42px;'
+ 'margin-bottom: -40px; }');
sheet.insertRule('.generic-girl-image .diamond-bar, .nc-event-reward-preview .diamond-bar {'
+ 'justify-content: center;'
+ 'z-index: 1;'
+ 'width: 100%; }');
sheet.insertRule('.rewards-stats .avatars-drawn-bottom-part .diamond-bar {'
+ 'margin-top: 275px; }');
sheet.insertRule('.rewards-stats .avatars-drawn-bottom-part img {'
+ 'margin-top: -275px; }');
sheet.insertRule('.nc-event-reward-preview .diamond-bar {'
+ 'margin-top: -25px; }');
sheet.insertRule('.rewards-stats .diamond-bar .diamond.unlocked, .pop_left_part .diamond-bar .diamond.unlocked, .generic-girl-image .diamond-bar .diamond.unlocked {'
+ 'cursor: default; }');
sheet.insertRule('.pop_left_part .diamond-bar-container {'
+ 'z-index: 5;'
+ 'position: absolute; }');
sheet.insertRule('.pop_left_part .diamond-bar {'
+ 'position: relative;'
+ 'left: 50%; }');
sheet.insertRule('#harem_right .diamond-bar .diamond:hover, .rewards-stats .diamond-bar .diamond:hover, .pop_left_part .diamond-bar .diamond:hover, .generic-girl-image .diamond-bar .diamond:hover, .nc-event-reward-preview .diamond-bar .diamond:hover {'
+ 'border: 2px solid #FE00FE; }');
sheet.insertRule('.avatar-box img, .event-widget.special-fullscreen-view .widget .rewards-stats .reward img, .generic-girl-image img, .nc-event-reward-preview img {'
+ 'cursor: zoom-in; }');
sheet.insertRule('#pop.canvas .pop_left_part img.pop_left_fade_page {'
+ 'margin-bottom: 10px;'
+ 'cursor: zoom-in; }');
}