Here's the link : https://milovana.com/webteases/showtease.php?id=45102
I thought it was time for a new POT challenge.
This thread is for comments, suggestions and bug reports.
Please leave your feedback and suggestions.




Code: Select all
// ==UserScript==
// @name EOS
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://oeos.art/?id=*
// @icon https://www.google.com/s2/favicons?domain=oeos.art
// @grant none
// ==/UserScript==
(function() {
'use strict';
const maxStrokeSpeed = 400;
const maxStrokeLength = 190;
const apiKey = 'YOUR_HANDY_API_KEY'; // api key
const api = "https://www.handyfeeling.com/api/handy/v2";
let lastSpeed = 0;
const sendRequest = (url, data, verb, onResponse) => {
let myHeaders = new Headers();
if (verb.trim().toLowerCase() !== 'option'){
myHeaders.append('X-Connection-Key', apiKey);
myHeaders.append('Content-Type', 'application/json');
myHeaders.append('Accept', 'application/json');
}
const options = {
method: verb,
headers: myHeaders,
mode: 'cors',
}
if (data) {
options.body = JSON.stringify(data);
}
console.log(url, 'request: ', options);
fetch(url, options)
.then(function(response) {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.json().then((r)=>{
console.log('response: ', r);
onResponse(r);
});
})
}
sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => {
sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => {
sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{
console.log('handy set');
});
});
});
/**
* Calculates the stroke speed and distance from the specified beats per second.
*
* Lookup Table
* ====================
* Speed / Stroke = BPS
* 400 / 80 = 5
* 400 / 100 = 4
* 400 / 133 = 3
* 400 / 200 = 2
* 300 / 200 = 1.5
* 200 / 200 = 1
* 100 / 200 = 0.5
* 50 / 200 = 0.25
*/
function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) {
maxSpeed = Math.min(maxStrokeSpeed, maxSpeed);
maxLength = Math.min(maxStrokeLength, maxLength);
let speed = maxSpeed;
let length = maxLength;
const fastestBPS = maxSpeed / maxLength;
// Decrease stroke speed to increase BPS
if (bps < fastestBPS) {
speed = maxLength * bps;
}
// Shorten stroke distance to increase BPS
if (bps > fastestBPS) {
length = maxSpeed / bps;
}
return {
speed,
stroke: length,
};
}
function changeSpeed(newState) {
sendRequest(api + "/hamp/state", null, 'GET',(response)=>{
console.log('state',response);
if (response.state !== 2){
sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{
console.log('start')
sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
console.log(request.speed)
sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
});
});
} else {
if (lastSpeed !== newState.speed){
if (lastSpeed > newState.speed){
sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{
console.log(request.speed)
sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed));
});
} else {
sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{
console.log(request.speed)
sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed));
});
}
}
}
lastSpeed = newState.speed;
});
}
const mainWrapperCallback = (records, ob) => {
records.forEach((record)=>{
if (record.target.id === 'oeos-sounds'){
const data = record.target.querySelector('data');
if (data){
const match = data.value.match(/([1-9].+)bpm/);
if (match){
const bpm = parseInt(match[1],10);
console.log('bpm',bpm);
const newState = getStrokeSpeedAndDistance(bpm/60);
changeSpeed(newState);
} else {
const bpsMatch = data.value.match(/([1-9].+)bps/);
if (bpsMatch){
const bps = parseInt(bpsMatch[1],10);
const newState = getStrokeSpeedAndDistance(bps);
changeSpeed(newState);
} else {
const bpsMatch = data.value.match(/([1-9].+)ps/);
if (bpsMatch){
const bps = parseInt(bpsMatch[1],10);
const newState = getStrokeSpeedAndDistance(bps);
changeSpeed(newState);
}
}
}
} else {
// remove the next 3 lines
sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{
console.log('stop', response);
});
}
}
});
};
const mainWrapper = document.querySelector('.v-main__wrap');
// Create an observer instance linked to the callback function
const wrapperObserver = new MutationObserver(mainWrapperCallback);
// Start observing the target node for configured mutations
wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true });
})();

