Skip to content

Instantly share code, notes, and snippets.

@langheran
Last active June 17, 2023 00:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save langheran/dbfb77fde26f19b31279f828c7f32f6c to your computer and use it in GitHub Desktop.
Save langheran/dbfb77fde26f19b31279f828c7f32f6c to your computer and use it in GitHub Desktop.
C:\Users\Nisim Hurst\Utilities\Autohotkey\UserScripts\Speechify.user.js
// ==UserScript==
// @name Speechify.user.js
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://app.speechify.com/item/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
// @require http://www.phpied.com/files/rgbcolor/rgbcolor.js
// @grant GM_addStyle
// @grant GM_setClipboard
// @grant GM_notification
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_download
// ==/UserScript==
class AudioState {
constructor() {
// The AudioContext cannot be instanciated before action of the user.
// This is a small lazy trick.
var context;
this.getContext = function() {
if (typeof context === "undefined")
{
window.AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
}
return context;
};
this.videoAudioSrc;
this.midFilter;
this.gainNode;
this.bassFilter;
this.trebleFilter;
}
};
function getElementsByText(str, tag = 'a') {
return Array.prototype.slice.call(document.getElementsByTagName(tag)).filter(el => el.innerText.trim() === str.trim());
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function findall(selector) {
return document.querySelectorAll(selector);
}
function waitForElm(selector, isText=false) {
return new Promise(resolve => {
const elem = document.querySelector(selector);
if (elem) {
return resolve(elem);
}
const observer = new MutationObserver(mutations => {
const elem = document.querySelector(selector);
if (elem) {
resolve(elem);
observer.disconnect();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
});
}
function waitSelectVoice(count=99999999){
return new Promise(async resolve => {
let elem = getElementsByText('Select Voice', 'h3')[0];
while(!elem && count>0){
count--;
await sleep(500);
elem = getElementsByText('Select Voice', 'h3')[0];
}
resolve(elem);
});
}
function waitForSelectorElm(selector, count=99999999){
return new Promise(async resolve => {
let elem = findall(selector)[0];
while(!elem && count>0){
count--;
await sleep(500);
elem = findall(selector)[0];
}
resolve(elem);
});
}
function waitForTitle(){
return new Promise(async resolve => {
let elem = document.title;
while(!elem || /.*Listen to text with.*/.test(elem)){
await sleep(500);
elem = document.title;
}
resolve(elem);
});
}
const mouseClickEvents = ['mousedown', 'click', 'mouseup'];
function simulateMouseClick(element){
mouseClickEvents.forEach(mouseEventType =>
element.dispatchEvent(
new MouseEvent(mouseEventType, {
view: unsafeWindow,
bubbles: true,
cancelable: true,
buttons: 1
})
)
);
}
function toSeconds(timeStr) {
var l = (timeStr.match(/:/g) || []).length
if (l < 2){
timeStr = `0:${timeStr}`;
}
const [hours, minutes, seconds] = timeStr.split(':').map(Number);
return hours * 3600 + minutes * 60 + seconds;
}
(async function() {
'use strict';
GM_addStyle(".bg-glass-300 { background-color: black; }");
// debugger;
const title = await waitForTitle();
// alert(title);
const notificationDetails = {
title: title,
timeout: 2000
};
var shiftDown = false;
var ctrlDown = false;
var altDown = false;
var playbtn = undefined;
var playbtnC = undefined;
var isObservingPosition = false;
var isLoadingScrollPosition = false;
var prevWidth = GM_getValue('prevWidth' + title, false);
var prevHeight = GM_getValue('prevHeight' + title, false);
if (!prevWidth || prevWidth<630){
unsafeWindow.resizeTo(627,353);
unsafeWindow.moveTo(1136,638);
unsafeWindow.resizeTo(627,353);
}else{
unsafeWindow.resizeTo(1551,879);
unsafeWindow.moveTo(1136,638);
unsafeWindow.resizeTo(1551,879);
}
var state = new AudioState();
function doc_keyUp(e) {
switch (e.keyCode) {
case 16:
shiftDown = false;
break;
case 17:
ctrlDown = false;
break;
case 18:
altDown = false;
break;
default:
break;
}
}
function myConfirm(...args){
shiftDown = false;
ctrlDown = false;
altDown = false;
return confirm(...args);
}
async function doc_keyDown(e) {
switch (e.keyCode) {
case 16:
shiftDown = true;
break;
case 17:
ctrlDown = true;
break;
case 18:
altDown = true;
break;
case 67: //c
GM_setValue('playButton' + title, !GM_getValue('playButton' + title, false));
setPlayButtonVisitbility();
break;
case 65:
// debugger;
autoScroll();
break;
case 32: //space
e.preventDefault();
if (!playbtn){
ensurePlayBtn(true);
await sleep(500);
}
ensurePlayBtn(true);
//if(playbtn)
//{
if (document.activeElement!==playbtn){
simulateMouseClick(playbtn);
}
// playbtn.style.setProperty("display", "none", "important");
//}
break;
case 90:
debugger;
break;
case 73: //i
//set up color properties to iterate through
var colorProperties = ['color', 'background-color'];
//iterate through every element in reverse order...
// debugger;
var elems = [
$("iframe").contents().find("*"),
$("*")
];
for(let es of elems){
es.get().reverse().forEach((obj) => {
var color = null;
for (var prop in colorProperties) {
prop = colorProperties[prop];
//if we can't find this property or it's null, continue
console.log(obj);
if (!$(obj).css(prop)) continue;
console.log('aaa');
//create RGBColor object
color = new RGBColor($(obj).css(prop));
if (color.ok) {
//good to go, let's build up this RGB baby!
//subtract each color component from 255
$(obj).css(prop, 'rgb(' + (255 - color.r) + ', ' + (255 - color.g) + ', ' + (255 - color.b) + ')');
}
color = null; //some cleanup
}
});
}
break;
case 79: //o
var previousPosition = GM_getValue('savedPosition' + title, false);
var maxPosition = GM_getValue('maxPosition' + title, false);
if (!isObservingPosition || !maxPosition){
observePosition();
await sleep(1000);
previousPosition = GM_getValue('savedPosition' + title, false);
maxPosition = GM_getValue('maxPosition' + title, false);
}
if (altDown && isObservingPosition){
if(!previousPosition || myConfirm("Unset previous position @"+previousPosition)){
var pos = document.querySelector("div.min-h-screen.bg-pageBackground > div:nth-child(2) > div > div").scrollTop;
GM_setValue('savedPosition' + title, pos);
GM_setValue('maxPosition' + title, pos);
}
}
else
{
// var forwardbtn = document.querySelector("button.ml-2.flex.h-6.items-center.justify-center.text-glass-500");
// if (previousPosition && forwardbtn){
// while(currentPosition < previousPosition){
// await sleep(500);
// simulateMouseClick(forwardbtn);
// }
// }
if (shiftDown){
if (previousPosition){
document.querySelector("div.min-h-screen.bg-pageBackground > div:nth-child(2) > div > div").scrollTo(0,previousPosition);
}
}else{
if (maxPosition){
document.querySelector("div.min-h-screen.bg-pageBackground > div:nth-child(2) > div > div").scrollTo(0,maxPosition);
}
}
}
autoScroll();
break;
case 85: //u
navigator.clipboard.writeText(
window.location.href
)
alert('Copied!');
break;
// case 65:
// setVolume(1);
// break;
// case 66:
// setVolume(0.3);
// break;
default:
break;
}
}
document.addEventListener('keyup', doc_keyUp, false);
document.addEventListener('keydown', doc_keyDown, false);
let hideElements = [];
//const elem = await waitSelectVoice();
// // elem.parentElement.parentElement.parentElement.removeChild(elem.parentElement.parentElement);
// hideElements.push(elem.parentElement.parentElement);
// hideElements.forEach(item => {
// item.style.setProperty("display", "none", "important");
// });
// // debugger;
async function autoScroll(){
var settings = document.querySelector("div.fixed.bottom-9.right-5.z-2000.cursor-pointer > div > div")
if (settings){
simulateMouseClick(settings);
}
var autoscroll = document.querySelector("#toggleAutoscroll");
if (autoscroll){
if(autoscroll.checked){
simulateMouseClick(autoscroll);
}
simulateMouseClick(autoscroll);
}
if (settings){
simulateMouseClick(settings);
}
}
async function ensurePlayBtn(force=false){
if (!playbtn || force){
try{
// const playbtn=await waitForSelectorElm('*[aria-label^="Pause"]')
// .catch(error=>{
// console.error(error);
// });
playbtn=await Promise.race([waitForSelectorElm('button.css-1wqny6f', 2), waitForSelectorElm('button.css-1rrad81', 2)]);
// debugger;
}catch(err){console.log(err)}
}
}
async function ensurePlaying(){
if(!playbtn){
return;
}
try{
// await Promise.race([waitForHTML(playbtn, '<svg width="14" height="15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.548 15c.337 0 .623-.135.96-.328l9.808-5.67c.698-.412.942-.681.942-1.127 0-.446-.244-.715-.942-1.12L2.507 1.078c-.336-.193-.622-.32-.959-.32-.622 0-1.01.472-1.01 1.204v11.828C.539 14.52.927 15 1.549 15z" fill="currentColor"></path></svg>')]);
var html = '<svg width="12" height="16"';
var count = 999999;
await new Promise(async resolve => {
if (!playbtn){
resolve(false);
}
// debugger;
while(!playbtn.innerHTML.startsWith(html) && count>0){
await ensurePlayBtn(true);
count--;
await sleep(1000);
// console.log(playbtn.innerHTML);
// console.log(html);
// console.log(playbtn.innerHTML.startsWith(html));
}
// debugger;
resolve(true);
});
}catch(err){console.log(err)}
}
async function setPlayButtonVisitbility(){
let playbtnVisible = GM_getValue('playButton' + title, false);
await ensurePlayBtn(true);
if(playbtn)
{
try{
let container = playbtn.parentElement.parentElement.parentElement.parentElement;
// debugger;
if (container.className == 'container flex h-full items-center justify-center'){
// debugger;
container = container.parentElement;
}
unsafeWindow.localStorage.setItem('autoscroll', true);
setTimeout(
()=>{window.dispatchEvent(new Event('resize'));},
500
);
if (playbtnVisible)
{
container.style.setProperty("display", "block", "important");
document.querySelector("header").style.setProperty('display', 'block', 'important');
}
else
{
container.style.setProperty("display", "none", "important");
document.querySelector("header").style.setProperty('display', 'none', 'important')
}
}catch(e){}
var container;
try{
container=await waitForSelectorElm('.font-ABCDiatype>div>div>button');
container = container.parentElement.parentElement.parentElement;
if (playbtnVisible)
{
container.style.setProperty("display", "block", "important");
}
else
{
container.style.setProperty("display", "none", "important");
}
}catch(e){}
try{
container=await waitForSelectorElm('.PSPDFKit-Container');
container = container.parentElement;
if (playbtnVisible)
{
//container.style.setProperty("padding-left", "66px", "important");
}
else
{
//container.style.setProperty("padding-left", "0px", "important");
}
}catch(e){}
try{
findall('*[aria-label^="Open Intercom Messenger"]').forEach(function(item) {
item.style.setProperty("display", "none", "important");
});
}catch(e){}
}
}
setPlayButtonVisitbility();
setVolume();
const container0=await waitForSelectorElm('.bg-glass-200');
// const container=await waitForSelectorElm('.bg-glass-300>div:first-child');
// debugger;
// console.log(container);
// container.style.setProperty("height", "100%", "important");
// container.style.setProperty("top", "0px", "important");
// navigator.mediaDevices
// .selectAudioOutput()
// .then((device) => {
// console.log(`${device.kind}: ${device.label} id = ${device.deviceId}`);
// });
async function observePosition(){
if(isObservingPosition){
return;
}
var selector = "div.mt-1.flex.w-full.justify-between.pl-2.pr-2.text-glass-500 > span:nth-child(1)";
await waitForElm(selector);
// debugger;
await ensurePlayBtn(true);
// debugger;
await ensurePlaying();
// debugger;
const observer = new MutationObserver(mutations => {
const elem = document.querySelector(selector);
if (elem) {
// resolve(elem);
// observer.disconnect();
// GM_setValue('playPosition' + title, toSeconds(elem.innerText));
// debugger;
// currentPosition = toSeconds(elem.innerText);
var pos = document.querySelector("div.min-h-screen.bg-pageBackground > div:nth-child(2) > div > div").scrollTop;
isObservingPosition = true;
GM_setValue('playPosition' + title, pos);
var maxPos = GM_getValue('maxPosition' + title, 0);
if (maxPos <= pos){
GM_setValue('maxPosition' + title, pos);
}
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
sleep(100).then(async () => {
await ensurePlaying();
await sleep(1000);
if (isLoadingScrollPosition){
document.querySelector("div.min-h-screen.bg-pageBackground > div:nth-child(2) > div > div").scrollTo(0,GM_getValue('playPosition' + title, 0));
document.querySelector("div.min-h-screen.bg-pageBackground > div:nth-child(2) > div > div").scrollTo(0,GM_getValue('playPosition' + title, 0));
}
var x = unsafeWindow.innerWidth / 2;
var y = unsafeWindow.innerHeight / 2;
sleep(2000).then(async () => {
var reg = new RegExp("[\w]+","g");
var elem = document.elementFromPoint(x, y);
// debugger;
// simulateMouseClick(elem);
// try{
// $($(elem).parents().get().find(itm => $(itm).find("span").length))[0].click();
// }catch(e){}
// try{
// simulateMouseClick($($(elem).parents().get().find(itm => $(itm).find("span").length))[0]);
// }catch(e){}
while(elem && $(elem).parent()[0] && !$(elem).find('*[class^="SentencePlayer"]')[0]){
elem = $(elem).parent()[0];
}
elem = $(elem).find('*[class^="SentencePlayer"]')[0];
try{
elem.click();
}catch(e){}
try{
if (isLoadingScrollPosition){
simulateMouseClick(elem);
}
}catch(e){}
setPlayButtonVisitbility();
await sleep(500);
setPlayButtonVisitbility();
await sleep(500);
setPlayButtonVisitbility();
observePosition();
});
});
function setVolume() {
var videoVolume = GM_getValue('volume' + title, 0.1);
if (videoVolume)
{
window.postMessage({ type: "VOLUME", volume: videoVolume }, "*");
}
// detect available wheel event
var support = "onwheel" in document.createElement("div") ? "wheel" : // Modern browsers support "wheel"
document.onmousewheel !== undefined ? "mousewheel" : // Webkit and IE support at least "mousewheel"
"DOMMouseScroll"; // let"s assume that remaining browsers are older Firefox
document.addEventListener(support, function (event) {
if (!altDown){
return;
}
event.preventDefault();
var volume = GM_getValue('volume' + title, 0.1);
var volumeDelta = 2;
var deltaY = support == "mousewheel" ? event.wheelDelta : (event.deltaY || event.detail);
// Optimize volume change for touchpad
if (Math.abs(deltaY) < 2) {
volumeDelta = Math.max(Math.floor(Math.abs(deltaY)), 1)/100;
}
volume += (deltaY > 0 ? -volumeDelta : volumeDelta)/100;
// Limit the volume between 0 and 100
volume = Math.max(0, Math.min(1, volume));
window.postMessage({ type: "VOLUME", volume: volume }, "*");
GM_setValue('volume' + title, volume);
videoVolume = GM_getValue('volume' + title, 0.1);
// Prevent the page to scroll
event.preventDefault();
event.stopImmediatePropagation();
return false;
}, { passive: false });
}
unsafeWindow.addEventListener("resize", e => {
sleep(500).then(async () => {
const elem = await waitSelectVoice(4);
if (elem){
elem.parentElement.parentElement.style.setProperty("display", "none", "important");
}
var newWidth = window.innerWidth;
if (Math.abs(prevWidth-newWidth)>100)
{
prevWidth = newWidth;
GM_setValue('prevWidth' + title, prevWidth);
}
GM_setValue('prevHeight' + title, window.innerHeight);
});
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment