This commit is contained in:
yoannchb-pro
2023-03-22 23:46:20 -04:00
parent 2ba7d05575
commit 23af5fff0d
11 changed files with 156 additions and 20 deletions
+14 -1
View File
@@ -43,14 +43,27 @@ Type back the <b>code</b> on the keyboard and the code will be removed from the
- <b>Cursor indication</b>: show a pointer cursor and a hourglass to know when the request is finished.
- <b>Title indication</b>: show some informations into the title to know for example if the code have been injected.
<br/> ![Injected](./assets/title-injected.png)
- <b>Infinite try</b>: click as much as you want on the question (don't forget to reset the question).
- <b>Console logs</b>: show logs into the console.
<br/><img src="./assets/logs.png" alt="Logs" width="250">
- <b>Request timeout</b>: If the request is too long it will be abort after 10seconds.
- <b>Typing effect</b>: create a typing effect for text. Type any text and it will be replaced by the correct one. If you want to stop it press <b>Backspace</b> key.
<br/> ![Typing](./assets/typing.gif)
- <b>Mouseover effect</b>: you will need to hover (or click for select) the question response to complete it automaticaly.
<br/> ![Mouseover](./assets/mouseover.gif)
<br/> ![Mouseover2](./assets/mouseover2.gif)
- <b>Table formatting</b>: Format table from the question to make it more readable for CHAT-GPT.
```
--------------------------------
| |name |birthDate |cars|
--------------------------------
|Person 1|Yvick|15/08/1999|yes |
--------------------------------
|Person 2|Yann |19/01/2000|no |
--------------------------------
```
- <b>Infinite try</b>: click as much as you want on the question (don't forget to reset the question).
## Examples
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 49 KiB

+53 -7
View File
@@ -77,12 +77,15 @@
*/
function getChatGPTResponse(config, question) {
return __awaiter(this, void 0, void 0, function* () {
const controller = new AbortController();
const timeoutControler = setTimeout(() => controller.abort(), 10000);
const req = yield fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${config.apiKey}`,
},
signal: config.timeout ? controller.signal : null,
body: JSON.stringify({
model: config.model && config.model !== "" ? config.model : "gpt-3.5-turbo",
messages: [{ role: "user", content: question }],
@@ -92,21 +95,58 @@
stop: null,
}),
});
clearTimeout(timeoutControler);
const rep = yield req.json();
const response = rep.choices[0].message.content;
return normalizeText(response);
});
}
/**
* Convert table to representating string table
* @param table
* @returns
*/
function htmlTableToString(table) {
const tab = [];
const lines = Array.from(table.querySelectorAll("tr"));
const maxColumnsLength = [];
lines.map((line) => {
const cells = Array.from(line.querySelectorAll("td, th"));
const cellsContent = cells.map((cell, index) => {
var _a;
const content = (_a = cell.textContent) === null || _a === void 0 ? void 0 : _a.trim();
maxColumnsLength[index] = Math.max(maxColumnsLength[index] || 0, content.length || 0);
return content;
});
tab.push(cellsContent);
});
const lineSeparationSize = maxColumnsLength.reduce((a, b) => a + b) + tab[0].length + 1;
const lineSeparation = "\n" + Array(lineSeparationSize).fill("-").join("") + "\n";
const mappedTab = tab.map((line) => {
const mappedLine = line.map((content, index) => content.padEnd(maxColumnsLength[index], "\u00A0"));
return "|" + mappedLine.join("|") + "|";
});
return lineSeparation + mappedTab.join(lineSeparation) + lineSeparation;
}
/**
* Normalize the question and add sub informations
* @param langage
* @param question
* @returns
*/
function normalizeQuestion(langage, question) {
const finalQuestion = `Give a short response as possible for this question, reply in ${langage && langage !== ""
? 'this langage "' + langage + '"'
function normalizeQuestion(config, questionContainer) {
let question = questionContainer.textContent;
if (config.table) {
//make table more readable for chat-gpt
const tables = questionContainer.querySelectorAll("table");
for (const table of tables) {
question = question.replace(table.textContent, htmlTableToString(table));
}
}
const finalQuestion = `Give a short response as possible for this question, reply in ${config.langage && config.langage !== ""
? 'this langage "' + config.langage + '"'
: "the following question langage"} and only show the result:
${question}
(If you have to choose between multiple results only show the corrects one, separate them with new line and take the same text as the question)`;
@@ -297,15 +337,21 @@
if (config.cursor)
hiddenButton.style.cursor = "wait";
(_a = form.querySelector(".accesshide")) === null || _a === void 0 ? void 0 : _a.remove();
const question = normalizeQuestion(config.langage, form.textContent);
const question = normalizeQuestion(config, form);
const inputList = form.querySelectorAll(query);
const response = yield getChatGPTResponse(config, question);
const response = yield getChatGPTResponse(config, question).catch((error) => ({
error,
}));
if (config.cursor)
hiddenButton.style.cursor = config.infinite ? "pointer" : "initial";
if (typeof response === "object" && "error" in response) {
console.error(response.error);
return;
}
if (config.logs) {
Logs.question(question);
Logs.response(response);
}
if (config.cursor)
hiddenButton.style.cursor = config.infinite ? "pointer" : "initial";
const handlers = [
handleTextbox,
handleNumber,
File diff suppressed because one or more lines are too long
+8
View File
@@ -45,6 +45,10 @@
<input id="mouseover" type="checkbox" />
<label for="mouseover">Mouseover effect</label>
</div>
<div class="line">
<input id="table" type="checkbox" checked />
<label for="table">Table formatting</label>
</div>
<div class="line">
<input id="infinite" type="checkbox" />
<label for="infinite">Infinite try</label>
@@ -63,6 +67,10 @@
<input id="cursor" type="checkbox" checked />
<label for="cursor">Cursor indication</label>
</div>
<div class="line">
<input id="timeout" type="checkbox" checked />
<label for="timeout">Request timeout</label>
</div>
</div>
</div>
<p id="message">Message</p>
+8 -3
View File
@@ -9,6 +9,8 @@ const inputsCheckbox = [
"typing",
"mouseover",
"infinite",
"table",
"timeout",
];
function showMessage(messageTxt, valide) {
@@ -23,9 +25,10 @@ saveBtn.addEventListener("click", function () {
const [apiKey, code, langage, model] = inputsText.map((selector) =>
document.querySelector("#" + selector).value.trim()
);
const [logs, title, cursor, typing, mouseover, infinite] = inputsCheckbox.map(
(selector) => document.querySelector("#" + selector).checked
);
const [logs, title, cursor, typing, mouseover, infinite, table, timeout] =
inputsCheckbox.map(
(selector) => document.querySelector("#" + selector).checked
);
if (!apiKey || !code) {
showMessage("Please comple all the form");
@@ -49,6 +52,8 @@ saveBtn.addEventListener("click", function () {
typing,
mouseover,
infinite,
table,
timeout,
},
});
+4
View File
@@ -11,12 +11,15 @@ async function getChatGPTResponse(
config: Config,
question: string
): Promise<string> {
const controller = new AbortController();
const timeoutControler = setTimeout(() => controller.abort(), 10000);
const req = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${config.apiKey}`,
},
signal: config.timeout ? controller.signal : null,
body: JSON.stringify({
model:
config.model && config.model !== "" ? config.model : "gpt-3.5-turbo",
@@ -27,6 +30,7 @@ async function getChatGPTResponse(
stop: null,
}),
});
clearTimeout(timeoutControler);
const rep = await req.json();
const response = rep.choices[0].message.content;
return normalizeText(response);
+14 -3
View File
@@ -1,5 +1,6 @@
import Config from "../types/config";
import normalizeText from "../utils/normalize-text";
import htmlTableToString from "../utils/html-table-to-string";
/**
* Normalize the question and add sub informations
@@ -7,10 +8,20 @@ import normalizeText from "../utils/normalize-text";
* @param question
* @returns
*/
function normalizeQuestion(langage: Config["langage"], question: string) {
function normalizeQuestion(config: Config, questionContainer: HTMLElement) {
let question = questionContainer.textContent;
if (config.table) {
//make table more readable for chat-gpt
const tables = questionContainer.querySelectorAll("table");
for (const table of tables) {
question = question.replace(table.textContent, htmlTableToString(table));
}
}
const finalQuestion = `Give a short response as possible for this question, reply in ${
langage && langage !== ""
? 'this langage "' + langage + '"'
config.langage && config.langage !== ""
? 'this langage "' + config.langage + '"'
: "the following question langage"
} and only show the result:
${question}
+14 -5
View File
@@ -26,19 +26,28 @@ async function reply(
form.querySelector(".accesshide")?.remove();
const question = normalizeQuestion(config.langage, form.textContent);
const question = normalizeQuestion(config, form);
const inputList: NodeListOf<HTMLElement> = form.querySelectorAll(query);
const response = await getChatGPTResponse(config, question);
const response = await getChatGPTResponse(config, question).catch(
(error) => ({
error,
})
);
if (config.cursor)
hiddenButton.style.cursor = config.infinite ? "pointer" : "initial";
if (typeof response === "object" && "error" in response) {
console.error(response.error);
return;
}
if (config.logs) {
Logs.question(question);
Logs.response(response);
}
if (config.cursor)
hiddenButton.style.cursor = config.infinite ? "pointer" : "initial";
const handlers = [
handleTextbox,
handleNumber,
+2
View File
@@ -9,6 +9,8 @@ type Config = {
cursor?: boolean;
logs?: boolean;
title?: boolean;
table?: boolean;
timeout?: boolean;
};
export default Config;
+38
View File
@@ -0,0 +1,38 @@
/**
* Convert table to representating string table
* @param table
* @returns
*/
function htmlTableToString(table: HTMLTableElement) {
const tab: string[][] = [];
const lines = Array.from(table.querySelectorAll("tr"));
const maxColumnsLength: number[] = [];
lines.map((line) => {
const cells = Array.from(line.querySelectorAll("td, th"));
const cellsContent = cells.map((cell, index) => {
const content = cell.textContent?.trim();
maxColumnsLength[index] = Math.max(
maxColumnsLength[index] || 0,
content.length || 0
);
return content;
});
tab.push(cellsContent);
});
const lineSeparationSize =
maxColumnsLength.reduce((a, b) => a + b) + tab[0].length + 1;
const lineSeparation =
"\n" + Array(lineSeparationSize).fill("-").join("") + "\n";
const mappedTab = tab.map((line) => {
const mappedLine = line.map((content, index) =>
content.padEnd(maxColumnsLength[index], "\u00A0")
);
return "|" + mappedLine.join("|") + "|";
});
return lineSeparation + mappedTab.join(lineSeparation) + lineSeparation;
}
export default htmlTableToString;