From 58a2fce2fe9952c5f787e6984587e33c66530e67 Mon Sep 17 00:00:00 2001
From: mrfry <mrfry@airmail.cc>
Date: Tue, 10 May 2022 12:01:59 +0200
Subject: [PATCH 1/3] information wrapper

---
 stable.user.js | 34 +++++++++++++++++++++++++++++-----
 1 file changed, 29 insertions(+), 5 deletions(-)

diff --git a/stable.user.js b/stable.user.js
index d07c281..5a2b6d8 100755
--- a/stable.user.js
+++ b/stable.user.js
@@ -116,7 +116,7 @@
   // Devel vars
   // ------------------------------------------------------------------------------
   // forcing pages for testing. unless you test, do not set these to true!
-  const isDevel = false
+  const isDevel = true
   const forcedMatchString = isDevel ? 'default' : null
   // only one of these should be true for testing
   const forceTestPage = isDevel && false
@@ -390,6 +390,26 @@
   }
 
   const questionNodeVariants = {
+    hasInformationText: {
+      criteria: () => {
+        const firstChild =
+          document.getElementsByTagName('form')[1].childNodes[0].childNodes[0]
+        if (!firstChild.className.includes('informationitem')) {
+          return false
+        }
+        const questionNodes = Array.from(
+          document.getElementsByTagName('form')[1].childNodes[0].childNodes
+        )
+        return questionNodes.length > 0
+      },
+      getter: () => {
+        return Array.from(
+          document.getElementsByTagName('form')[1].childNodes[0].childNodes
+        ).filter((node) => {
+          return !node.className.includes('informationitem')
+        })
+      },
+    },
     formFirst: {
       criteria: () => {
         const questionNodes = Array.from(
@@ -434,6 +454,7 @@
               `question nodes ${key} criteria was true, but result is an empty array!`
             )
           } else {
+            log(`Using question node getter variant: ${key}`)
             return true
           }
         }
@@ -720,6 +741,7 @@
               `result nodes ${key} criteria was true, but result is an empty array!`
             )
           } else {
+            log(`Using question node getter variant: ${key}`)
             return true
           }
         }
@@ -774,12 +796,13 @@
       if (getter.requirement(node)) {
         try {
           res = getter.getterFunction(node)
+          log(`[Question getter] Using ${key}`)
           return true
         } catch (e) {
-          log(`${key} failed`)
+          log(`[Question getter] ${key} failed`)
         }
       } else {
-        log(`${key} did not pass`)
+        log(`[Question getter] ${key} did not pass`)
       }
     })
 
@@ -803,6 +826,7 @@
           log('Answer or question array is empty, skipping question')
           resolve({ success: false })
         }
+        console.log({ node: node, questionPromises: questionPromises, answerPromises: answerPromises, possibleAnswers: possibleAnswers })
 
         Promise.all([
           Promise.all(questionPromises),
@@ -825,12 +849,12 @@
             resolve(result)
           })
           .catch((err) => {
-            warn('Error in getQuizFromNode()')
+            warn('Error in getQuizFromNode() (creating question)')
             warn(err)
             resolve({ success: false })
           })
       } catch (e) {
-        warn('Error in getQuizFromNode()!')
+        warn('Error in getQuizFromNode() (creating promises)')
         warn(e)
         warn(node)
       }

From 03c4064de851d71d12b3a739d6ef3625dd976c50 Mon Sep 17 00:00:00 2001
From: mrfry <mrfry@airmail.cc>
Date: Sun, 15 May 2022 10:23:45 +0200
Subject: [PATCH 2/3] log -> debuglog, information text getter fix

---
 stable.user.js | 71 +++++++++++++++++++++++++++-----------------------
 1 file changed, 38 insertions(+), 33 deletions(-)

diff --git a/stable.user.js b/stable.user.js
index 5a2b6d8..417aa1e 100755
--- a/stable.user.js
+++ b/stable.user.js
@@ -311,13 +311,13 @@
         }
       })
     } catch (e) {
-      log("Couldn't get images from result (old)")
+      debugLog("Couldn't get images from result (old)")
     }
   }
 
   function getCurrentSubjectName() {
     if (logElementGetting) {
-      log('getting current subjects name')
+      debugLog('getting current subjects name')
     }
     return document.getElementById('page-header').innerText.split('\n')[0] || ''
   }
@@ -370,7 +370,7 @@
           uid: getUid(),
         }
 
