Adding ClientId; Adding Teacher Panel to start/end event recording
parent
fb3d497aa3
commit
53d1767a2d
|
@ -12,9 +12,6 @@ dist
|
||||||
# misc
|
# misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# config
|
|
||||||
config.json
|
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
"author": "Your Name",
|
"author": "Your Name",
|
||||||
|
|
||||||
"permissions": [
|
"permissions": [
|
||||||
"storage"
|
"storage",
|
||||||
|
"alarms"
|
||||||
],
|
],
|
||||||
|
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
"http://localhost:5000/*"
|
"http://localhost:5000/*",
|
||||||
|
"https://zpdai.rkg.lv/*"
|
||||||
],
|
],
|
||||||
|
|
||||||
"content_security_policy": {
|
"content_security_policy": {
|
||||||
|
|
62
options.js
62
options.js
|
@ -1,3 +1,5 @@
|
||||||
|
const browserAPI = typeof browser !== 'undefined' ? browser : chrome;
|
||||||
|
|
||||||
function saveOptions(event) {
|
function saveOptions(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const serverUrl = document.querySelector("#server-url").value;
|
const serverUrl = document.querySelector("#server-url").value;
|
||||||
|
@ -8,20 +10,62 @@ function saveOptions(event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
browser.storage.sync.set({ serverUrl, password }).then(() => {
|
if (typeof browser !== 'undefined') {
|
||||||
const status = document.querySelector("#status");
|
browserAPI.storage.sync.set({ serverUrl, password })
|
||||||
status.textContent = "Настройки сохранены!";
|
.then(() => {
|
||||||
setTimeout(() => (status.textContent = ""), 2000);
|
showStatus("Настройки сохранены!");
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Ошибка сохранения настроек:", error);
|
||||||
|
showStatus("Ошибка сохранения!", true);
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
browserAPI.storage.sync.set({ serverUrl, password }, () => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error("Ошибка сохранения настроек:", chrome.runtime.lastError);
|
||||||
|
showStatus("Ошибка сохранения!", true);
|
||||||
|
} else {
|
||||||
|
showStatus("Настройки сохранены!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreOptions() {
|
function restoreOptions() {
|
||||||
browser.storage.sync.get(["serverUrl", "password"]).then((result) => {
|
if (typeof browser !== 'undefined') {
|
||||||
const serverUrl = result.serverUrl || "http://localhost:5000/submit";
|
browserAPI.storage.sync.get(["serverUrl", "password"])
|
||||||
const password = result.password || "";
|
.then((result) => {
|
||||||
document.querySelector("#server-url").value = serverUrl;
|
updateFormFields(result);
|
||||||
document.querySelector("#password").value = password;
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Ошибка загрузки настроек:", error);
|
||||||
|
updateFormFields({});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
browserAPI.storage.sync.get(["serverUrl", "password"], (result) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error("Ошибка загрузки настроек:", chrome.runtime.lastError);
|
||||||
|
updateFormFields({});
|
||||||
|
} else {
|
||||||
|
updateFormFields(result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFormFields(result) {
|
||||||
|
document.querySelector("#server-url").value = result.serverUrl || "http://localhost:5000/submit";
|
||||||
|
document.querySelector("#password").value = result.password || "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStatus(message, isError = false) {
|
||||||
|
const status = document.querySelector("#status");
|
||||||
|
status.textContent = message;
|
||||||
|
status.style.color = isError ? "red" : "green";
|
||||||
|
setTimeout(() => {
|
||||||
|
status.textContent = "";
|
||||||
|
status.style.color = "";
|
||||||
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", restoreOptions);
|
document.addEventListener("DOMContentLoaded", restoreOptions);
|
||||||
|
|
167
src/borderify.js
167
src/borderify.js
|
@ -1,8 +1,39 @@
|
||||||
|
const browserAPI = typeof browser !== 'undefined' ? browser : chrome;
|
||||||
|
|
||||||
let serverUrl = "http://localhost:5000/submit";
|
let serverUrl = "http://localhost:5000/submit";
|
||||||
let password = "";
|
let password = "";
|
||||||
|
let clientId = null;
|
||||||
|
let isRecording = false;
|
||||||
|
let checkInterval = null;
|
||||||
|
let currentSessionId = null;
|
||||||
|
|
||||||
|
|
||||||
function loadSettings() {
|
function loadSettings() {
|
||||||
return browser.storage.sync.get(["serverUrl", "password"]).then((result) => {
|
return new Promise((resolve) => {
|
||||||
|
if (typeof browser !== 'undefined') {
|
||||||
|
browserAPI.storage.sync.get(["serverUrl", "password"])
|
||||||
|
.then((result) => {
|
||||||
|
processSettings(result);
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Ошибка загрузки настроек:", error);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
browserAPI.storage.sync.get(["serverUrl", "password"], (result) => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error("Ошибка загрузки настроек:", chrome.runtime.lastError);
|
||||||
|
} else {
|
||||||
|
processSettings(result);
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function processSettings(result) {
|
||||||
if (result.serverUrl) {
|
if (result.serverUrl) {
|
||||||
serverUrl = result.serverUrl;
|
serverUrl = result.serverUrl;
|
||||||
console.log("URL сервера загружен из настроек:", serverUrl);
|
console.log("URL сервера загружен из настроек:", serverUrl);
|
||||||
|
@ -10,30 +41,35 @@ function loadSettings() {
|
||||||
if (result.password) {
|
if (result.password) {
|
||||||
password = result.password;
|
password = result.password;
|
||||||
console.log("Пароль загружен из настроек.");
|
console.log("Пароль загружен из настроек.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClientId() {
|
||||||
|
if (typeof browser !== 'undefined') {
|
||||||
|
browserAPI.storage.sync.get("clientId")
|
||||||
|
.then((result) => {
|
||||||
|
if (result.clientId) {
|
||||||
|
clientId = result.clientId;
|
||||||
|
console.log("ID клиента загружен:", clientId);
|
||||||
} else {
|
} else {
|
||||||
return fetch(browser.runtime.getURL("config.json"))
|
generateAndSaveId();
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Ошибка загрузки config.json: ${response.statusText}`);
|
|
||||||
}
|
}
|
||||||
return response.json();
|
|
||||||
})
|
})
|
||||||
.then(config => {
|
.catch(console.error);
|
||||||
serverUrl = config.FLASK_SERVER_URL;
|
} else {
|
||||||
password = config.PASSWORD || password;
|
browserAPI.storage.sync.get("clientId", (result) => {
|
||||||
console.log("URL сервера успешно загружен:", serverUrl);
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error("Ошибка загрузки ID клиента:", chrome.runtime.lastError);
|
||||||
|
} else if (result.clientId) {
|
||||||
|
clientId = result.clientId;
|
||||||
|
console.log("ID клиента загружен:", clientId);
|
||||||
|
} else {
|
||||||
|
generateAndSaveId();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
|
||||||
console.error("Ошибка загрузки URL сервера:", error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSettings();
|
|
||||||
|
|
||||||
|
|
||||||
let clientId = null;
|
|
||||||
|
|
||||||
function generateUUID() {
|
function generateUUID() {
|
||||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
||||||
const r = (Math.random() * 16) | 0;
|
const r = (Math.random() * 16) | 0;
|
||||||
|
@ -42,20 +78,55 @@ function generateUUID() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
browser.storage.sync.get("clientId").then((result) => {
|
function generateAndSaveId() {
|
||||||
if (result.clientId) {
|
|
||||||
clientId = result.clientId;
|
|
||||||
console.log("ID клиента загружен:", clientId);
|
|
||||||
} else {
|
|
||||||
clientId = generateUUID();
|
clientId = generateUUID();
|
||||||
browser.storage.sync.set({ clientId }).then(() => {
|
if (typeof browser !== 'undefined') {
|
||||||
|
browserAPI.storage.sync.set({ clientId })
|
||||||
|
.then(() => console.log("ID клиента создан и сохранен:", clientId))
|
||||||
|
.catch(console.error);
|
||||||
|
} else {
|
||||||
|
browserAPI.storage.sync.set({ clientId }, () => {
|
||||||
|
if (chrome.runtime.lastError) {
|
||||||
|
console.error("Ошибка сохранения ID клиента:", chrome.runtime.lastError);
|
||||||
|
} else {
|
||||||
console.log("ID клиента создан и сохранен:", clientId);
|
console.log("ID клиента создан и сохранен:", clientId);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
}
|
||||||
console.error("Ошибка загрузки ID клиента:", error);
|
|
||||||
|
|
||||||
|
async function checkSessionStatus() {
|
||||||
|
try {
|
||||||
|
const statusUrl = 'http://127.0.0.1:5000/api/session_status';
|
||||||
|
const response = await fetch(statusUrl, {
|
||||||
|
headers: { 'X-Password': password }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { active, session_id } = await response.json();
|
||||||
|
|
||||||
|
if (active && !isRecording) {
|
||||||
|
startRecording(session_id);
|
||||||
|
} else if (!active && isRecording) {
|
||||||
|
stopRecording();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка проверки сессии:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function startRecording(sessionId) {
|
||||||
|
isRecording = true;
|
||||||
|
currentSessionId = sessionId;
|
||||||
|
console.log('Запись действий начата для сессии:', sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopRecording() {
|
||||||
|
isRecording = false;
|
||||||
|
currentSessionId = null;
|
||||||
|
console.log('Запись действий остановлена');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function createEventJSON(eventType, data) {
|
function createEventJSON(eventType, data) {
|
||||||
const timeStamp = new Date().toISOString();
|
const timeStamp = new Date().toISOString();
|
||||||
|
@ -71,10 +142,8 @@ function createEventJSON(eventType, data) {
|
||||||
|
|
||||||
|
|
||||||
async function sendDataToServer(eventData) {
|
async function sendDataToServer(eventData) {
|
||||||
if (!serverUrl || !password) {
|
if (!isRecording || !serverUrl || !password) return;
|
||||||
console.error("URL сервера или пароль не заданы. Проверьте настройки.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(serverUrl, {
|
const response = await fetch(serverUrl, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
|
@ -82,7 +151,10 @@ async function sendDataToServer(eventData) {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-Password': password,
|
'X-Password': password,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(eventData),
|
body: JSON.stringify({
|
||||||
|
...eventData,
|
||||||
|
session_id: currentSessionId
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const responseData = await response.json();
|
const responseData = await response.json();
|
||||||
|
@ -96,8 +168,24 @@ async function sendDataToServer(eventData) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function debounce(func, delay) {
|
||||||
|
let timeout;
|
||||||
|
return function(...args) {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
timeout = setTimeout(() => func(...args), delay);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initialize() {
|
||||||
|
await loadSettings();
|
||||||
|
handleClientId();
|
||||||
|
|
||||||
|
checkInterval = setInterval(checkSessionStatus, 5000);
|
||||||
|
checkSessionStatus();
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener("keydown", (event) => {
|
document.addEventListener("keydown", (event) => {
|
||||||
|
if (!isRecording) return;
|
||||||
const key = event.key;
|
const key = event.key;
|
||||||
const code = event.code;
|
const code = event.code;
|
||||||
let description;
|
let description;
|
||||||
|
@ -119,22 +207,16 @@ document.addEventListener("keydown", (event) => {
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener("mousedown", (event) => {
|
document.addEventListener("mousedown", (event) => {
|
||||||
|
if (!isRecording) return;
|
||||||
const eventData = createEventJSON('mousedown', { button: event.button, description: `Клик мышью: ${event.button}` });
|
const eventData = createEventJSON('mousedown', { button: event.button, description: `Клик мышью: ${event.button}` });
|
||||||
console.log("Событие mousedown:", JSON.stringify(eventData));
|
console.log("Событие mousedown:", JSON.stringify(eventData));
|
||||||
sendDataToServer(eventData);
|
sendDataToServer(eventData);
|
||||||
});
|
});
|
||||||
|
|
||||||
function debounce(func, wait) {
|
|
||||||
let timeout;
|
|
||||||
return function(...args) {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
timeout = setTimeout(() => func.apply(this, args), wait);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let accumulatedPixels = 0;
|
let accumulatedPixels = 0;
|
||||||
|
|
||||||
const handleWheel = debounce((event) => {
|
const handleWheel = debounce((event) => {
|
||||||
|
if (!isRecording) return;
|
||||||
const direction = accumulatedPixels > 0 ? "вниз" : "вверх";
|
const direction = accumulatedPixels > 0 ? "вниз" : "вверх";
|
||||||
const pixels = Math.abs(accumulatedPixels);
|
const pixels = Math.abs(accumulatedPixels);
|
||||||
|
|
||||||
|
@ -145,9 +227,10 @@ const handleWheel = debounce((event) => {
|
||||||
accumulatedPixels = 0;
|
accumulatedPixels = 0;
|
||||||
}, 200);
|
}, 200);
|
||||||
|
|
||||||
document.addEventListener("wheel", (event) => { accumulatedPixels += event.deltaY; handleWheel(event);});
|
document.addEventListener("wheel", (event) => { if (!isRecording) return; accumulatedPixels += event.deltaY; handleWheel(event);});
|
||||||
|
|
||||||
document.addEventListener("click", (event) => {
|
document.addEventListener("click", (event) => {
|
||||||
|
if (!isRecording) return;
|
||||||
const eventType = 'click';
|
const eventType = 'click';
|
||||||
const clickedElement = event.target;
|
const clickedElement = event.target;
|
||||||
const tag = clickedElement.tagName;
|
const tag = clickedElement.tagName;
|
||||||
|
@ -187,6 +270,7 @@ function navigateWithPromise(href) {
|
||||||
|
|
||||||
|
|
||||||
document.addEventListener("copy", (event) => {
|
document.addEventListener("copy", (event) => {
|
||||||
|
if (!isRecording) return;
|
||||||
const selectedText = window.getSelection().toString();
|
const selectedText = window.getSelection().toString();
|
||||||
|
|
||||||
let outputText = selectedText.length > 50 ? selectedText.substring(0, 49) + '…' : selectedText;
|
let outputText = selectedText.length > 50 ? selectedText.substring(0, 49) + '…' : selectedText;
|
||||||
|
@ -197,3 +281,6 @@ document.addEventListener("copy", (event) => {
|
||||||
sendDataToServer(eventData);
|
sendDataToServer(eventData);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize();
|
Loading…
Reference in New Issue