NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
/* eslint-disable max-len */
// ==UserScript==
// @name Kamihime Project NTK - Bypass New DL
// @version 3.0.0
// @icon https://g.pikan.party/wiki/portrait/(Dream%20Cotton%20Spiral)%20Uriel%20Portrait.png
// @description Have you ever felt that as soon as you read this, you already wasted 4 hours of reading? FOUR. HOURS!one1!!1!one1
// @author Eunicorn
// @license MIT
// @match https://pf.nutaku.com/*
// @match https://osapi.nutaku.com/*
// @match https://gnkh-api-r.prod.nkh.dmmgames.com/front/cocos2d-proj/components-pc/game/app.html
// @match https://gnkh-api-g.prod.nkh.dmmgames.com/front/cocos2d-proj/components-pc/game/app.html
// @match https://gnkh-api-r.prod.nkh.dmmgames.com/front/cocos2d-proj/components-sp/game/app.html
// @match https://gnkh-api-g.prod.nkh.dmmgames.com/front/cocos2d-proj/components-sp/game/app.html
// @run-at document-start
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_setClipboard
// @require https://openuserjs.org/src/libs/sizzle/GM_config.js
// ==/UserScript==
/* eslint-enable max-len */
/* globals GM_config, kh, Q */
const gm = {
key: 'Ramiel_Sucks_Her_Own_Dick_Yes_Stop_Reading_Me_GTFO',
async getCredentials () {
const settings = await GM_getValue(this.key, undefined);
if (!settings) return undefined;
return JSON.parse(settings);
},
async setCredentials (key, val) {
const creds = (await this.getCredentials()) || { };
if (!key) return GM_setValue(this.key, '');
Object.assign(creds, {
[key]: val,
updated: new Date().valueOf()
});
return GM_setValue(this.key, JSON.stringify(creds));
}
};
// GM_Config
/* eslint-disable camelcase */
GM_config.init({
id: 'ramielcfg',
title: 'Bypass DL - Settings',
fields: {
popup: {
label: 'Popup Window',
type: 'checkbox',
default: true
},
size: {
label: 'Popup Window iFrame Size',
type: 'text',
default: '960x640'
},
colour: {
label: 'Popup Window Background Colour',
type: 'text',
default: '#000'
}
}
});
GM_registerMenuCommand('Bypass DL Settings', () => GM_config.open());
/* eslint-enable camelcase */
const SESSION_ID = 'sessionId';
const CSRF_TOKEN = 'csrfToken';
const RAMIEL_CFG_DEFAULT = '{ "popup": true, "size": "960x640" }';
function getHTML (width, height, colour, versionType, deviceType) {
/* eslint-disable indent */
return [
'<!DOCTYPE html>',
'<html>',
'<head>',
'<title>Uriel is Probably Gay</title>',
'</head>',
`<body style="background-color:${colour};">`,
'<p align="center">',
// eslint-disable-next-line max-len
`<iframe title="Ditto" src="https://gnkh-api-${versionType}.prod.nkh.dmmgames.com/front/cocos2d-proj/components-${deviceType}/game/app.html" width="${width}" height="${height}" />`,
'</p>',
'</body>',
'</html>',
].join('\n');
/* eslint-enable indent */
}
// function sleep (ms = 2e3) {
// return new Promise(res => setTimeout(res, ms));
// }
(async () => {
const ntkApiRegex = /^https:\/\/(?:pf|osapi)\.nutaku\.com\/gadgets\/ifr.*kamihime/i;
if (ntkApiRegex.test(window.location.href)) {
let lastUpdated = new Date().valueOf();
const interval = setInterval(async () => {
if (!kh || (kh && !kh.Session)) return;
if (!kh.Session.getCsrfToken() || !kh.Session.getSessionId()) return;
if ((new Date().valueOf() - lastUpdated) < 5e3) return;
await gm.setCredentials(CSRF_TOKEN, kh.Session.getCsrfToken());
await gm.setCredentials(SESSION_ID, kh.Session.getSessionId());
clearInterval(interval);
const deviceType = kh.env.isSp ? 'sp' : 'pc';
const versionType = kh.env.isR18 ? 'r' : 'g';
const url = [
`https://gnkh-api-${versionType}`,
`prod.nkh.dmmgames.com/.dmmgames.com/front/cocos2d-proj/components-${deviceType}/game/app.html`,
].join('.');
try {
const gmc = JSON.parse(await GM_getValue('ramielcfg', RAMIEL_CFG_DEFAULT));
const sized = gmc.size.trim().split('x').filter(s => s).map(s => Number(s));
const [ width = 960, height = 640 ] = sized;
if (gmc.popup) {
// Keeps the window size intact, instead of going to DL right away
const newWindow = window.open('', '_blank', `width=${width + 25}, height=${height + 25}`);
newWindow.document.open();
newWindow.document.write(getHTML(width, height, gmc.colour, versionType, deviceType));
newWindow.document.close();
newWindow.focus();
window.alert('You can close this window now.');
} else top.window.location.href = url;
} catch (_) {
console.error(_);
await GM_setClipboard(url, 'text');
alert([
'Redirect/popup is disabled.',
'Please allow this site to redirect/popup or change script settings.',
'\nAnyhow: Game URL has been copied to your clipboard. You can access it now.',
].join('\n'));
}
}, 30);
return;
}
const creds = await gm.getCredentials();
const fail = async () => {
const isAdultVersion = /cf\.r/i.test(window.location.href);
const url = `https://nutaku.${isAdultVersion ? 'net' : 'com'}/games/kamihime${isAdultVersion ? '-r' : ''}/play`;
await GM_setClipboard(url, 'text');
return alert([
'You must go to normal game window first.',
'\nURL has been copied to your clipboard if you don\'t know it.',
].join('\n'));
};
if (!creds) return fail();
// If token already 1 hour last updated
if ((new Date().valueOf() - creds.updated) > 36e5) {
await gm.setCredentials(undefined);
return fail();
}
const interval = setInterval(() => {
if (!kh || (kh && !kh.GameSession)) return;
clearInterval(interval);
Object.defineProperties(kh.GameSession.prototype, {
awaitSetFirstSession: {
value () {
this._sendParentFrameFlag = false;
this.setSessionId(creds.sessionId, false, true);
this.setCsrfToken(creds.csrfToken, false, true);
return Q.resolve();
}
},
setSessionId: {
value (val, toParent = true, initial) {
this.set(SESSION_ID, val, toParent);
if (!initial) gm.setCredentials(SESSION_ID, val);
}
},
setCsrfToken: {
value (val, toParent = true, initial) {
this.set(CSRF_TOKEN, val, toParent);
if (!initial) gm.setCredentials(CSRF_TOKEN, val);
}
}
});
}, 30);
})();