Thx a lot! Are you able to edit it?Ghingis wrote: Sat Dec 04, 2021 3:50 pm The thing is it is not so easy to continue after a while, this might help if you have a handy..
* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art
How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)
If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.
Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.
Code: Select all
// ==UserScript== // @name EOS // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://oeos.art/?id=* // @icon https://www.google.com/s2/favicons?domain=oeos.art // @grant none // ==/UserScript== (function() { 'use strict'; const maxStrokeSpeed = 400; const maxStrokeLength = 190; const apiKey = 'YOUR_HANDY_API_KEY'; // api key const api = "https://www.handyfeeling.com/api/handy/v2"; let lastSpeed = 0; const sendRequest = (url, data, verb, onResponse) => { let myHeaders = new Headers(); if (verb.trim().toLowerCase() !== 'option'){ myHeaders.append('X-Connection-Key', apiKey); myHeaders.append('Content-Type', 'application/json'); myHeaders.append('Accept', 'application/json'); } const options = { method: verb, headers: myHeaders, mode: 'cors', } if (data) { options.body = JSON.stringify(data); } console.log(url, 'request: ', options); fetch(url, options) .then(function(response) { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json().then((r)=>{ console.log('response: ', r); onResponse(r); }); }) } sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => { sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => { sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{ console.log('handy set'); }); }); }); /** * Calculates the stroke speed and distance from the specified beats per second. * * Lookup Table * ==================== * Speed / Stroke = BPS * 400 / 80 = 5 * 400 / 100 = 4 * 400 / 133 = 3 * 400 / 200 = 2 * 300 / 200 = 1.5 * 200 / 200 = 1 * 100 / 200 = 0.5 * 50 / 200 = 0.25 */ function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) { maxSpeed = Math.min(maxStrokeSpeed, maxSpeed); maxLength = Math.min(maxStrokeLength, maxLength); let speed = maxSpeed; let length = maxLength; const fastestBPS = maxSpeed / maxLength; // Decrease stroke speed to increase BPS if (bps < fastestBPS) { speed = maxLength * bps; } // Shorten stroke distance to increase BPS if (bps > fastestBPS) { length = maxSpeed / bps; } return { speed, stroke: length, }; } function changeSpeed(newState) { sendRequest(api + "/hamp/state", null, 'GET',(response)=>{ console.log('state',response); if (response.state !== 2){ sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{ console.log('start') sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed)); }); }); } else { if (lastSpeed !== newState.speed){ if (lastSpeed > newState.speed){ sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed)); }); } else { sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed)); }); } } } lastSpeed = newState.speed; }); } const mainWrapperCallback = (records, ob) => { records.forEach((record)=>{ if (record.target.id === 'oeos-sounds'){ const data = record.target.querySelector('data'); if (data){ const match = data.value.match(/([1-9].+)bpm/); if (match){ const bpm = parseInt(match[1],10); console.log('bpm',bpm); const newState = getStrokeSpeedAndDistance(bpm/60); changeSpeed(newState); } else { const bpsMatch = data.value.match(/([1-9].+)bps/); if (bpsMatch){ const bps = parseInt(bpsMatch[1],10); const newState = getStrokeSpeedAndDistance(bps); changeSpeed(newState); } else { const bpsMatch = data.value.match(/([1-9].+)ps/); if (bpsMatch){ const bps = parseInt(bpsMatch[1],10); const newState = getStrokeSpeedAndDistance(bps); changeSpeed(newState); } } } } else { // remove the next 3 lines sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{ console.log('stop', response); }); } } }); }; const mainWrapper = document.querySelector('.v-main__wrap'); // Create an observer instance linked to the callback function const wrapperObserver = new MutationObserver(mainWrapperCallback); // Start observing the target node for configured mutations wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true }); })();
You are welcome, I'm not sure what do you want to edit on this, but anyone could do it.Achatius wrote: Sun Dec 19, 2021 11:17 amThx a lot! Are you able to edit it?Ghingis wrote: Sat Dec 04, 2021 3:50 pm The thing is it is not so easy to continue after a while, this might help if you have a handy..
* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art
How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)
If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.
Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.
Code: Select all
// ==UserScript== // @name EOS // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://oeos.art/?id=* // @icon https://www.google.com/s2/favicons?domain=oeos.art // @grant none // ==/UserScript== (function() { 'use strict'; const maxStrokeSpeed = 400; const maxStrokeLength = 190; const apiKey = 'YOUR_HANDY_API_KEY'; // api key const api = "https://www.handyfeeling.com/api/handy/v2"; let lastSpeed = 0; const sendRequest = (url, data, verb, onResponse) => { let myHeaders = new Headers(); if (verb.trim().toLowerCase() !== 'option'){ myHeaders.append('X-Connection-Key', apiKey); myHeaders.append('Content-Type', 'application/json'); myHeaders.append('Accept', 'application/json'); } const options = { method: verb, headers: myHeaders, mode: 'cors', } if (data) { options.body = JSON.stringify(data); } console.log(url, 'request: ', options); fetch(url, options) .then(function(response) { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json().then((r)=>{ console.log('response: ', r); onResponse(r); }); }) } sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => { sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => { sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{ console.log('handy set'); }); }); }); /** * Calculates the stroke speed and distance from the specified beats per second. * * Lookup Table * ==================== * Speed / Stroke = BPS * 400 / 80 = 5 * 400 / 100 = 4 * 400 / 133 = 3 * 400 / 200 = 2 * 300 / 200 = 1.5 * 200 / 200 = 1 * 100 / 200 = 0.5 * 50 / 200 = 0.25 */ function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) { maxSpeed = Math.min(maxStrokeSpeed, maxSpeed); maxLength = Math.min(maxStrokeLength, maxLength); let speed = maxSpeed; let length = maxLength; const fastestBPS = maxSpeed / maxLength; // Decrease stroke speed to increase BPS if (bps < fastestBPS) { speed = maxLength * bps; } // Shorten stroke distance to increase BPS if (bps > fastestBPS) { length = maxSpeed / bps; } return { speed, stroke: length, }; } function changeSpeed(newState) { sendRequest(api + "/hamp/state", null, 'GET',(response)=>{ console.log('state',response); if (response.state !== 2){ sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{ console.log('start') sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed)); }); }); } else { if (lastSpeed !== newState.speed){ if (lastSpeed > newState.speed){ sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed)); }); } else { sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed)); }); } } } lastSpeed = newState.speed; }); } const mainWrapperCallback = (records, ob) => { records.forEach((record)=>{ if (record.target.id === 'oeos-sounds'){ const data = record.target.querySelector('data'); if (data){ const match = data.value.match(/([1-9].+)bpm/); if (match){ const bpm = parseInt(match[1],10); console.log('bpm',bpm); const newState = getStrokeSpeedAndDistance(bpm/60); changeSpeed(newState); } else { const bpsMatch = data.value.match(/([1-9].+)bps/); if (bpsMatch){ const bps = parseInt(bpsMatch[1],10); const newState = getStrokeSpeedAndDistance(bps); changeSpeed(newState); } else { const bpsMatch = data.value.match(/([1-9].+)ps/); if (bpsMatch){ const bps = parseInt(bpsMatch[1],10); const newState = getStrokeSpeedAndDistance(bps); changeSpeed(newState); } } } } else { // remove the next 3 lines sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{ console.log('stop', response); }); } } }); }; const mainWrapper = document.querySelector('.v-main__wrap'); // Create an observer instance linked to the callback function const wrapperObserver = new MutationObserver(mainWrapperCallback); // Start observing the target node for configured mutations wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true }); })();

