- // ==UserScript==
- // @name Omni Tools
- // @namespace http://tampermonkey.net/
- // @version 1.4.1
- // @description ;)
- // @author You
- // @match https://omni.top-academy.ru/*
- // @icon https://www.google.com/s2/favicons?sz=64&domain=top-academy.ru
- // @grant none
- // @license MIT
- // ==/UserScript==
- var Version = "1.4.1";
- var CurrentHomeworks=null;
- var CanOpenImage=true;
- var UpdateFounded=false;
- var TeacherLogin = null;
- let FetchesCount = 0;
- let URLWaitingList = [];
-
- function FeedbackAi(){
- //Список моделей на сайте
- let AINameList = [
- 'OpenChat 3.5 (Recommended)',
- 'SnowFlake (Recommended)',
- 'Mistral 7B',
- 'Llama 3 8B',
- 'RWKV v5 3B AI Town',
- 'Capybara 7B',
- 'Gemma 7B',
- 'MythoMist 7B']
- //Список используемых нейросетей
- let AIProvidesList = [
- 'openchat/openchat-7b:free',
- 'snowflake/snowflake-arctic-instruct',
- 'mistralai/mistral-7b-instruct:free',
- 'meta-llama/llama-3-8b-instruct:free',
- 'recursal/rwkv-5-3b-ai-town',
- 'nousresearch/nous-capybara-7b:free',
- 'google/gemma-7b-it:free',
- 'gryphe/mythomist-7b:free']
-
- //Функция отправки запроса с ожиданием ответа
- function sendRequest(method, url, senddata) {
- try{
- return new Promise((resolve, reject) => {
- fetch("https://openrouter.ai/api/v1/chat/completions", {
- method: "POST",
- headers: {
- "Authorization": `Bearer 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`,
- "HTTP-Referer": `https://docs.google.com/`,
- "Content-Type": "application/json"
- },
- body: JSON.stringify({
- "model": senddata.ai_model,
- "messages": [
- {"role": "user", "content": senddata.promt},
- ],
- })
- })
- .then(response => {
- if (!response.ok) {
- throw new Error(`HTTP error! status: ${response.status}`);
- }
- return response.json();
- })
- .then(data => resolve(data["choices"][0]["message"]["content"]))
- .catch(error => reject(error));
- });
- } catch(e){alert(e)}
- }
-
-
-
- let feedbackareas = document.querySelectorAll('textarea.textarea-rev')//Поиск всех textarea для подстановки текста из ИИ
- let stundentinfodiv = document.querySelectorAll('.col-md-12 .col-md-6:nth-child(1)')//Поиск div с описанием студента
-
- while (document.getElementById('AIButton') !== null){document.getElementById('AIButton').remove()}//Это очищает все созданные кнопки
- while (document.getElementById('AIPromt') !== null){document.getElementById('AIPromt').remove()}//Это очищает все созданные поля промтов
-
- function PromtPrepare(buttonPosition){
- let informationdiv = stundentinfodiv[buttonPosition]//Получение div под номером buttonPosition из списка
- let information = informationdiv.querySelectorAll('p')//Получение данных об ученике
-
- let Grade = Math.round(Number(information[4].textContent.replace('Успеваемость: ',''))/120*1000)//Конвертация успреваемости в проценты (я знаю что этот расчёт просто имба)
- if (Grade !== NaN && Grade !== null){
- let PromtText = 'Привет! Я преподаватель в колледже и мне нужно оставить простой и краткий отзыв для ученика, желательно, не более 2 предложений. Прошу тебя помочь с написанием отзыва. Ниже приведена небольшая информация об ученике. Полное имя ученика: '+information[5].textContent.replace('ФИО: ','')+', средняя посещаемость ученика: '+information[3].textContent.replace('Посещаемость: ','')+', средняя успеваемость:'+Grade+'%. (Предмет:'+(information[6].textContent.replace('Предмет:',''))+'). Будет замечательно если ты допустишь как можно меньше грамматических ошибок';
- return PromtText
- } else {
- return false
- }
- }
-
-
-
-
- function AskAI(i){
- let pressedButton = document.querySelector('.AIButtonAsk'+i)//Поиск нажатой кнопки
- let informationdiv = stundentinfodiv[i]//Поиск требуемого div из списка
- let promt = informationdiv.querySelector('textarea').value//Получение textarea из полученного div и его значения
- let choiced_model_number = AINameList.indexOf(document.getElementById('AISelection').value)//Получение выбранной модели
- pressedButton.textContent = 'Генерация отзыва...'
- pressedButton.disabled='true'
- sendRequest('POST', 'https://omnixtended.loca.lt/askAi', {promt: promt, ai_model:AIProvidesList[choiced_model_number]}).then(res => {
- feedbackareas[i].value = res;
- pressedButton.textContent = 'Сгенерировать заново'
- pressedButton.style.border='none'
- pressedButton.disabled = false;
- }).catch(err=> {
- console.error(err)
- pressedButton.textContent = 'Произошла ошибка :(';
- pressedButton.style.border='solid 2px red'
- pressedButton.disabled = false;
- })
- }
-
- //Для каждого ученика создаётся своя кнопка и поле с промптом
- for (let i = 0; i<feedbackareas.length; i++){
- //Создание кнопки с вызовом генерации
- let AIButton = document.createElement('button')
- AIButton.id='AIButton'
- AIButton.textContent='Генерация отзыва с помозью AI'
- AIButton.style='margin: 10px 0px 0px 0px; width: 100%'
- AIButton.className= 'waves-effect waves-light btn md-button md-ink-ripple AIButtonAsk'+i
- AIButton.addEventListener('click', function() {
- AskAI(i)
- })
-
-
- //Создание поля с промптом
- let AIPromt = document.createElement('textarea')
- AIPromt.id="AIPromt"
- AIPromt.style="width: 100%; height: 60px; border-radius: 10px; font-size: smaller"
- AIPromt.placeholder="Описание студента для нейросети";
-
- //Заспавнить кнопку после поля ввода
- feedbackareas[i].parentElement.appendChild(AIButton)//Можно использовать parentElement.appendChild вместо after
- //Заспавнить промпт-поле после информации об ученике
- stundentinfodiv[i].appendChild(AIPromt)
- let finalPromt = PromtPrepare(i)//Создание и вставка заготовленного промта для этого ученика
- AIPromt.value = finalPromt
- }
-
- if(document.getElementById('AISelection') !== null) {document.getElementById('AISelection').remove()}//Сброс выбора поля модельки нейросети при перезапуске
- //Создание выпадающего меню
- let AISelection = document.createElement('select')
- AISelection.id='AISelection'
- AISelection.style='margin: 10px; padding: 4px; border-radius: 5px;'
- let selectionInner='';
- for (let h = 0; h<AINameList.length; h++){
- //Добавлениее списка доступных нейронок в выпадающее меню
- selectionInner+='<option>'+AINameList[h]+'</option>'
- }
- //Применение
- AISelection.innerHTML=selectionInner;
- document.querySelector('span.reviews-container').before(AISelection)
-
- //Создание кнопки перезапуска (нужна была когда я начинал делать этот код, но сейчас просто фишка)
- if (document.getElementById('AIReload') !== null){document.getElementById('AIReload').remove()}
- let AIReload = document.createElement('button')
- AIReload.id="AIReload";
- AIReload.className = 'waves-effect waves-light btn md-button md-ink-ripple'
- AIReload.style='position: absolute; top: 0px; width: fit-content; right: 10px'
- AIReload.textContent = 'Перезапустить AITools';
- AIReload.addEventListener('click', function() {
- FeedbackAi()//Вызвать эту функцию заново
- })
- document.querySelector('span.reviews-container').appendChild(AIReload)
- }
- function checkFeedbackOpened(){
- if(document.querySelector('md-dialog.reviews-modal.reviews-modal-comments.layout-padding') !== null && document.getElementById('AIButton') === null){
- setTimeout(FeedbackAi, 1000);
- }
- }
-
-
-
-
- function SendPacket(URL, Type, JSONVals){
- return new Promise((resolve, reject) => {
-
- const xhr = new XMLHttpRequest();
- xhr.open(Type, URL);
- xhr.setRequestHeader('authority', 'msapi.top-academy.ru');
- xhr.setRequestHeader('method', 'POST');
- xhr.setRequestHeader('path', '/api/v2/auth/login');
- xhr.setRequestHeader('scheme', 'https');
- xhr.setRequestHeader('Accept', 'application/json, text/plain, */*');
- xhr.setRequestHeader('Accept-Language', 'ru_RU, ru');
- xhr.setRequestHeader('UIRequestData', TeacherLogin);
-
- xhr.onreadystatechange = () => {
- if (xhr.readyState === XMLHttpRequest.DONE) {
- if (xhr.status >= 200 && xhr.status < 300) {
- resolve(xhr.responseText);
- } else {
- reject(xhr.statusText);
- }
- }
- };
- xhr.onerror = () => reject(xhr.statusText);
-
- if (URL.indexOf("teacherTools") >= 0) {FetchesCount += 1;}
- if (JSONVals!==null) {
- xhr.setRequestHeader('Content-Type', 'application/json');
-
- let requestBody = JSONVals;
- if (typeof JSONVals === 'string') {
- requestBody = JSON.parse(JSONVals);
- }
- xhr.send(JSON.stringify(requestBody));
- } else {
- xhr.send();
- }
-
- });
-
- }
- window.SendPacket = SendPacket;
-
- function CreateFullscreenViewAPI(){
- var FullscreenView = document.createElement('div');
- FullscreenView.id="FillScreenViewer"
- FullscreenView.innerHTML=`
- <style>
- img#FullscreenImg { max-width: 100%; max-height: 100%; height: 80% !important; object-fit: cover; transition: all 1s;transform: translate(-50%, -50%);left: 50%;top: 50%;position: relative;height: auto;border-radius: 20px;z-index: 9000;display: block;-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;}
- img#FullscreenImg:hover { height: 97% !important; }
- .imgActiveImage{ transition: all 1s; border-radius: 20px; width: 100%; max-height: 100px; object-fit: cover; cursor: pointer; }
- .imgActiveImage:hover{ max-height: 150px; }
- div#FullscreenView {width: 100%; height: 0%; background: #252525de; position: absolute; transition: all .6s; top: 0px; z-index: 102; display: none; }
- </style>
- <div id="FullscreenView" onClick="window.CloseImageOnFullscreen()">
- <img id="FullscreenImg">
-
- </div>`;
- document.querySelector("body").after(FullscreenView)
- }
-
- function IsHomeWorksOpened(){
- return document.querySelectorAll("#myDialog.home_work_modal md-dialog").length > 0 // Применить скрипт если окно открылось
- }
-
- function CreateStyleIfNotExists(name, content) {
- if (document.getElementById(name) === null) {
- let style = document.createElement('style')
- style.textContent = content;
- style.id = name;
- document.body.appendChild(style)
- }
- }
-
-
- function DisplayRender(res, urlToHomework, placement) {
- CreateStyleIfNotExists('hwPreview', `
- #myDialog.home_work_modal .hw-md_item {width: 50%; position: relative}
- .hwPreview {width: 50%; position: absolute; left: 100%; top: 0%; height: 100%}
- .hwPreview {border-radius: 4px; width:100%; overflow: auto; border: solid 1px #383838; height: 100%; padding: 10px }
- .hwPreview img {max-width:100%; object-fit: contain; padding: 10px; border-radius: 6px}
- .hwPreview .pythonReader {white-space: pre;}
- .hwPreview *[style="min-height:56.7pt"] {display: none;}
- .md-dialog-container.ng-scope {height: 100% !important; position: fixed}
- .hw-md_single__select-mark {flex-wrap: wrap;}
- #myDialog.home_work_modal md-dialog {width: 1160px; left: 50%; transform: translateX(-50%)}
- `);
-
- if (document.querySelector(`.hwPreview[previewurl="${urlToHomework}"]`) !== null) {return}
-
- let content = '<span class="NoSucsessLoad"> Не удалось открыть файл (неизвестный тип файла) </span>'
-
- if (res.displayAs ==='html'){
- content = res.content.replace('href="', 'href="https:\\\\journalui.ru\\HwPreview\\fileReaderCache\\')
- } else if (res.displayAs ==='image'){
- content = res.content
- } else if (res.displayAs ==='pdf'){
- content = '<iframe class="pdfViewer" src="https:\\journalui.ru/homework/pdfPreview/'+res.AdditionalInfo+'"></iframe>'
- }
-
- let DisplayingDiv = document.createElement('div')
- DisplayingDiv.setAttribute('previewurl', urlToHomework)
- DisplayingDiv.className = 'hwPreview'
- DisplayingDiv.innerHTML = content;
- placement.after(DisplayingDiv)
- FetchesCount = FetchesCount - 1;
- URLWaitingList.splice(URLWaitingList.indexOf(urlToHomework), 1)
- if (res.displayAs ==='python') {
- DisplayingDiv.innerHTML = '';
- let span = document.createElement('span');
- span.className = 'pythonReader';
- span.textContent = res.content;
- DisplayingDiv.appendChild(span);
- }
-
-
- }
-
- function CreateRemoteViewAPI (urlToHomework, placement) {
- // Скоро загружу обнову на сервер, и запрос будет доступен по ссылке (пишу на момент теста на моём любимом 127.0.0.1:4890)
- // https://journalui.ru/teacherTools/hwPreviewTool
-
- // P.S. файлы по типу .py начну поддерживать скоро, обновление клиента (этого скрипта) не понадобиться (я надеюсь). А ещё добавлю пару проверок чтобы запрос был разрешён только с омни (код же открытый)
- // Дизайн наверное сделаю приятнее но чуть позже, сейчас времени нету
-
-
- if (document.querySelector(`.hwPreview[previewurl="${urlToHomework}"]`) === null && urlToHomework !== null && FetchesCount < 10 && URLWaitingList.indexOf(urlToHomework) == -1) {
- URLWaitingList.push(urlToHomework);
- if (localStorage.getItem(`hwPreviewTool:${urlToHomework}`) !== null) {
- let res = localStorage.getItem(`hwPreviewTool:${urlToHomework}`)
- console.log(`hwPreviewTool:${urlToHomework}`)
- res= JSON.parse(res);
- console.log(`Pulling ${urlToHomework} to storage...`);
- DisplayRender(res, urlToHomework, placement);
- } else {
-
-
-
-
- SendPacket("https://journalui.ru/teacherTools/hwPreviewTool", "POST", {url: urlToHomework}).then(res => {
- res = JSON.parse(res);
- console.log(`Saving ${urlToHomework} to storage...`);
- localStorage.setItem(`hwPreviewTool:${urlToHomework}`, JSON.stringify(res));
- DisplayRender(res, urlToHomework, placement);
- }).catch(err => {
- console.error(err);
- let DisplayingDiv = document.createElement('div')
- DisplayingDiv.setAttribute('previewurl', urlToHomework);
- DisplayingDiv.className = 'hwPreview'
- DisplayingDiv.textContent = 'Нам не удалось открыть этот файл'
- placement.after(DisplayingDiv) // Предотвращает повторный пинг сервера, убирая нагрузку
- FetchesCount = FetchesCount - 1;
- URLWaitingList.splice(URLWaitingList.indexOf(urlToHomework), 1)
- })
- }
- }
- }
-
- function ShowImageIfAvaiable(){
- if (IsHomeWorksOpened()){
- SendPacket("https://omni.top-academy.ru/homework/get-new-homeworks", "POST", null).then(data => {
- data = JSON.parse(data);
-
- CurrentHomeworks=data.homework.reverse();
- const downloadUrls = CurrentHomeworks.map(obj => obj.download_url_stud);
- const PreviewPlaces = document.querySelectorAll(".hw-md_single_stud-work__outer")
-
- if (document.getElementById("FillScreenViewer") === null){
- CreateFullscreenViewAPI();
- }
-
-
- for (var i=0; i < PreviewPlaces.length; i++){
- try{
- CreateRemoteViewAPI(downloadUrls[i], PreviewPlaces[i]);
- if (document.getElementById("ActiveImage"+i) !== null && document.getElementById("ActiveImage"+i).src !== downloadUrls[i]) {document.getElementById("ActiveImage"+i).src = downloadUrls[i]}
- if (document.getElementById("ActiveImage"+i) === null){
- var ImgPreviewDiv = document.createElement('div');
- ImgPreviewDiv.innerHTML=(`
- <img class='imgActiveImage' src=`+downloadUrls[i]+` id="ActiveImage`+i+`" onError='NotImage("ActiveImage`+i+`")' style="border-radius:20px; width:100%; cursor:pointer;" onClick="OpenImageOnFullscreen('`+downloadUrls[i]+`')">
- `);
- PreviewPlaces[i].after(ImgPreviewDiv)
- }
- }catch(e){console.error(e)}
- }
-
-
-
-
-
- })
- }
- setTimeout(ShowImageIfAvaiable, 1000)
- }
-
-
-
- function CheckUpdates(){
- fetch('https://gf.qytechs.cn/ru/scripts/487845-omni-image-preview', {method: 'GET'})
- .then(response => response.text())
- .then(data => {
- var versionRegex = /<dt class="script-show-version"><span>Версия<\/span><\/dt>\s+<dd class="script-show-version"><span>(.*?)<\/span><\/dd>/;
-
- var match = data.match(versionRegex);
-
- if (match) {
- var version = match[1];
- if (version!==Version && version!=="" && UpdateFounded==false){
- UpdateFounded=true;
- window.open('https://gf.qytechs.cn/ru/scripts/487845-omni-image-preview')
-
- } else {
- setTimeout(CheckUpdates, 1800000);
- }
- }
- })
- .catch(error => {});
- }
-
-
- function ProcessLoad(){
- if(IsHomeWorksOpened()){
- setTimeout(ShowImageIfAvaiable, 200)
- } else {
- setTimeout(ProcessLoad, 200)
- }
- }
-
- function AccountLog (){
- SendPacket('https://omni.top-academy.ru/profile/get-profile', 'POST', {}).then(res=>{
- res = JSON.parse(res);
- TeacherLogin = encodeURI(res.teach_info.fio_teach.toLowerCase().replace(" ","_"))
- console.log(TeacherLogin)
- })
- }
-
- (function() {
- setTimeout(CheckUpdates, 60000);
- setInterval(checkFeedbackOpened, 1000);//
- window.CloseImageOnFullscreen = function () {
- if (CanOpenImage){
- CanOpenImage=false;
- document.getElementById('FullscreenView').style.height='0%'
- setTimeout(function() {document.getElementById('FullscreenView').style.display='none'}, 510);
- setTimeout(CanOpenImage=true, 500);
- }
-
- };
- window.OpenImageOnFullscreen = function (URL) {
- if (CanOpenImage){
- CanOpenImage=false;
- document.getElementById('FullscreenView').style.display='block';
- setTimeout(function() {document.getElementById('FullscreenView').style.height='100%'}, 10);
- document.getElementById('FullscreenImg').src=URL;
- setTimeout(CanOpenImage=true, 500);
- }
- };
- window.NotImage = function (ID) {
- if (document.getElementById(ID) !== null){
- document.getElementById(ID).style.display="none";
- }
- };
- ProcessLoad();
- setTimeout(AccountLog, 1000)
- })();