-        log('Sent data', sentData)
+        debugLog('Sent data', sentData)
         post('ask', sentData).then((results) => {
           removeLoadingMessage()
           ShowAnswers(
@@ -394,7 +394,7 @@
       criteria: () => {
         const firstChild =
           document.getElementsByTagName('form')[1].childNodes[0].childNodes[0]
-        if (!firstChild.className.includes('informationitem')) {
+        if (!firstChild || !firstChild.className.includes('informationitem')) {
           return false
         }
         const questionNodes = Array.from(
@@ -454,7 +454,7 @@
               `question nodes ${key} criteria was true, but result is an empty array!`
             )
           } else {
-            log(`Using question node getter variant: ${key}`)
+            debugLog(`Using question node getter variant: ${key}`)
             return true
           }
         }
@@ -741,7 +741,7 @@
               `result nodes ${key} criteria was true, but result is an empty array!`
             )
           } else {
-            log(`Using question node getter variant: ${key}`)
+            debugLog(`Using question node getter variant: ${key}`)
             return true
           }
         }
@@ -796,13 +796,13 @@
       if (getter.requirement(node)) {
         try {
           res = getter.getterFunction(node)
-          log(`[Question getter] Using ${key}`)
+          debugLog(`[Question getter] Using ${key}`)
           return true
         } catch (e) {
-          log(`[Question getter] ${key} failed`)
+          debugLog(`[Question getter] ${key} failed`)
         }
       } else {
-        log(`[Question getter] ${key} did not pass`)
+        debugLog(`[Question getter] ${key} did not pass`)
       }
     })
 
@@ -823,10 +823,9 @@
         const possibleAnswers = getPossibleAnswers(node)
 
         if (!answerPromises || !questionPromises) {
-          log('Answer or question array is empty, skipping question')
+          debugLog('Answer or question array is empty, skipping question')
           resolve({ success: false })
         }
-        console.log({ node: node, questionPromises: questionPromises, answerPromises: answerPromises, possibleAnswers: possibleAnswers })
 
         Promise.all([
           Promise.all(questionPromises),
@@ -1123,7 +1122,7 @@
         ],
       }
 
-      log(sentData)
+      debugLog(sentData)
       post('isAdding', sentData).then((res) => {
         ShowSaveQuizDialog(res.success, sentData, res.totalNewQuestions)
       })
@@ -1162,13 +1161,13 @@
         prevLength = kkerdesElements.length
         clearAllMessages()
         if (determineCurrentSite() === 'TEST') {
-          log('AVR: handling test')
+          debugLog('AVR: handling test')
           handleAVRQuiz(url)
         } else if (determineCurrentSite() === 'RESULT') {
-          log('AVR: handling result')
+          debugLog('AVR: handling result')
           HandleAVRResults(url)
         } else {
-          log('AVR: handling UI')
+          debugLog('AVR: handling UI')
           HandleUI()
         }
       }
@@ -1197,7 +1196,7 @@
         testUrl: url,
       }
 
-      log('Sent data', sentData)
+      debugLog('Sent data', sentData)
       post('ask', sentData).then((results) => {
         removeLoadingMessage()
         ShowAnswers(
@@ -1231,14 +1230,14 @@
 
   function getVideo() {
     if (logElementGetting) {
-      log('getting video stuff')
+      debugLog('getting video stuff')
     }
     return document.getElementsByTagName('video')[0]
   }
 
   function getVideoElement() {
     if (logElementGetting) {
-      log('getting video element')
+      debugLog('getting video element')
     }
     return document.getElementById('videoElement').parentNode
   }
@@ -1416,7 +1415,7 @@
           return false // TODO :insert real url
         },
         action: (url) => {
-          log('Handling canvas quiz')
+          debugLog('Handling canvas quiz')
           handleCanvasQuiz(url)
         },
       },
@@ -1425,7 +1424,7 @@
           return false // TODO :insert real url
         },
         action: (url) => {
-          log('Handling canvas results')
+          debugLog('Handling canvas results')
           HandleCanvasResults(url)
         },
       },
@@ -1434,7 +1433,7 @@
           return false // TODO :insert real url
         },
         action: (url) => {
-          log('Handling canvas default action')
+          debugLog('Handling canvas default action')
           HandleUI(url)
         },
       },
@@ -1462,7 +1461,7 @@
           return true // TODO :insert real url
         },
         action: (url) => {
-          log('Handling AVR default action')
+          debugLog('Handling AVR default action')
           handleAVRSite(url)
         },
       },
@@ -1477,7 +1476,7 @@
           )
         },
         action: () => {
-          log('Handling moodle quiz')
+          debugLog('Handling moodle quiz')
           handleMoodleQuiz()
         },
       },
@@ -1489,7 +1488,7 @@
           )
         },
         action: (url) => {
-          log('Handling moodle results')
+          debugLog('Handling moodle results')
           HandleMoodleResults(url)
         },
       },
@@ -1503,7 +1502,7 @@
           )
         },
         action: (url) => {
-          log('Handling moodle default action')
+          debugLog('Handling moodle default action')
           HandleUI(url)
         },
       },