Would be great to shorten the tease. Every image is too long / there is a lack of input. It's just like fapping 30 seconds for a single sentence. And the first "hour" in a slow rhythm. A 10 Minute "impossible POT-Challenge" is good enough, where you have to have your orgasm at least at minute 7 or 8.Ghingis wrote: Mon Dec 20, 2021 12:07 amYou are welcome, I'm not sure what do you want to edit on this, but anyone could do it.Achatius wrote: Sun Dec 19, 2021 11:17 amThx a lot! Are you able to edit it?Ghingis wrote: Sat Dec 04, 2021 3:50 pm The thing is it is not so easy to continue after a while, this might help if you have a handy..
* Install the script (google for "tempermonkey" or "greasemonkey" you will find it how)
* Open the tease on oeos.art
How it works in a sentence:
It watches the html dom and if a new sound gets added / removed, it checks the filename if it has *bpm / *bps / *ps in the filename it sets the handy via api, so it would reach that speed / stops it.
(it might work with other teases if the audio filename matches..)
If it bothers you that the handy stops when the page changes, there is a comment in the code: remove the next 3 lines
Just remove them.
Note: you can use the buttons on the handy to stop / move the stoke zone, but it will be changed in the next page.
Code: Select all
// ==UserScript== // @name EOS // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @match https://oeos.art/?id=* // @icon https://www.google.com/s2/favicons?domain=oeos.art // @grant none // ==/UserScript== (function() { 'use strict'; const maxStrokeSpeed = 400; const maxStrokeLength = 190; const apiKey = 'YOUR_HANDY_API_KEY'; // api key const api = "https://www.handyfeeling.com/api/handy/v2"; let lastSpeed = 0; const sendRequest = (url, data, verb, onResponse) => { let myHeaders = new Headers(); if (verb.trim().toLowerCase() !== 'option'){ myHeaders.append('X-Connection-Key', apiKey); myHeaders.append('Content-Type', 'application/json'); myHeaders.append('Accept', 'application/json'); } const options = { method: verb, headers: myHeaders, mode: 'cors', } if (data) { options.body = JSON.stringify(data); } console.log(url, 'request: ', options); fetch(url, options) .then(function(response) { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json().then((r)=>{ console.log('response: ', r); onResponse(r); }); }) } sendRequest(api + "/mode", {mode: 0}, 'PUT',(request) => { sendRequest(api + "/slide", {min: 0, max: maxStrokeLength}, 'PUT',(request) => { sendRequest(api + "/hamp/velocity", {velocity: 20}, 'PUT',()=>{ console.log('handy set'); }); }); }); /** * Calculates the stroke speed and distance from the specified beats per second. * * Lookup Table * ==================== * Speed / Stroke = BPS * 400 / 80 = 5 * 400 / 100 = 4 * 400 / 133 = 3 * 400 / 200 = 2 * 300 / 200 = 1.5 * 200 / 200 = 1 * 100 / 200 = 0.5 * 50 / 200 = 0.25 */ function getStrokeSpeedAndDistance(bps, maxSpeed = 400, maxLength = 200) { maxSpeed = Math.min(maxStrokeSpeed, maxSpeed); maxLength = Math.min(maxStrokeLength, maxLength); let speed = maxSpeed; let length = maxLength; const fastestBPS = maxSpeed / maxLength; // Decrease stroke speed to increase BPS if (bps < fastestBPS) { speed = maxLength * bps; } // Shorten stroke distance to increase BPS if (bps > fastestBPS) { length = maxSpeed / bps; } return { speed, stroke: length, }; } function changeSpeed(newState) { sendRequest(api + "/hamp/state", null, 'GET',(response)=>{ console.log('state',response); if (response.state !== 2){ sendRequest(api + "/hamp/start", null, 'PUT',(response)=>{ console.log('start') sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed)); }); }); } else { if (lastSpeed !== newState.speed){ if (lastSpeed > newState.speed){ sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>console.log(request.speed)); }); } else { sendRequest(api + "/slide", {min: 0, max: newState.stroke/2}, 'PUT',(request)=>{ console.log(request.speed) sendRequest(api + "/hamp/velocity", {velocity: newState.speed / 4}, 'PUT',(request)=>console.log(request.speed)); }); } } } lastSpeed = newState.speed; }); } const mainWrapperCallback = (records, ob) => { records.forEach((record)=>{ if (record.target.id === 'oeos-sounds'){ const data = record.target.querySelector('data'); if (data){ const match = data.value.match(/([1-9].+)bpm/); if (match){ const bpm = parseInt(match[1],10); console.log('bpm',bpm); const newState = getStrokeSpeedAndDistance(bpm/60); changeSpeed(newState); } else { const bpsMatch = data.value.match(/([1-9].+)bps/); if (bpsMatch){ const bps = parseInt(bpsMatch[1],10); const newState = getStrokeSpeedAndDistance(bps); changeSpeed(newState); } else { const bpsMatch = data.value.match(/([1-9].+)ps/); if (bpsMatch){ const bps = parseInt(bpsMatch[1],10); const newState = getStrokeSpeedAndDistance(bps); changeSpeed(newState); } } } } else { // remove the next 3 lines sendRequest(api + "/hamp/stop", null, 'PUT',(response)=>{ console.log('stop', response); }); } } }); }; const mainWrapper = document.querySelector('.v-main__wrap'); // Create an observer instance linked to the callback function const wrapperObserver = new MutationObserver(mainWrapperCallback); // Start observing the target node for configured mutations wrapperObserver.observe(mainWrapper, { attributes: false, childList: true, subtree: true }); })();
But I can change things, if you have recommendations.
You really missed something, I'm not the one who made the tease. I just made a script, that controls your handy to the speed of the beat.. So no I can not shorten the tease.Achatius wrote: Sat Jan 08, 2022 8:30 am Would be great to shorten the tease. Every image is too long / there is a lack of input. It's just like fapping 30 seconds for a single sentence. And the first "hour" in a slow rhythm. A 10 Minute "impossible POT-Challenge" is good enough, where you have to have your orgasm at least at minute 7 or 8.