mirror of
				https://gitlab.com/MrFry/moodle-test-userscript
				synced 2025-04-01 20:22:48 +02:00 
			
		
		
		
	p2p functionality
This commit is contained in:
		| @@ -2,8 +2,9 @@ module.exports = { | ||||
|   env: { | ||||
|     browser: true, | ||||
|     es6: true, | ||||
|     node: true, | ||||
|     jest: true, | ||||
|   }, | ||||
|   parserOptions: { | ||||
|     ecmaVersion: 8, | ||||
|   }, | ||||
|   extends: ['eslint:recommended'], | ||||
|   globals: { | ||||
|   | ||||
							
								
								
									
										535
									
								
								stable.user.js
									
									
									
									
									
								
							
							
						
						
									
										535
									
								
								stable.user.js
									
									
									
									
									
								
							| @@ -46,7 +46,7 @@ | ||||
| // : Script header {{{ | ||||
| // ==UserScript== | ||||
| // @name         Moodle/Elearning/KMOOC test help | ||||
| // @version      2.1.3.15 | ||||
| // @version      2.1.4.0 | ||||
| // @description  Online Moodle/Elearning/KMOOC test help | ||||
| // @author       MrFry | ||||
| // @match        https://elearning.uni-obuda.hu/* | ||||
| @@ -72,6 +72,7 @@ | ||||
| // @match        https://v39.moodle.uniduna.hu/* | ||||
| // @match        https://mentok.net/* | ||||
| // @match        https://qmining.frylabs.net/* | ||||
| // @match        https://frylabs.net/* | ||||
| // @noframes | ||||
| // @run-at       document-start | ||||
| // @grant        GM_getResourceText | ||||
| @@ -83,16 +84,25 @@ | ||||
| // @grant        GM_openInTab | ||||
| // @grant        unsafeWindow | ||||
| // @license      GNU General Public License v3.0 or later | ||||
| // @supportURL   qmining.frylabs.net | ||||
| // @contributionURL qmining.frylabs.net | ||||
| // @namespace    https://qmining.frylabs.net | ||||
| // @updateURL    https://qmining.frylabs.net/moodle-test-userscript/stable.user.js?up | ||||
| // @supportURL   frylabs.net | ||||
| // @contributionURL frylabs.net | ||||
| // @namespace    https://frylabs.net | ||||
| // @updateURL    https://frylabs.net/moodle-test-userscript/stable.user.js?up | ||||
| // ==/UserScript== | ||||
| // : }}} | ||||
|  | ||||
| ;(function () { | ||||
|   // : ESLINT bs {{{ | ||||
|   // CONFIG | ||||
|   let originalServer = { host: 'frylabs.net', port: 443 } | ||||
|   const logElementGetting = false | ||||
|   const logEnabled = true | ||||
|   const motdShowCount = 5 // Ammount of times to show motd | ||||
|   let infoExpireTime = 60 * 5 // Every n seconds basic info should be (re)loaded from server | ||||
|   let p2pInfoExpireTime = 60 * 60 * 24 | ||||
|   const messageOpacityDelta = 0.1 | ||||
|   const minMessageOpacity = 0.2 | ||||
|  | ||||
|   // : ESLINT bs {{{ | ||||
|   // eslint-disable-line | ||||
|   // GM functions, only to disable ESLINT errors | ||||
|   /* eslint-disable  */ | ||||
| @@ -125,31 +135,21 @@ | ||||
|   // Devel vars | ||||
|   // ------------------------------------------------------------------------------ | ||||
|   // forcing pages for testing. unless you test, do not set these to true! | ||||
|   const isDevel = true | ||||
|   const isDevel = false | ||||
|   const forcedMatchString = isDevel ? 'default' : null | ||||
|   // only one of these should be true for testing | ||||
|   const forceTestPage = isDevel && false | ||||
|   const forceResultPage = isDevel && true | ||||
|   const forceResultPage = isDevel && false | ||||
|   const forceDefaultPage = isDevel && false | ||||
|   // ------------------------------------------------------------------------------ | ||||
|  | ||||
|   const logElementGetting = false | ||||
|   const logEnabled = true | ||||
|   const showErrors = true | ||||
|  | ||||
|   let serverAdress = getPeerUrl(originalServer) | ||||
|   let apiAdress = getPeerUrl(originalServer) + 'api/' | ||||
|   var addEventListener // add event listener function | ||||
|   let serverAdress = 'https://qmining.frylabs.net/' | ||||
|   let apiAdress = 'https://api.frylabs.net/' | ||||
|  | ||||
|   const motdShowCount = 5 /* Ammount of times to show motd */ | ||||
|   const messageOpacityDelta = 0.1 | ||||
|   const minMessageOpacity = 0.2 | ||||
|   let infoExpireTime = 60 * 5 // Every n seconds basic info should be loaded from server | ||||
|   var motd = '' | ||||
|   var lastestVersion = '' | ||||
|   var subjInfo | ||||
|   var uiShowing = true | ||||
|  | ||||
|   let uiShowing = getVal('uishowing') | ||||
|   // array, where elems are added to shadow-root, but its position should be at target. | ||||
|   var updatableElements = [] // { elem: ..., target: ... } | ||||
|   var elementUpdaterInterval = -1 | ||||
| @@ -158,8 +158,29 @@ | ||||
|   if (isDevel) { | ||||
|     warn('Moodle script running in developement mode!') | ||||
|     infoExpireTime = 1 | ||||
|     serverAdress = 'http://localhost:8080/' | ||||
|     apiAdress = 'http://localhost:8080/' | ||||
|     p2pInfoExpireTime = 1 | ||||
|     originalServer = { host: 'localhost', port: 8080 } | ||||
|     serverAdress = getPeerUrl(originalServer) | ||||
|     apiAdress = getPeerUrl(originalServer) + 'api/' | ||||
|     setVal('motdcount', 5) | ||||
|   } | ||||
|  | ||||
|   const peerToUseString = getVal('peerToUse') | ||||
|   var usingPeer = false | ||||
|   if (peerToUseString) { | ||||
|     try { | ||||
|       const peerToUse = JSON.parse(peerToUseString) | ||||
|  | ||||
|       if (peerToUse && peerToUse.host && peerToUse.port) { | ||||
|         const url = getPeerUrl(peerToUse) | ||||
|         debugLog('Using saved peer url: ' + url) | ||||
|         serverAdress = url | ||||
|         apiAdress = url + 'api/' | ||||
|         usingPeer = true | ||||
|       } | ||||
|     } catch (e) { | ||||
|       debugLog('peerToUse not JSON') | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   const currUrl = location.href.includes('file:///') | ||||
| @@ -171,8 +192,7 @@ | ||||
|   const huTexts = { | ||||
|     fatalError: | ||||
|       'Fatál error. Check console (f12). Kattints az üzenetre az összes kérdés/válaszért manuális kereséshez! (új böngésző tab-ban)', | ||||
|     consoleErrorInfo: | ||||
|       'Itteni hibák 100% a moodle hiba. Kivéve, ha oda van írva hogy script error ;) Ha ilyesmi szerepel itt, akkor olvasd el a segítség szekciót! https://qmining.frylabs.net/manual?scriptcmd', | ||||
|     consoleErrorInfo: `Itteni hibák 100% a moodle hiba. Kivéve, ha oda van írva hogy script error ;) Ha ilyesmi szerepel itt, akkor olvasd el a segítség szekciót! ${serverAdress}`, | ||||
|     freshStartWarning: | ||||
|       '<h1>Moodle teszt userscript:<h1><h3>1.5.0 verzió: a script mostantól XMLHTTP kéréseket küld szerver fele! Erre a userscript futtató kiegészítőd is figyelmeztetni fog! Ha ez történik, a script rendes működése érdekében engedélyezd (Always allow domain)! Ha nem akarod, hogy ez történjen, akkor ne engedélyezd, vagy a menüben válaszd ki a "helyi fájl használata" opciót!</h3> <h3>Elküldött adatok: minden teszt után a kérdés-válasz páros. Fogadott adatok: Az összes eddig ismert kérdés. Érdemes help-et elolvasni!!!</h3><h5>Ez az ablak frissités után eltűnik. Ha nem, akkor a visza gombbal próbálkozz.</h5>', | ||||
|     noResult: | ||||
| @@ -193,20 +213,24 @@ | ||||
|     dataEditorTitle: 'Adatbázisban lévő kérdések szerkesztése', | ||||
|     invalidPW: 'Hibás jelszó: ', | ||||
|     search: 'Keresés ...', | ||||
|     loading: 'Betöltés ...', | ||||
|     connecting: 'Csatlakozás: ', | ||||
|     login: 'Belépés', | ||||
|     newPWTitle: 'Új jelszó új felhasználónak', | ||||
|     pwRequest: 'Jelszó új felhasználónak', | ||||
|     noServer: 'Nem elérhető a szerver!', | ||||
|     tryingPeer: 'Csatlakozás: ', | ||||
|     noPeersOnline: 'Egy peer sem elérhető!', | ||||
|     peerTryingError: 'Hiba peerek keresése közben!', | ||||
|     usingpeer: `A script eredeti szervere megszűnt, vagy nem elérhető, így egy másik peert használ! Hogy továbbra is kapj frissítéseekt újra kell telepítened a scriptet. További infó: <a href="${serverAdress}faq?tab=newpeer">${serverAdress}faq?tab=newpeer</a>`, | ||||
|     pwHere: 'Jelszó ...', | ||||
|     noServerConsoleMessage: `Nem elérhető a szerver, vagy kis eséllyel kezeletlen hiba történt! Ha elérhető a weboldal, akkor ott meg bírod nézni a kérdéseket itt: ${serverAdress}legacy`, | ||||
|     noServerConsoleMessage: `Nem elérhető a szerver! Ha elérhető a weboldal, akkor ott meg bírod nézni a kérdéseket itt: ${serverAdress}allQuestions`, | ||||
|     unhandledErrorConsoleMessage: `Kezeletlen hiba történt! Ha elérhető a weboldal, akkor ott meg bírod nézni a kérdéseket itt: ${serverAdress}allQuestions`, | ||||
|     noParseableQuestionResult: | ||||
|       'A tesztben nem találhatók kérdések, amit fel lehet dolgozni, vagy hiba történt feldolgozásuk közben', | ||||
|     unableToParseTestQuestion: | ||||
|       'Hiba történt a kérdések beolvasása közben :/ Kattints az üzenetre a manuális kereséshez (új böngésző tab-ban)', | ||||
|     loadingAnswer: 'Válaszok betöltése ...', | ||||
|     reinstallFromCorrectSource: | ||||
|       'Scriptet nem a qmining weboldalról raktad fel. Könnyebb kezelhetőség szempontjából kérlek onnan telepítsd. <a href="https://qmining.frylabs.net/manual.html#scriptreinstall">Részletes leírás</a>', | ||||
|     reinstallFromCorrectSource: `Scriptet nem a qmining weboldalról raktad fel. Könnyebb kezelhetőség szempontjából kérlek onnan telepítsd. <a href="${serverAdress}">Részletes leírás</a>`, | ||||
|     versionUpdated: 'Verzió frissítve ', | ||||
|     newVersionAvaible: 'Új verzió elérhető: ', | ||||
|     userSpecifitMotdAvailable: | ||||
| @@ -1463,10 +1487,6 @@ | ||||
|  | ||||
|     log('Moodle / E-Learning script') | ||||
|     preventWindowClose() | ||||
|     console.log( | ||||
|       '%c Moodle / E-Learning script', | ||||
|       'font-weight: bold; font-size: 50px;color: yellow; text-shadow: 3px 3px 0 rgb(245,221,8) , 6px 6px 0 rgb(226,91,14) , 9px 9px 0 rgb(217,31,38) , 12px 12px 0 rgb(5,148,68) , 15px 15px 0 rgb(2,135,206) , 18px 18px 0 rgb(4,77,145) , 21px 21px 0 rgb(42,21,113)' | ||||
|     ) | ||||
|  | ||||
|     if (document.readyState === 'loading') { | ||||
|       document.addEventListener('DOMContentLoaded', Init) | ||||
| @@ -1694,13 +1714,13 @@ | ||||
|       SetupMenu() | ||||
|       ShowMenu() | ||||
|     } | ||||
|     ConnectToServer(AfterLoad) | ||||
|     ConnectToServer() | ||||
|   } | ||||
|  | ||||
|   function Auth(pw) { | ||||
|     post('login', { pw: pw, script: true }).then((res) => { | ||||
|       if (res.result === 'success') { | ||||
|         ConnectToServer(AfterLoad) | ||||
|         ConnectToServer() | ||||
|         clearAllMessages() | ||||
|         resetMenu() | ||||
|       } else { | ||||
| @@ -1722,44 +1742,137 @@ | ||||
|       elem.style.display = 'none' | ||||
|     }) | ||||
|     SafeGetElementById('infoMainDiv', (elem) => { | ||||
|       elem.innerText = texts.loading | ||||
|       elem.innerText = texts.connecting + getShortServerURL(serverAdress) | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   function ConnectToServer(cwith) { | ||||
|   function ConnectToServer() { | ||||
|     clearAllMessages() | ||||
|     GetXHRInfos() | ||||
|       .then((inf) => { | ||||
|         if (inf.result === 'nouser') { | ||||
|           NoUserAction() | ||||
|           return | ||||
|         } | ||||
|         lastestVersion = inf.version.replace(/\n/g, '') | ||||
|         motd = inf.motd | ||||
|         if (getUid() !== inf.uid) { | ||||
|         try { | ||||
|           if (inf.result === 'nouser') { | ||||
|             NoUserAction() | ||||
|             return | ||||
|           } | ||||
|           lastestVersion = inf.version.replace(/\n/g, '') | ||||
|           motd = inf.motd | ||||
|           if (getUid() !== inf.uid) { | ||||
|             setVal('userId', inf.uid) | ||||
|           } | ||||
|           subjInfo = inf.subjinfo | ||||
|           setVal('userId', inf.uid) | ||||
|           overlay.querySelector( | ||||
|             '#infoMainDiv' | ||||
|           ).innerText = `${subjInfo.subjects.toLocaleString()} tárgy, ${subjInfo.questions.toLocaleString()} kérdés. UID: #${getUid()}\n${getShortServerURL( | ||||
|             serverAdress | ||||
|           )}` | ||||
|           if (inf.unreads.length > 0) { | ||||
|             overlay.querySelector('#mailButton').innerText = '📬' | ||||
|           } | ||||
|  | ||||
|           getPeers().catch(() => warn('unable to get p2p info')) | ||||
|           AfterLoad() | ||||
|         } catch (e) { | ||||
|           warn(texts.unhandledErrorConsoleMessage) | ||||
|           warn(e) | ||||
|         } | ||||
|         subjInfo = inf.subjinfo | ||||
|         setVal('userId', inf.uid) | ||||
|         overlay.querySelector( | ||||
|           '#infoMainDiv' | ||||
|         ).innerText = `${subjInfo.subjects.toLocaleString( | ||||
|           'hu' | ||||
|         )} tárgy, ${subjInfo.questions.toLocaleString( | ||||
|           'hu' | ||||
|         )} kérdés.\nUser ID: ${getUid()}` | ||||
|         if (inf.unreads.length > 0) { | ||||
|           overlay.querySelector('#mailButton').innerText = '📬' | ||||
|         } | ||||
|         // FIXME: if cwith() throws an unhandled error it sais server is not avaible | ||||
|         cwith() | ||||
|       }) | ||||
|       .catch(() => { | ||||
|         NoServerAction() | ||||
|       .catch((e) => { | ||||
|         warn(texts.noServerConsoleMessage) | ||||
|         warn(e) | ||||
|         tryAnotherPeer() | ||||
|       }) | ||||
|   } | ||||
|  | ||||
|   async function tryAnotherPeer() { | ||||
|     SafeGetElementById('scriptMenuDiv', (elem) => { | ||||
|       elem.style.backgroundColor = 'red' | ||||
|     }) | ||||
|  | ||||
|     debugLog('Unable to connect to main server, trying peers') | ||||
|     try { | ||||
|       const lastp2pinfo = JSON.parse(getVal('lastp2pinfo')) | ||||
|       if ( | ||||
|         !lastp2pinfo || | ||||
|         (Array.isArray(lastp2pinfo) && lastp2pinfo.length === 0) | ||||
|       ) { | ||||
|         debugLog('No saved p2p info available!') | ||||
|         return | ||||
|       } | ||||
|       debugLog('Saved peers: ', lastp2pinfo) | ||||
|       const shuffledPeers = lastp2pinfo.sort(() => 0.5 - Math.random()) | ||||
|       if (usingPeer) { | ||||
|         debugLog('Added original server') | ||||
|         shuffledPeers.unshift(originalServer) | ||||
|       } | ||||
|  | ||||
|       let suitablePeer = null | ||||
|       let i = 0 | ||||
|       while (suitablePeer === null && i < shuffledPeers.length) { | ||||
|         const peer = shuffledPeers[i] | ||||
|         i++ | ||||
|  | ||||
|         const url = getPeerUrl(peer) | ||||
|         SafeGetElementById('infoMainDiv', (elem) => { | ||||
|           elem.innerText = texts.tryingPeer + getShortServerURL(url) | ||||
|         }) | ||||
|         debugLog('Trying ' + url) | ||||
|  | ||||
|         try { | ||||
|           const res = await head(url) | ||||
|           if (res.status === 401) { | ||||
|             debugLog(url + ' responded with ' + res.status) | ||||
|           } else if (res.status === 200) { | ||||
|             suitablePeer = peer | ||||
|           } | ||||
|         } catch (e) { | ||||
|           debugLog('Unable to connect!') | ||||
|         } | ||||
|       } | ||||
|  | ||||
|       if (suitablePeer) { | ||||
|         const url = getPeerUrl(suitablePeer) | ||||
|         debugLog('Found suitable peer with URL: ' + url + 'index: ' + i) | ||||
|         serverAdress = url | ||||
|         apiAdress = url + 'api/' | ||||
|         if ( | ||||
|           suitablePeer.host === originalServer.host && | ||||
|           suitablePeer.port === originalServer.port | ||||
|         ) { | ||||
|           setVal('peerToUse', undefined) | ||||
|           usingPeer = false | ||||
|         } else { | ||||
|           setVal('peerToUse', JSON.stringify(suitablePeer)) | ||||
|           usingPeer = true | ||||
|         } | ||||
|  | ||||
|         SafeGetElementById('scriptMenuDiv', (elem) => { | ||||
|           elem.style.backgroundColor = '#222426' | ||||
|         }) | ||||
|  | ||||
|         ConnectToServer() | ||||
|       } else { | ||||
|         SafeGetElementById('retryContainer', (elem) => { | ||||
|           elem.style.display = 'flex' | ||||
|         }) | ||||
|         SafeGetElementById('infoMainDiv', (elem) => { | ||||
|           elem.innerText = texts.noPeersOnline | ||||
|         }) | ||||
|         debugLog('None of the peers are online!') | ||||
|       } | ||||
|     } catch (e) { | ||||
|       SafeGetElementById('retryContainer', (elem) => { | ||||
|         elem.style.display = 'flex' | ||||
|       }) | ||||
|       SafeGetElementById('infoMainDiv', (elem) => { | ||||
|         elem.innerText = texts.peerTryingError | ||||
|       }) | ||||
|       warn('Error ocurred during trying to connect to peers!') | ||||
|       warn(e) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function NoUserAction() { | ||||
|     SafeGetElementById('scriptMenuDiv', (elem) => { | ||||
|       elem.style.backgroundColor = '#44cc00' | ||||
| @@ -1772,18 +1885,6 @@ | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   function NoServerAction() { | ||||
|     SafeGetElementById('scriptMenuDiv', (elem) => { | ||||
|       elem.style.backgroundColor = 'red' | ||||
|     }) | ||||
|     SafeGetElementById('infoMainDiv', (elem) => { | ||||
|       elem.innerText = texts.noServer | ||||
|     }) | ||||
|     SafeGetElementById('retryContainer', (elem) => { | ||||
|       elem.style.display = 'flex' | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   function VersionActions() { | ||||
|     FreshStart() | ||||
|   } | ||||
| @@ -1836,9 +1937,6 @@ | ||||
|     let timeout = null | ||||
|     const greetMsg = [] | ||||
|  | ||||
|     if (isNewVersionAvaible || newVersion || showMOTD) { | ||||
|       greetMsg.push(texts.scriptName + info().script.version) | ||||
|     } | ||||
|     if (isNewVersionAvaible) { | ||||
|       timeout = 5 | ||||
|       greetMsg.push(texts.newVersionAvaible + lastestVersion) | ||||
| @@ -1852,12 +1950,14 @@ | ||||
|       greetMsg.push(texts.motd + motd) | ||||
|       timeout = null | ||||
|     } | ||||
|     if (usingPeer) { | ||||
|       greetMsg.push(texts.usingpeer) | ||||
|     } | ||||
|     if (greetMsg.length > 0) { | ||||
|       greetMsg.unshift(texts.scriptName + info().script.version) | ||||
|     } | ||||
|  | ||||
|     ShowMessage( | ||||
|       greetMsg.join('\n'), | ||||
|  | ||||
|       timeout | ||||
|     ) | ||||
|     ShowMessage(greetMsg.join('\n'), timeout) | ||||
|   } | ||||
|  | ||||
|   // : }}} | ||||
| @@ -2167,6 +2267,8 @@ | ||||
|   } | ||||
|  | ||||
|   function getConvertedMessageNode(message) { | ||||
|     if (!message) return '' | ||||
|  | ||||
|     const messageNode = document.createElement('p') | ||||
|     const resultNode = document.createElement('p') | ||||
|     messageNode.innerHTML = message.replace(/\n/g, '</br>') | ||||
| @@ -2263,6 +2365,7 @@ | ||||
|       true | ||||
|     ) | ||||
|     uiShowing = !uiShowing | ||||
|     setVal('uishowing', uiShowing) | ||||
|   } | ||||
|  | ||||
|   function SetupMenu() { | ||||
| @@ -2315,6 +2418,7 @@ | ||||
|       width: width + 'px', | ||||
|       opacity: getVal(`${id}_opacity`), | ||||
|       cursor: funct ? 'pointer' : 'move', | ||||
|       display: uiShowing ? '' : 'none', | ||||
|     }) | ||||
|     if (funct) { | ||||
|       addEventListener(messageElem, 'click', funct) | ||||
| @@ -2517,7 +2621,14 @@ | ||||
|         result.msgContainer.child.leftSideDiv.child.matchPercent.elem.innerText = | ||||
|           isNaN(getCurrMsg().p) ? '' : getCurrMsg().p + '%' | ||||
|  | ||||
|         result.msgContainer.child.msgDiv.elem.innerText = getCurrMsg().m | ||||
|         if (isSimpleMessage) { | ||||
|           result.msgContainer.child.msgDiv.elem.replaceChildren() | ||||
|           result.msgContainer.child.msgDiv.elem.appendChild( | ||||
|             getConvertedMessageNode(getCurrMsg().m) | ||||
|           ) | ||||
|         } else { | ||||
|           result.msgContainer.child.msgDiv.elem.innerText = getCurrMsg().m | ||||
|         } | ||||
|       } catch (e) { | ||||
|         warn('Error in message updating') | ||||
|         warn(e) | ||||
| @@ -2545,6 +2656,8 @@ | ||||
|       const id = 'scriptMenuDiv' | ||||
|       scriptMenuDiv.setAttribute('id', id) | ||||
|       SetStyle(scriptMenuDiv, { | ||||
|         display: uiShowing ? 'flex' : 'none', | ||||
|         flexDirection: 'column', | ||||
|         width: '300px', | ||||
|         height: '90px', | ||||
|         position: 'fixed', | ||||
| @@ -2599,9 +2712,8 @@ | ||||
|           style: { | ||||
|             position: 'absolute', | ||||
|             display: 'inline', | ||||
|             bottom: '20px', | ||||
|             left: '5px', | ||||
|             bottom: '15px', | ||||
|             margin: '5px', | ||||
|             fontSize: '30px', | ||||
|             cursor: 'pointer', | ||||
|           }, | ||||
| @@ -2643,72 +2755,82 @@ | ||||
|             }, | ||||
|           }, | ||||
|         }, | ||||
|         infoContainer: { | ||||
|           id: 'infoMainDiv', | ||||
|           innerText: texts.loading, | ||||
|         statusContainer: { | ||||
|           style: { | ||||
|             color: '#ffffff', | ||||
|             margin: '5px 50px', | ||||
|             textAlign: 'center', | ||||
|           }, | ||||
|         }, | ||||
|         loginContainer: { | ||||
|           id: 'loginDiv', | ||||
|           style: { | ||||
|             display: 'none', | ||||
|             display: 'flex', | ||||
|             flexDirection: 'column', | ||||
|             justifyContent: 'center', | ||||
|             flex: 1, | ||||
|             margin: '0px 50px', | ||||
|           }, | ||||
|           children: { | ||||
|             loginInput: { | ||||
|               customElem: () => { | ||||
|                 const loginInput = document.createElement('input') | ||||
|                 loginInput.setAttribute('id', 'pwInput') | ||||
|                 loginInput.type = 'text' | ||||
|                 loginInput.placeholder = texts.pwHere | ||||
|                 SetStyle(loginInput, { | ||||
|                   width: '100%', | ||||
|                   textAlign: 'center', | ||||
|                 }) | ||||
|                 return loginInput | ||||
|               }, | ||||
|             }, | ||||
|             loginButton: { | ||||
|               innerText: texts.login, | ||||
|               style: buttonStyle, | ||||
|               onClick: () => { | ||||
|                 SafeGetElementById('pwInput', (elem) => { | ||||
|                   Auth(elem.value) | ||||
|                 }) | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
|         }, | ||||
|         retryContainer: { | ||||
|           id: 'retryContainer', | ||||
|           style: { | ||||
|             display: 'none', | ||||
|             justifyContent: 'center', | ||||
|           }, | ||||
|           children: { | ||||
|             retryButton: { | ||||
|               innerText: texts.retry, | ||||
|             infoContainer: { | ||||
|               id: 'infoMainDiv', | ||||
|               innerText: texts.connecting + getShortServerURL(serverAdress), | ||||
|               style: { | ||||
|                 position: '', | ||||
|                 padding: '0px 8px', | ||||
|                 border: '1px solid #333', | ||||
|                 borderRadius: '2px', | ||||
|                 color: '#ffffff', | ||||
|                 cursor: 'pointer', | ||||
|                 textAlign: 'center', | ||||
|               }, | ||||
|               onClick: () => { | ||||
|                 scriptMenuDiv.style.background = '#262626' | ||||
|                 SafeGetElementById('infoMainDiv', (elem) => { | ||||
|                   elem.innerText = texts.loading | ||||
|                 }) | ||||
|                 SafeGetElementById('retryContainer', (elem) => { | ||||
|                   elem.style.display = 'none' | ||||
|                 }) | ||||
|                 ConnectToServer(AfterLoad) | ||||
|             }, | ||||
|             loginContainer: { | ||||
|               id: 'loginDiv', | ||||
|               style: { | ||||
|                 display: 'none', | ||||
|               }, | ||||
|               children: { | ||||
|                 loginInput: { | ||||
|                   customElem: () => { | ||||
|                     const loginInput = document.createElement('input') | ||||
|                     loginInput.setAttribute('id', 'pwInput') | ||||
|                     loginInput.type = 'text' | ||||
|                     loginInput.placeholder = texts.pwHere | ||||
|                     SetStyle(loginInput, { | ||||
|                       width: '100%', | ||||
|                       textAlign: 'center', | ||||
|                     }) | ||||
|                     return loginInput | ||||
|                   }, | ||||
|                 }, | ||||
|                 loginButton: { | ||||
|                   innerText: texts.login, | ||||
|                   style: buttonStyle, | ||||
|                   onClick: () => { | ||||
|                     SafeGetElementById('pwInput', (elem) => { | ||||
|                       Auth(elem.value) | ||||
|                     }) | ||||
|                   }, | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|             retryContainer: { | ||||
|               id: 'retryContainer', | ||||
|               style: { | ||||
|                 display: 'none', | ||||
|                 justifyContent: 'center', | ||||
|               }, | ||||
|               children: { | ||||
|                 retryButton: { | ||||
|                   innerText: texts.retry, | ||||
|                   style: { | ||||
|                     position: '', | ||||
|                     padding: '0px 8px', | ||||
|                     border: '1px solid #333', | ||||
|                     borderRadius: '2px', | ||||
|                     color: '#ffffff', | ||||
|                     cursor: 'pointer', | ||||
|                   }, | ||||
|                   onClick: () => { | ||||
|                     scriptMenuDiv.style.background = '#262626' | ||||
|                     SafeGetElementById('infoMainDiv', (elem) => { | ||||
|                       elem.innerText = | ||||
|                         texts.connecting + getShortServerURL(serverAdress) | ||||
|                     }) | ||||
|                     SafeGetElementById('retryContainer', (elem) => { | ||||
|                       elem.style.display = 'none' | ||||
|                     }) | ||||
|                     ConnectToServer() | ||||
|                   }, | ||||
|                 }, | ||||
|               }, | ||||
|             }, | ||||
|           }, | ||||
| @@ -2801,6 +2923,24 @@ | ||||
|     log('------------------------------------------') | ||||
|   } | ||||
|  | ||||
|   function getShortServerURL(url) { | ||||
|     const maxlegnth = 30 | ||||
|     const shortUrl = url.replace('https://', '').replace('http://', '') | ||||
|     if (shortUrl.length <= maxlegnth) { | ||||
|       return shortUrl | ||||
|     } else { | ||||
|       return shortUrl.substring(0, maxlegnth - 3) + '...' | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function getPeerUrl(peer) { | ||||
|     let protocol = 'https://' | ||||
|     if (isDevel) { | ||||
|       let protocol = 'http://' | ||||
|     } | ||||
|     return protocol + peer.host + ':' + peer.port + '/' | ||||
|   } | ||||
|  | ||||
|   function getUid() { | ||||
|     return getVal('userId') | ||||
|   } | ||||
| @@ -2896,22 +3036,12 @@ | ||||
|     const now = new Date().getTime() | ||||
|     const lastCheck = getVal('lastInfoCheckTime') | ||||
|     if (!lastCheck) { | ||||
|       setVal('lastInfoCheckTime', now) | ||||
|       setVal('lastInfoCheckTime', 0) | ||||
|     } | ||||
|  | ||||
|     let lastInfo = { result: 'noLastInfo' } | ||||
|     try { | ||||
|       lastInfo = JSON.parse(getVal('lastInfo')) | ||||
|     } catch (e) { | ||||
|       if (showErrors) { | ||||
|         warn(e) | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     if ( | ||||
|       lastInfo.result !== 'success' || | ||||
|       now > lastCheck + infoExpireTime * 1000 | ||||
|     ) { | ||||
|     if (now > lastCheck + infoExpireTime * 1000) { | ||||
|       return new Promise((resolve, reject) => { | ||||
|         const url = | ||||
|           apiAdress + | ||||
| @@ -2923,11 +3053,11 @@ | ||||
|         Promise.all([get(url), get(apiAdress + 'hasNewMsg')]) | ||||
|           .then(([{ responseText: infos }, { responseText: hasNewMsg }]) => { | ||||
|             try { | ||||
|               setVal('lastInfoCheckTime', now) | ||||
|               const infosObj = JSON.parse(infos) | ||||
|               const hasNewMsgsObj = JSON.parse(hasNewMsg) | ||||
|               const merged = Object.assign({}, infosObj, hasNewMsgsObj) | ||||
|               setVal('lastInfo', JSON.stringify(merged)) | ||||
|               setVal('lastInfoCheckTime', now) | ||||
|               resolve(merged) | ||||
|             } catch (e) { | ||||
|               log('Errro paring JSON in GetXHRInfos') | ||||
| @@ -2944,6 +3074,7 @@ | ||||
|     } else { | ||||
|       return new Promise((resolve, reject) => { | ||||
|         try { | ||||
|           lastInfo = JSON.parse(getVal('lastInfo')) | ||||
|           resolve(lastInfo) | ||||
|         } catch (e) { | ||||
|           log('Errro paring JSON in GetXHRInfos, when using old data!') | ||||
| @@ -2954,12 +3085,102 @@ | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function updateP2pData(newData) { | ||||
|     const lastp2pinfo = getVal('lastp2pinfo') | ||||
|     const oldPeers = lastp2pinfo ? JSON.parse(lastp2pinfo) : [] | ||||
|     const merged = newData.reduce((acc, peer) => { | ||||
|       const peerAlreadyExists = acc.find((existingPeer) => { | ||||
|         const p1 = peer.host + ':' + peer.port | ||||
|         const p2 = existingPeer.host + ':' + existingPeer.port | ||||
|         return p1 === p2 | ||||
|       }) | ||||
|  | ||||
|       if (!peerAlreadyExists) { | ||||
|         peer.added = new Date().getTime() | ||||
|         return [peer, ...acc] | ||||
|       } | ||||
|  | ||||
|       return acc | ||||
|     }, oldPeers) | ||||
|     return merged | ||||
|   } | ||||
|  | ||||
|   function getPeers() { | ||||
|     const now = new Date().getTime() | ||||
|     const lastCheck = getVal('lastp2pchecktime') | ||||
|     if (!lastCheck) { | ||||
|       setVal('lastp2pchecktime', 0) | ||||
|     } | ||||
|  | ||||
|     let lastp2pinfo = {} | ||||
|  | ||||
|     if (now > lastCheck + p2pInfoExpireTime * 1000) { | ||||
|       return new Promise((resolve, reject) => { | ||||
|         const url = apiAdress + 'p2pinfo' | ||||
|  | ||||
|         get(url) | ||||
|           .then(({ responseText: p2pinfo }) => { | ||||
|             try { | ||||
|               const p2pinfoObj = updateP2pData(JSON.parse(p2pinfo).myPeers) | ||||
|               setVal('lastp2pinfo', JSON.stringify(p2pinfoObj)) | ||||
|               setVal('lastp2pchecktime', now) | ||||
|               resolve(p2pinfoObj) | ||||
|             } catch (e) { | ||||
|               log('Errro paring JSON in getPeers') | ||||
|               log(p2pinfo) | ||||
|               log(e) | ||||
|               reject(e) | ||||
|             } | ||||
|           }) | ||||
|           .catch((e) => { | ||||
|             log('Info get Error', e) | ||||
|             reject(e) | ||||
|           }) | ||||
|       }) | ||||
|     } else { | ||||
|       return new Promise((resolve, reject) => { | ||||
|         try { | ||||
|           lastp2pinfo = JSON.parse(getVal('lastp2pinfo')) | ||||
|           resolve(lastp2pinfo) | ||||
|         } catch (e) { | ||||
|           log('Errro paring JSON in GetXHRInfos, when using old data!') | ||||
|           log(e) | ||||
|           reject(e) | ||||
|         } | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function head(url) { | ||||
|     return new Promise((resolve, reject) => { | ||||
|       xmlhttpRequest({ | ||||
|         method: 'HEAD', | ||||
|         url: url, | ||||
|         crossDomain: true, | ||||
|         timeout: 5 * 1000, | ||||
|         ontimeout: () => { | ||||
|           reject(new Error('HEAD request timed out')) | ||||
|         }, | ||||
|         onload: function (response) { | ||||
|           resolve(response) | ||||
|         }, | ||||
|         onerror: (e) => { | ||||
|           reject(e) | ||||
|         }, | ||||
|       }) | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   function get(url) { | ||||
|     return new Promise((resolve, reject) => { | ||||
|       xmlhttpRequest({ | ||||
|         method: 'GET', | ||||
|         url: url, | ||||
|         crossDomain: true, | ||||
|         timeout: 15 * 1000, | ||||
|         ontimeout: () => { | ||||
|           reject(new Error('GET request timed out')) | ||||
|         }, | ||||
|         xhrFields: { withCredentials: true }, | ||||
|         headers: { | ||||
|           'Content-Type': 'application/json', | ||||
| @@ -2984,6 +3205,10 @@ | ||||
|         method: 'POST', | ||||
|         url: url, | ||||
|         crossDomain: true, | ||||
|         timeout: 30 * 1000, | ||||
|         ontimeout: () => { | ||||
|           reject(new Error('POST request timed out')) | ||||
|         }, | ||||
|         xhrFields: { withCredentials: true }, | ||||
|         data: message, | ||||
|         headers: { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user