Adds support for theHandy for FapInstructor.com
// ==UserScript==
// @name theHandy support for FapInstructor.com
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Adds support for theHandy for FapInstructor.com
// @author notSafeForDev
// @match https://fapinstructor.com
// @grant none
// ==/UserScript==
(function() {
'use strict';
const inputText = document.createElement("input");
inputText.type = "text";
inputText.placeholder = "Enter connection key...";
inputText.style.position = "absolute";
inputText.style.top = "calc(100vh - 100px)";
let stroking = false;
let strokeLength = 0.4;
let lastStrokesPerSecond = 0;
const sendRequest = (url, onResponse) => {
const request = new XMLHttpRequest();
request.open("GET", url);
request.send();
request.onreadystatechange = () => {
if (request.readyState == 4 && onResponse != undefined) {
onResponse(request);
}
}
}
const lerp = (value1, value2, amount) => {
amount = amount < 0 ? 0 : amount;
amount = amount > 1 ? 1 : amount;
return value1 + (value2 - value1) * amount;
}
const updateStrokeLength = () => {
if (inputText.value == "") {
return;
}
const api = "https://www.handyfeeling.com/api/v1/" + inputText.value;
sendRequest(api + "/getSettings", (request) => {
var newStrokeLength = JSON.parse(request.responseText).stroke / 100;
if (newStrokeLength != strokeLength) {
strokeLength = newStrokeLength;
updateStrokeSpeed(lastStrokesPerSecond);
}
});
}
const updateStrokeSpeed = (strokesPerSecond) => {
if (stroking == false && strokesPerSecond == 0) {
return;
}
let toySpeed = Math.round(strokesPerSecond * lerp(10, 45, strokeLength));
const api = "https://www.handyfeeling.com/api/v1/" + inputText.value;
if (stroking == false && strokesPerSecond > 0) {
stroking = true;
sendRequest(api + "/setMode?mode=1", () => {
sendRequest(api + "/setSpeed?speed=" + toySpeed + "&type=%25");
});
} else if (stroking == true && strokesPerSecond == 0) {
stroking = false;
sendRequest(api + "/setMode?mode=0");
} else {
sendRequest(api + "/setSpeed?speed=" + toySpeed + "&type=%25");
}
lastStrokesPerSecond = strokesPerSecond;
}
const getSpeedText = () => {
return document.querySelector(
`#root > div:nth-child(2) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)
> div:nth-child(1) > div:nth-child(2) > div:nth-child(1) > div:nth-child(2) > div:nth-child(2) > p:nth-child(1)`
);
}
const onRequestAnimationFrame = (ms) => {
requestAnimationFrame(onRequestAnimationFrame);
const speedText = getSpeedText();
if (speedText == null) {
if (stroking == true) {
updateStrokeSpeed(0);
}
return;
}
if (inputText.parentNode == null) {
document.body.appendChild(inputText);
}
if (inputText.value == "") {
return;
}
const strokesPerSecond = parseFloat(speedText.textContent);
if (strokesPerSecond != lastStrokesPerSecond) {
updateStrokeSpeed(strokesPerSecond);
}
}
setInterval(() => {
updateStrokeLength();
}, 5000);
requestAnimationFrame(onRequestAnimationFrame);
})();