NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name BetterSham // @namespace https://openuserjs.org/users/NotDave123456 // @version 0.1.2 // @description Adds some extra things to sham.chat such as auto reconnect and fake leave // @copyright 2019-2021, NotDave123456 (https://openuserjs.org/users/NotDave123456) // @license MIT // @author NotDave123456 // @updateURL https://openuserjs.org/meta/NotDave123456/BetterSham.meta.js // @downloadURL https://openuserjs.org/install/NotDave123456/BetterSham.user.js // @match https://sham.chat/* // @grant GM_setValue // @grant GM_getValue // @grant GM_addStyle // ==/UserScript== // Chnagelog // 0.1.2 // Fix: BetterSham settings modal now adhere site theme (function () { 'use strict' // Mutation observer watch for DOM change let observer = new MutationObserver(mutations => { for (let mutation of mutations) { // examine new nodes, is there anything to highlight for (let node of mutation.addedNodes) { // we track only elements, skip other nodes (e.g. text nodes) if (!(node instanceof HTMLElement)) continue if (node.innerHTML === 'More' && GM_getValue('reconnect')) { let timeLeft = 10 let countdownDom = document.querySelector('.countdownDom') let countdownTime = setInterval(() => { timeLeft-- countdownDom.textContent = timeLeft if (timeLeft <= 0) { clearInterval(countdownTime) countdownDom.textContent = GM_getValue('reconnectInv', 10) node.click() } }, parseInt(GM_getValue('reconnectInv', 10)) * 100) } } } }) // Start observer let demoElem = document.querySelector('body') observer.observe(demoElem, { childList: true, subtree: true }) // HTML for settings let settingModal = ` <div class="betterShamSettings modal fade in" id="betterShamSettings" role="dialog"> <div class="modal-dialog"> <div class="betterShamSettingsContent modal-content"> <div class="betterShamSettingsTitle modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title">BetterSham Settings</h4> </div> <div class="betterShamSettingsBody modal-body"> <label>Auto Reconnect Interval <input class="form-control settings text number" id="reconnectInv" type="number" value="${GM_getValue('reconnectInv', 10)}"/></label> <label>Socket Reconnect Interval <input class="form-control settings text number" id="socketInv" type="number" value="${GM_getValue('socketInv', 3)}"/></label> </div> <div class="betterShamSettingsFooter modal-footer"> <button type="button" class="btn btn-default settings button close" data-dismiss="modal" data-baction="saveSettings">Save & Quit</button> </div> </div> </div> </div> ` // HTML for the header let headerHTML = ` <div class="betterSham"> <p class="betterShamStatus">Socket connected: <span>${socket.connected}</span></p> <button class="btn btn-info betterShamButton betterShamButtonConnect" data-baction="connect">${socket.connected ? 'Disconnect' : 'Connect'}</button> <p class="betterShamTitle"><a data-baction="home">BetterSham</a></p> <button class="btn btn-info betterShamButton" type="button" data-toggle="modal" data-target="#betterShamSettings" data-baction="updateSettings">Settings</button> <div> <p class="onoff"> <input class="settigs checkbox" type="checkbox" name="reconnectCheck" id="reconnectCheck" ${GM_getValue('reconnect', false) ? 'checked' : ''}> <label for="reconnectCheck"></label> </p> Auto Reconnect: <span class="countdownDom">${GM_getValue('reconnectInv', 10)}</span> </div> </div> ` // Helper funaction to generate useble HTML let parseHTML = (html) => { let t = document.createElement('template') t.innerHTML = html return t.content.cloneNode(true) } // Setup page document.querySelector('.desktop').append(parseHTML(headerHTML)) document.querySelector('body').append(parseHTML(settingModal)) document.querySelector('#hats').remove() document.querySelector('#logo').remove() // Event listnener for button clicks document.addEventListener('click', (e) => { if (e.target.dataset.baction === 'home') go_home() if (e.target.dataset.baction === `connect`) { setTimeout(() => { document.querySelector('.betterShamButtonConnect').innerHTML = socket.connected ? 'Disconnect' : 'Connect' document.querySelector('.betterShamStatus>span').innerHTML = socket.connected }, parseInt(GM_getValue('reconnectInv', 10)) * 100) if (socket.connected) { socket.disconnect() } else { socket.connect() } } if (e.target.dataset.baction === 'updateSettings') { document.querySelector('#reconnectInv').value = GM_getValue('reconnectInv', 10) document.querySelector('#socketInv').value = GM_getValue('socketInv', 3) } if (e.target.dataset.baction === `saveSettings`) { GM_setValue('reconnectInv', document.querySelector('#reconnectInv').value) GM_setValue('socketInv', document.querySelector('#socketInv').value) } if (e.target.id === 'reconnectCheck') GM_setValue('reconnect', e.target.checked) }) // Update Socket UI setTimeout(() => { document.querySelector('.betterShamStatus>span').innerHTML = socket.connected document.querySelector('.betterShamButtonConnect').innerHTML = socket.connected ? 'Disconnect' : 'Connect' }, parseInt(GM_getValue('reconnectInv', 10)) * 100) toggle_night(meta.dark) // CSS inject GM_addStyle(` .betterSham { display: flex; flex-direction: row; align-items: center; justify-content: space-evenly; } .betterShamSettings {display:none} .betterShamTitle > a {cursor: pointer;} .list-group {height:calc(100vh - 11em)} `) })()