NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Insta.Ling Bot // @version 2022.06.03.01.r0.ge333da4 // @author ArcybiskupstwoPolskie // @description Self-learning Insta.Ling bot in javascript. // @match https://instaling.pl/ling2/html_app/app.php* // @namespace net.arcybiskupstwopolskie.instaling-bot // @license MIT // @updateURL https://openuserjs.org/meta/arkandevel/Insta.Ling_Bot.meta.js // @downloadURL https://openuserjs.org/install/arkandevel/Insta.Ling_Bot.user.js // ==/UserScript== const inj = document.createElement("script"); inj.textContent = ` var localdb_template = { "version": 1, "users": {} }; var dictionary_template = { "version": 2, "info": { "language_id": 0, "session_length": 0 }, "settings": {}, "translations": { "byId": {}, "byWord": {} } }; storage_id = "net.arcybiskupstwopolskie.instaling-bot"; function translations_save(dictionary) { localdb = JSON.parse(localStorage.getItem(storage_id)); localdb.users[currentChildId] = dictionary; localStorage.setItem(storage_id, JSON.stringify(localdb)); console.info("Dictionary saved."); } function translations_load() { localdb = JSON.parse(localStorage.getItem(storage_id)); if (localdb == null) { console.info("Initializing script database."); localdb = localdb_template; localStorage.setItem(storage_id, JSON.stringify(localdb_template)); } result = localdb.users[currentChildId]; if (result == null) { console.info("Initializing dictionary for child id: " + currentChildId); translations_save(dictionary_template); result = translations_load(); } console.info("Dictionary loaded."); return result } function suspend_point_store(suspend_point, dictionary) { if (suspend_point != null) { dictionary.suspend_point = suspend_point; } else { delete dictionary.suspend_point; } translations_save(dictionary); return 0 } // Load dictionary from storage api var dictionary = translations_load(); // Sleep function const sleep = (delay) => {return new Promise(resolve => setTimeout(resolve, delay))}; // Keeps how long a session will last var max_session_length = dictionary["info"]["session_length"]; var current_session_length = 0; // Stores if the script started with the session var started_with_session = false; // -- dict update // Stores if dictionary has been updated var dictionary_updated = false; function dictionary_updated_set() { if (!dictionary_updated) { dictionary_updated = true; console.log("The dictionary has changed."); } } function dictionary_updated_unset() { if (dictionary_updated) { dictionary_updated = false; console.log("The dictionary has been saved."); } } // -- done function emergency_save() { translations_save(dictionary); } // -- var bot_same_language = false; var bot_same_language_checked = false; function bot_same_language_check() { if (!bot_same_language_checked) { if (dictionary["info"]["language_id"] == 0) { console.log("Language id not set."); dictionary["info"]["language_id"] = currentLanguageId; dictionary_updated_set(); } // Check if dictionary language is the same as page bot_same_language = currentLanguageId == dictionary["info"]["language_id"]; bot_same_language_checked = true; } } // -- done // -- I'm bad at naming things. function bot_bug_log(message) { console.error(message + "\\nPlease report this to the maintainer."); } // -- done // -- Suspend / Resume functionality function suspend_point_create() { console.log("Creating suspend point"); suspend_point = { version: 1, started_with_session: started_with_session, current_session_length: current_session_length }; console.debug(suspend_point); dictionary.suspend_point = suspend_point; suspend_point_store(suspend_point, dictionary); console.info("Suspend point created."); } function suspend_point_load() { if (dictionary.suspend_point != undefined) { suspend_point = dictionary.suspend_point; console.debug(dictionary.suspend_point); started_with_session = suspend_point.started_with_session; current_session_length = suspend_point.current_session_length; console.info("Suspend point loaded."); return 0; } else { console.log("No suspend point found."); return 1; } } function suspend_point_delete() { if (dictionary.suspend_point != undefined) { suspend_point_store(null, dictionary); console.info("Suspend point deleted."); return 0; } else { console.log("No suspend point found."); return 1; } } // -- done // -- /* * 0 for visible * 1 for invisible * -1 for unknown */ function check_page_visibility(page_name) { let page = document.getElementById("allpage").children[page_name]; switch (page.style["display"]) { case "block": return 0 case "none": return 1 default: bot_bug_log(\`Page "\${page_name}" has an unknown display status: "\${start_page.style}"\`); return -1 } } // -- // -- Simple translator function bot_translate(id, word) { bot_same_language_check(); if (bot_same_language) { var result = dictionary.translations.byId[id]; if (result != undefined) { console.log('✔️ Word id "' + id+ '" means "' + result + '".'); return result } else { console.log('❌ Word id "' + id + '" was not found in the blob.'); } } var result = dictionary.translations.byWord[word]; if (result != undefined) { console.log('✔️ "' + word + '" means "' + result + '".'); return result } else { console.log('❌ "' + word + '" was not found in the blob.'); return "" } } function bot_autofill(id, translation) { textbox.insertIntoTextArea(bot_translate(id, translation)); } // -- done // -- Blob appending function dictionary_add(id, word, translation) { bot_same_language_check(); // Adding to id list if (bot_same_language && dictionary.translations.byId[id] != word) { console.log('Adding translation from word id "' + id + '" to "' + word + '".'); dictionary.translations.byId[id] = word; dictionary_updated_set(); // Adding to word list if (dictionary.translations.byWord[translation] != word) { console.log('Adding translation from "' + translation + '" to "' + word + '".'); dictionary.translations.byWord[translation] = word; } } if (started_with_session) { console.log(\`Words left: \${max_session_length - current_session_length}\`); } } // -- done // -- getNextWord_hook function getNextWord_hook(data) { if (data.maxWords != undefined) { if (max_session_length != data.maxWords) { console.log(\`The session length reported by InstaLing (\${data.maxWords}) is not the same as reported by the dictionary (\${max_session_length})\`); max_session_length = data.maxWords; dictionary.info.session_length = max_session_length; dictionary_updated_set(); } } switch (data.type) { case "marketing": console.log("I hate ads."); break; case "word": bot_autofill(data.id, data.translations); break; default: bot_bug_log("Insta.ling has sent an unknown data type."); console.log("Trying to autofill anyway."); bot_autofill(data.id, data.translations); } enable_paste(); } function getNextWord_fail_hook() { console.error("Failed to get next word!"); suspend_point_create(); } // -- Hook into getNextWord request function getNextWordRepeat() { // - Untouched \$.ajax({ url: '../server/actions/generate_next_word.php', type: "POST", dataType: 'json', data: {child_id:currentChildId, date:new Date().getTime() , repeat:repeat , start:start , end:end } }).done(function(data) { if (typeof data.id == 'undefined') { finishRepeatPageShow(data.summary); } else{ learningPageShow(data.id, data.speech_part, data.usage_example, data.translations, data.word, data.has_audio, data.audio_file_name, data.is_new_word, data.type == 'marketing'); // -- done getNextWord_hook(data); // - Untouched } }).error(function() { getNextWord_fail_hook(); alert('Błąd połączenia'); }); // -- done } function getNextWord() { // - Untouched \$.ajax({ url: '../server/actions/generate_next_word.php', type: "POST", dataType: 'json', data: {child_id:currentChildId, date:new Date().getTime()} }).done(function(data) { if (typeof data.id == 'undefined') { finishPageShow(data.summary); } else{ learningPageShow(data.id, data.speech_part, data.usage_example, data.translations, data.word, data.has_audio, data.audio_file_name, data.is_new_word, data.type == 'marketing'); // -- done getNextWord_hook(data); // - Untouched } }).error(function() { getNextWord_fail_hook(); alert('Błąd połączenia'); }); // -- done } // -- done // -- Hook into updateParams function updateParams_fail_hook() { console.error("Failed to send word!"); suspend_point_create(); } // -- Self-learning function updateParams(id, answer, show_grade, version) { // - Untouched \$.ajax({ url: '../server/actions/save_answer.php', type: "POST", dataType: 'json', data: {child_id:currentChildId, word_id: id, answer:answer, version:version} }).done(function(data) { // - done // Adds word (data.translations) to the database with it's translation (data.word) if (data.grade === 1) { current_session_length++; } else if (data.grade === 0) { // Do nothing } else { bot_bug_log("Insta.ling has sent an unknown grade."); } dictionary_add(data.id, data.word, data.translations); // - Untouched showAnswerPage(id, answer, data.usage_example, data.translations, data.grade, data.word, data.answershow, data.has_audio, show_grade); }).error(function() { updateParams_fail_hook(); alert('Błąd połączenia'); }); // - done } // -- done // -- Blob output function finishPageShow(summary) { // - Untouched \$('#answer').off('keyup'); \$('body').off('keyup'); \$('#return_mainpage').off('click'); \$("body").keyup(function(e){ if (e.keyCode == 13) { \$('body').off('keyup'); \$('.back').trigger('click'); } }); \$('#return_mainpage').click(function (){ \$('body').off('keyup'); \$('.back').trigger('click'); }); \$('#session_result').html(nl2br(summary)); \$('#grade_report_button').click(getGradeReport); \$('#loading').hide(); \$('.back').show(); \$('#finish_page').show(); // - done suspend_point_delete(); translations_save(dictionary); if (!dictionary_updated) { console.log("The word databse did not change."); } } // -- done function beforeunload_hook(event) { if (!dictionary.settings.onbeforereload_suspend_point_disabled) { if ( check_page_visibility("start_session_page") == 1 && check_page_visibility("finish_page") == 1 ) { suspend_point_create(); } else { console.info("Skipping suspend point creation."); } } if (dictionary_updated) { translations_save(dictionary); } return; } // -- async function session_start_check() { let exit_code = suspend_point_load(); console.info("Checking if the start page is visible."); let page_visible = false; for (let i = 0; i < 100; i++) { if (check_page_visibility("start_session_page") == 0) { console.log("Started with session."); page_visible = true; break; } else { if ((i + 1) % 50 == 0) { console.log(\`Tried \${i + 1} times.\`) } await sleep(0.5 * 100); } } if (page_visible) { if (exit_code === 0) { console.warn("The session saved in the suspend point seems to be finished."); suspend_point_delete(); } started_with_session = true; current_session_length = 0; } else { if (exit_code === 0) { console.log("Continuing from suspend point."); console.log(\`Words left: \${max_session_length - current_session_length}\`); } else { console.warn("The script did not start with the session."); } } } function enable_paste() { textbox = \$('input[id=answer]'); textbox.off("paste"); console.info("Copy-paste enabled."); } function delete_audio() { \$("#jquery_audioPlayer")[0].remove(); console.info("Audio player deleted."); } function beforeunload_setup() { console.debug("Adding event listener to beforeunload"); addEventListener("beforeunload", beforeunload_hook); } // -- done // -- Main function async function main() { let _ = session_start_check(); enable_paste(); if (dictionary.settings != undefined) { if (!dictionary.settings.sound_enable) { delete_audio(); } } else { console.log("No settings found in dictionary."); dictionary.settings = {}; dictionary_updated_set(); delete_audio(); } await _; delete _; beforeunload_setup(); console.info("Script ready!"); } // -- done // Run main main(); `; document.body.appendChild(inj);