@@ -1520,7 +1519,7 @@
           matcher.matchString === 'default' ||
           matcher.matchString.includes(forcedMatchString)
         ) {
-          log(`trying '${matcher.matchString}'`)
+          debugLog(`trying '${matcher.matchString}'`)
           if (matcher.testPage && matcher.testPage.match(url)) {
             matcher.testPage.action(url)
             return true
@@ -1877,7 +1876,7 @@
   //   }
   // }>
   function ShowAnswers(results) {
-    log(results)
+    debugLog(results)
     try {
       const answers = results.reduce((acc, res) => {
         const prepared = PrepareAnswers(res)
@@ -1971,9 +1970,9 @@
           sentData.subj = getCurrentSubjectName()
         } catch (e) {
           sentData.subj = 'NOSUBJ'
-          log('unable to get subject name :c')
+          debugLog('unable to get subject name :c')
         }
-        log('SENT DATA', sentData)
+        debugLog('SENT DATA', sentData)
         post('isAdding', sentData).then((res) => {
           ShowSaveQuizDialog(res.success, sentData, res.totalNewQuestions)
         })
@@ -2031,8 +2030,8 @@
         installSource: info().script.updateURL,
       })
     } catch (err) {
-      warn('Unexpected error while registering script')
-      log(err)
+      debugLog('Unexpected error while registering script')
+      debugLog(err)
     }
   }
 
@@ -2065,8 +2064,8 @@
           video.currentTime -= seekTime
         }
       } catch (err) {
-        log('Hotkey error.')
-        log(err.message)
+        debugLog('Hotkey error.')
+        debugLog(err.message)
       }
     })
     var toadd = getVideoElement()
@@ -2678,6 +2677,12 @@
     logHelper(console.log, ...arguments)
   }
 
+  function debugLog() {
+    if (isDevel) {
+      logHelper(console.log, ...arguments)
+    }
+  }
+
   function Exception(e, msg) {
     log('------------------------------------------')
     log(msg)

From 6213c1a7b8df238c81993ec4221cc5c0e8f9c917 Mon Sep 17 00:00:00 2001
From: mrfry <mrfry@airmail.cc>
Date: Sun, 15 May 2022 11:37:08 +0200
Subject: [PATCH 3/3] Variable depth nodes fix

---
 stable.user.js | 55 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 37 insertions(+), 18 deletions(-)

diff --git a/stable.user.js b/stable.user.js
index 417aa1e..556cfe6 100755
--- a/stable.user.js
+++ b/stable.user.js
@@ -116,11 +116,11 @@
   // 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
   // ------------------------------------------------------------------------------
 
@@ -218,8 +218,12 @@
 
   // : Basic processing helpers {{{
 
-  function getTextPromisesFromNode(node) {
-    return Array.from(node.childNodes).reduce((promises, elem) => {
+  function getTextPromisesFromNode(inputNode) {
+    const nodes = Array.from(inputNode.childNodes)
+      .map((x) => flattenNode(x))
+      .flat()
+
+    return nodes.reduce((promises, elem) => {
       let img = elem
       if (elem.tagName !== 'IMG') {
         const t = elem.tagName ? elem.getElementsByTagName('img') : []
@@ -246,17 +250,21 @@
       }
 
       if (img.tagName === 'IMG') {
-        promises.push(
-          new Promise((resolve) => {
-            digestMessage(getBase64Image(img)).then((res) => {
-              resolve({
-                type: 'img',
-                val: res,
-                node: img,
+        if (img.title) {
+          promises.push({ type: 'txt', val: img.title, node: elem })
+        } else {
+          promises.push(
+            new Promise((resolve) => {
+              digestMessage(getBase64Image(img)).then((res) => {
+                resolve({
+                  type: 'img',
+                  val: res,
+                  node: img,
+                })
               })
             })
-          })
-        )
+          )
+        }
       } else if (elem.tagName === undefined) {
         promises.push({ type: 'txt', val: elem.nodeValue, node: elem })
       } else {
@@ -267,6 +275,16 @@
     }, [])
   }
 
+  function flattenNode(node) {
+    if (node.childNodes && node.childNodes.length > 0) {
+      return Array.from(node.childNodes)
+        .map((x) => flattenNode(x))
+        .flat()
+    } else {
+      return node
+    }
+  }
+
   function makeTextFromElements(acc, item) {
     if (emptyOrWhiteSpace(item.val)) {
       return acc
@@ -1209,7 +1227,8 @@
         )
       })
     } catch (e) {
-      console.warn(e)
+      debugLog('Error in handleAVRQuiz')
+      debugLog(e)
     }
   }
 
@@ -1905,8 +1924,8 @@
         )
       }
     } catch (e) {
-      console.warn('Error showing answers')
-      console.warn(e)
+      debugLog('Error showing answers')
+      debugLog(e)
     }
   }
 
@@ -2410,8 +2429,8 @@
 
         result.msgContainer.child.msgDiv.elem.innerText = getCurrMsg().m
       } catch (e) {
-        console.warn('Error in message updating')
-        console.warn(e)
+        debugLog('Error in message updating')
+        debugLog(e)
       }
     }
     updateMessageText()