// ==UserScript==
// @name AIGPT Everywhere
// @namespace OperaBrowserGestures
// @description Mini A.I. floating menu that can define words, answer questions, translate, and much more in a single click and with your custom prompts. Includes useful click to search on Google and copy selected text buttons, along with Rocker+Mouse Gestures and Units+Currency+Time zone Converters, all features can be easily modified or disabled.
// @version 75
// @author hacker09
// @include *
// @exclude https://accounts.google.com/v3/signin/*
// @icon https://i.imgur.com/8iw8GOm.png
// @grant GM_registerMenuCommand
// @grant GM_getResourceText
// @grant GM.xmlHttpRequest
// @grant GM_setClipboard
// @grant GM_deleteValue
// @grant GM_openInTab
// @grant window.close
// @run-at document-end
// @grant GM_setValue
// @grant GM_getValue
// @connect google.com
// @connect generativelanguage.googleapis.com
// @resource AIMenuContent https://hacker09.glitch.me/AIMenu.html
// @require https://update.greasyfork.org/scripts/506699/marked.js
// @require https://update.greasyfork.org/scripts/519002/Units%20Converter.js
// @downloadURL https://update.greasyfork.icu/scripts/419825/AIGPT%20Everywhere.user.js
// @updateURL https://update.greasyfork.icu/scripts/419825/AIGPT%20Everywhere.meta.js
// ==/UserScript==
/* jshint esversion: 11 */
const toHTML = html => window.trustedTypes?.createPolicy('BypassTT', { createHTML: HTML => HTML })?.createHTML(html) || html; //Bypass Trusted Types API + create safe HTML for chromium browsers
if ((location.href === 'https://aistudio.google.com/app/apikey' && document.querySelector(".apikey-link") !== null) && GM_getValue("APIKey") === undefined || GM_getValue("APIKey") === null || GM_getValue("APIKey") === '') { //Set up the API Key
window.onload = setTimeout(function() {
document.querySelectorAll(".apikey-link")[1].click(); //Click on the API Key
setTimeout(function() {
GM_setValue("APIKey", document.querySelector(".apikey-text").innerText); //Store the API Key
alert((GM_getValue("APIKey") !== undefined && GM_getValue("APIKey") !== null && GM_getValue("APIKey") !== '') ? 'API Key automatically added!' : 'Failed to automatically add API Key!');
}, 500);
}, 1000);
}
if (GM_getValue("SearchHighlight") === undefined) { //Set up everything on the first run
GM_setValue("SearchHighlight", true);
GM_setValue("MouseGestures", true);
GM_setValue("TimeConverter", true);
GM_setValue("UnitsConverter", true);
GM_setValue("CurrenciesConverter", true);
}
function ToggleFeature(feature)
{
GM_setValue(feature, GM_getValue(feature) === true ? false : true);
location.reload();
}
//Mouse Gestures__________________________________________________________________________________________________________________________________________________________________________________
GM_registerMenuCommand(`${GM_getValue("MouseGestures") ? "Disable" : "Enable"} Mouse Gestures`, function() { ToggleFeature("MouseGestures"); });
if (GM_getValue("MouseGestures") === true) //If the MouseGestures is enabled
{
var link;
document.querySelectorAll('a').forEach(el => {
el.addEventListener('mouseover', function() {
link = this.href; //Store the hovered link
});
el.addEventListener('mouseout', () => {
const previousLink = link; //Save the hovered link
setTimeout(() => {
if (previousLink === link) { //Check if the same link is still hovered
link = 'about:newtab'; //Open a new tab
}
}, 200);
});
});
const funcs = { //Store the MouseGestures functions
'DL': function() { //Detect the Down+Left movement
GM_openInTab(location.href, { incognito: true, });
window.top.close();
},
'L': function() { //Detect the Left movement
window.history.back();
},
'R': function() { //Detect the Right movement
window.history.forward();
},
'D': function(e) { //Detect the Down movement
if (e.shiftKey) {
open(link, '_blank', 'height=' + screen.height + ',width=' + screen.width);
}
else {
GM_openInTab(link, { active: true, insert: true, setParent: true });
}
},
'UD': function() { //Detect the Up+Down movement
location.reload();
},
'DR': function(e) { //Detect the Down+Right movement
top.close();
e.preventDefault();
e.stopPropagation();
},
'DU': function() { //Detect the Down+Up movement
GM_openInTab(link, { active: false, insert: true, setParent: true });
}
};
//Math codes to track the mouse movement gestures
var x, y, path;
const TOLERANCE = 3;
const SENSITIVITY = 3;
const s = 1 << ((7 - SENSITIVITY) << 1);
const t1 = Math.tan(0.15708 * TOLERANCE),t2 = 1 / t1;
const tracer = function(e) {
var cx = e.clientX, cy = e.clientY, deltaX = cx - x, deltaY = cy - y, distance = deltaX * deltaX + deltaY * deltaY;
if (distance > s) {
var slope = Math.abs(deltaY / deltaX), direction = '';
if (slope > t1) {
direction = deltaY > 0 ? 'D' : 'U';
} else if (slope <= t2) {
direction = deltaX > 0 ? 'R' : 'L';
}
if (path.charAt(path.length - 1) !== direction) {
path += direction;
}
x = cx;
y = cy;
}
};
window.addEventListener('mousedown', function(e) {
if (e.which === 3) {
x = e.clientX;
y = e.clientY;
path = "";
window.addEventListener('mousemove', tracer, false); //Detect the mouse position
}
}, false);
window.addEventListener('contextmenu', function(e) { //When the right click BTN is released
window.removeEventListener('mousemove', tracer, false); //Track the mouse movements
if (path !== "") {
e.preventDefault();
if (funcs.hasOwnProperty(path)) {
funcs[path](e);
}
}
}, false);
}
//Rocker Mouse Gestures___________________________________________________________________________________________________________________________________________________________________________
GM_registerMenuCommand(`${GM_getValue("RockerMouseGestures") ? "Disable" : "Enable"} Rocker Gestures`, function() { ToggleFeature("RockerMouseGestures"); });
if (GM_getValue("RockerMouseGestures") === true) //If the RockerMouseGestures is enabled
{
const mouseState = { 0: false, 2: false }; //0: Left, 2: Right
window.addEventListener("mouseup", function(e) {
mouseState[e.button] = false; //Update the state for the released button
if (mouseState[0] && !mouseState[2]) { //Left clicked, Right released
history.back();
} else if (mouseState[2] && !mouseState[0]) { //Right clicked, Left released
history.forward();
}
}, false);
window.addEventListener("mousedown", function(e) {
mouseState[e.button] = true; //Update the state for the pressed button
}, false);
}
//Search HighLight + Time + Currencies + Units Converters + Search HighLight + AI menus___________________________________________________________________________________________________________
GM_registerMenuCommand(`${GM_getValue("SearchHighlight") ? "Disable" : "Enable"} Search Highlight`, function() { ToggleFeature("SearchHighlight"); });
if (GM_getValue("SearchHighlight") === true) //If the SearchHighlight is enabled
{
var SelectedText;
const Links = new RegExp(/\.org|\.ly|\.net|\.co|\.tv|\.me|\.biz|\.club|\.site|\.br|\.gov|\.io|\.ai|\.jp|\.edu|\.au|\.in|\.it|\.ca|\.mx|\.fr|\.tw|\.il|\.uk|\.zoom\.us|\.youtu\.be|\.com|\.us|\.de|\.cn|\.ru|\.es|\.ch|\.nl|\.se|\.no|\.dk|\.fi|\.pl|\.tr|\.xyz|\.za/i);
document.body.addEventListener('mouseup', async function() { //When the user releases the mouse click after selecting something
HtmlMenu.style.display = 'block'; //Display the container div
SelectedText = getSelection().toString().trim(); //Store the selected text
shadowRoot.querySelector("#ShowCurrencyORUnits").innerText = ''; //Remove the previous Units/Currency text
function ShowConvertion(UnitORCurrency, Type, Result) {
shadowRoot.querySelector("#SearchBTN span")?.remove(); //Return previous HTML
shadowRoot.querySelector("#SearchBTN").innerHTML = toHTML('│ ' + shadowRoot.querySelector("#SearchBTN").innerHTML);
if (UnitORCurrency === 'Currencies') {
const hasSymbol = SelectedText.match(Currencies)[2].match(CurrencySymbols) !== null;
const currencyFormat = Intl.NumberFormat(navigator.language, {
style: 'currency',
currency: GM_getValue("YourLocalCurrency")
}).format(Result);
const displayText = hasSymbol ? (Type + ' 🠂 ' + currencyFormat) : currencyFormat;
shadowRoot.querySelector("#ShowCurrencyORUnits").innerHTML = toHTML(displayText);
}
else
{
shadowRoot.querySelector("#ShowCurrencyORUnits").innerHTML = toHTML(UnitORCurrency === 'Units' ? `${Result} ${Type}` : Result); //Show the converted time results
}
setTimeout(() => { //Wait for Units to show up to get the right offsetWidth
const offsetWidth = shadowRoot.querySelector("#ShowCurrencyORUnits").offsetWidth; //Store the current menu size
shadowRoot.querySelector("#ShowCurrencyORUnits").onmouseover = function() { //When the mouse hovers the unit/currency
shadowRoot.querySelector("#ShowCurrencyORUnits").innerHTML = toHTML(`Copy`);
shadowRoot.querySelector("#ShowCurrencyORUnits").style.display = 'inline-flex';
shadowRoot.querySelector("#ShowCurrencyORUnits").style.width = `${offsetWidth}px`; //Maintain the aspect ratio
};
}, 0);
const htmlcode = shadowRoot.querySelector("#ShowCurrencyORUnits").innerHTML; //Save the converted unit/currency value
shadowRoot.querySelector("#ShowCurrencyORUnits").onmouseout = function() { //When the mouse leaves the unit/currency
shadowRoot.querySelector("#ShowCurrencyORUnits").style.width = ''; //Return the original aspect ratio
shadowRoot.querySelector("#ShowCurrencyORUnits").style.display = ''; //Return the original aspect ratio
shadowRoot.querySelector("#ShowCurrencyORUnits").innerHTML = toHTML(htmlcode); //Return the previous html
};
shadowRoot.querySelector("#ShowCurrencyORUnits").onclick = function() { //When the unit/currency is clicked
UnitORCurrency.match(/Units|Time/) ? GM_setClipboard(`${Result} ${Type}`) : GM_setClipboard(Intl.NumberFormat(navigator.language, { style: 'currency', currency: GM_getValue("YourLocalCurrency") }).format(Result));
};
}
function Get(url) { //Get the final converted time/currency value
return new Promise(resolve => GM.xmlHttpRequest({
method: "GET",
url: url,
onload: response => resolve(new DOMParser().parseFromString(response.responseText, 'text/html'))
}));
}
//Time Converter______________________________________________________________________________________________________________________________________________________________________________
GM_registerMenuCommand(`${GM_getValue("TimeConverter") ? "Disable" : "Enable"} Time Converter`, function() { ToggleFeature("TimeConverter"); });
const time = new RegExp(/^[ \t\xA0]*(?=.*?(\d{1,2}:\d{2}(?::\d{2})?\s?(?:[aApP]\.?[mM]\.?)?)|\d{1,2}(?::\d{2}(?::\d{2})?)?\s?(?:[aApP]\.?[mM]\.?)?)(?=.*?(PST|PDT|MST|MDT|CST|CDT|EST|EDT|AST|ADT|NST|NDT|GMT|BST|MET|CET|CEST|EET|EEST|WET|WEST|JST|KST|IST|MSK|UTC|PT))(?:\1[ \t\xA0]*\2|\2[ \t\xA0]*\1)[ \t\xA0]*$/i);
if (GM_getValue("TimeConverter") === true && SelectedText.match(time) !== null) //If the TimeConverter is enabled and if the selected text is a time
{
const timeResponse = await Get(`https://www.google.com/search?q=${SelectedText.match(time)[0].replace("WET", "Western European Time")} to local time`);
const ConvertedTime = timeResponse.querySelector(".aCAqKc")?.innerText;
const Secs = SelectedText.match(time)[0].match(/(?:\d{1,2}:\d{2}(:\d{2})\s?[ap]\.?m)/i)?.[1] || '';
ConvertedTime && ShowConvertion('Time', '', ConvertedTime.replace(/(\d{1,2}):(\d{2})\s?([pP][mM])/, (_, h, m) => `${(h % 12 + 12) % 24}:${m}`).match(/[\d:]+/g)[0] + Secs); //Convert PM to 24-hour format if we got the final time conversion value
}
//Currencies Converter________________________________________________________________________________________________________________________________________________________________________
GM_registerMenuCommand(`${GM_getValue("CurrenciesConverter") ? "Disable" : "Enable"} Currencies Converter`, function() { ToggleFeature("CurrenciesConverter"); });
const CurrencySymbols = new RegExp(/AU\$|HK\$|US\$|\$US|R\$|\$|¥|€|Rp|Kč|kr(?!w)|zł|£|฿|₩|лв|₪|円|₱|₽|руб|lei|Fr|krw|RON|TRY|₿|Br|₾|₴|₸|₺/i);
const Currencies = new RegExp(/^[ \t\xA0]*\$?(?=.*?(\d+(?:.*\d+)?))(?=(?:\1[ \t\xA0]*)?(Dólares|dolares|dólares|dollars?|AU\$?D?|BGN|BRL|BCH|BTC|BYN|CAD|CHF|Fr|CNY|CZK|DKK|EUR|EGP|ETH|GBP|GEL|HKD|HUF|IDR|ILS|INR|JPY|LTC|KRW|MXN|NOK|NZD|PHP|PLN|RON|RUB|SEK|SGD|THB|TRY|USD|UAH|ZAR|KZT|YTL|\$|R\$|HK\$|US\$|\$US|¥|€|Rp|Kč|kr|krw|zł|£|฿|₩|лв|₪|円|₱|₽|руб|lei|Kč|₿|Br|₾|₴|₸|₺))(?:\1[ \t\xA0]*\2|\2[ \t\xA0]*\1)[ \t\xA0]*$/i); //https://regex101.com/r/6vTbtv/20 Davidebyzero
if (GM_getValue("CurrenciesConverter") === true && SelectedText.match(Currencies) !== null) { //If Currencies Converter is enabled and if the selected text is a currency
if (GM_getValue("YourLocalCurrency") === undefined) {
const UserInput = prompt('Write your local currency.\nThe script will always use your local currency to make exchange-rate conversions.\n\n*Currency input examples:\nBRL\nCAD\nUSD\netc...\n\n*Press OK');
GM_setValue("YourLocalCurrency", UserInput);
}
const currencyMap = { 'AU$': 'AUD', '$': 'USD', 'us$': 'USD', '$us': 'USD', 'r$': 'BRL', 'hk$': 'HKD', '¥': 'JPY', '€': 'EUR', 'rp': 'IDR', 'kč': 'CZK', 'kr': 'NOK', 'zł': 'PLN', '£': 'GBP', '฿': 'THB', '₩': 'KRW', 'лв': 'BGN', '₪': 'ILS', '円': 'JPY', '₱': 'PHP', '₽': 'RUB', 'руб': 'RUB', 'lei': 'RON', 'ron': 'Romanian Leu', 'krw': 'KRW', 'fr': 'CHF', '₿': 'BTC', 'Br': 'BYN', '₾': 'GEL', '₴': 'UAH', '₸': 'KZT', '₺': 'YTL', 'try': 'Turkish Lira' };
const CurrencySymbol = currencyMap[SelectedText.match(CurrencySymbols)?.[0].toUpperCase()] || SelectedText.match(Currencies)[2]; //Store the currency symbol
const currencyResponse = await Get(`https://www.google.com/search?q=${SelectedText.match(Currencies)[1]} ${CurrencySymbol} in ${GM_getValue("YourLocalCurrency")}`);
const FinalCurrency = parseFloat(currencyResponse.querySelector(".SwHCTb, .pclqee").innerText.split(' ')[0].replaceAll(',', '')); //Store the FinalCurrency and erase all commas
ShowConvertion('Currencies', CurrencySymbol, FinalCurrency);
}
//Units Converter_____________________________________________________________________________________________________________________________________________________________________________
GM_registerMenuCommand(`${GM_getValue("UnitsConverter") ? "Disable" : "Enable"} Units Converter`, function() { ToggleFeature("UnitsConverter"); });
const Units = new RegExp(/^[ \t\xA0]*(-?\d+(?:[., ]\d+)?)(?:[ \t\xA0]*x[ \t\xA0]*(-?\d+(?:[., ]\d+)?))?[ \t\xA0]*(in|inch|inches|"|”|″|cm|cms|centimeters?|m|mt|mts|meters?|ft|kg|lbs?|pounds?|kilograms?|ounces?|g|ozs?|fl oz|fl oz (us)|fluid ounces?|kphs?|km\/h|kilometers per hours?|mhp|mphs?|meters per hours?|(?:°\s?|º\s?|)(?:degrees?\s+)?(?:celsius|fahrenheit|[CF])|km\/hs?|ml|milliliters?|l|liters?|litres?|gal|gallons?|yards?|yd|Millimeter|millimetre|kilometers?|mi|mm|miles?|km|ft|fl|feets?|grams?|kilowatts?|kws?|brake horsepower|mechanical horsepower|hps?|bhps?|miles per gallons?|mpgs?|liters per 100 kilometers?|lt?\/100km|liquid quarts?|lqs?|qt|foot-? ?pounds?|ft-?lbs?|lb fts?|newton-? ?meters?|n·?m|\^\d+)[ \t\xA0]*(?:\(\w+\)[ \t\xA0]*)?$/i);
if (GM_getValue("UnitsConverter") === true && SelectedText.match(Units) !== null) { //If the Units Converter option is enabled and if the selected text is an unit
const selectedUnitType = SelectedText.match(Units)[3].toLowerCase();
const SelectedUnitValue = SelectedText.match(Units)[1].replaceAll(',', '.');
const SecondSelectedUnitValue = SelectedText.match(Units)[2]?.replaceAll(',', '.') || 0;
const convertValue = (value, unitType) => {
const { factor, convert } = window.UConv[unitType] || {};
return convert ? convert(value) : value * factor;
};
var NewUnit = window.UConv[selectedUnitType]?.unit || selectedUnitType;
var ConvertedUnit = `${convertValue(parseFloat(SelectedUnitValue), selectedUnitType).toFixed(2)}${SecondSelectedUnitValue != 0 ? ` x ${convertValue(parseFloat(SecondSelectedUnitValue), selectedUnitType).toFixed(2)}` : ''}`;
ConvertedUnit = SelectedText.match(/\^(\d+\.?\d*)/) ? (NewUnit = 'power', Math.pow(parseFloat(SelectedUnitValue), parseFloat(SelectedText.match(/\^(\d+\.?\d*)/)[1]))) : ConvertedUnit;
ShowConvertion('Units', NewUnit, ConvertedUnit);
}
//Mini Menu___________________________________________________________________________________________________________________________________________________________________________________
if (shadowRoot.querySelector("#SearchBTN").innerText === 'Open') //If the Search BTN text is 'Open'
{
shadowRoot.querySelector("#highlight_menu > ul").style.paddingInlineStart = '19px'; //Increase the menu size
shadowRoot.querySelector("#SearchBTN").innerText = 'Search'; //Display the BTN text as Search again
shadowRoot.querySelectorAll(".AI-BG-box button").forEach(button => { button.style.marginLeft = ''; }); //Remove the margin left
shadowRoot.querySelector("#OpenAfter").remove(); //Remove the custom Open white hover overlay
}
if (SelectedText.match(Links) !== null) //If the selected text is a link
{
shadowRoot.querySelector("#highlight_menu > ul").style.paddingInlineStart = '27px'; //Increase the menu size
shadowRoot.querySelector("#SearchBTN").innerText = 'Open'; //Change the BTN text to Open
shadowRoot.querySelectorAll(".AI-BG-box button").forEach(button => { button.style.marginLeft = '-2%'; }); //Add a margin left
shadowRoot.innerHTML += toHTML(` `); //Add a custom Open white hover overlay
}
shadowRoot.querySelector("#SearchBTN").onmousedown = function() {
GM_openInTab(SelectedText.match(Links) ? SelectedText.replace(/^(?!https?:\/\/)(.+)$/, 'https://$1') : `https://www.google.com/search?q=${SelectedText.replaceAll('&', '%26').replace(/\s+/g, ' ')}`, { active: true, setParent: true, loadInBackground: true }); //Open link or google and search for the selected text
shadowRoot.querySelector("#highlight_menu").classList.remove('show'); //Hide the menu
};
const menu = shadowRoot.querySelector("#highlight_menu");
if (document.getSelection().toString().trim() !== '') { //If text has been selected
const p = document.getSelection().getRangeAt(0).getBoundingClientRect(); //Store the selected position
menu.classList.add('show'); //Show the menu
menu.offsetHeight; //Trigger reflow by forcing a style calculation
menu.style.left = p.left + (p.width / 2) - (menu.offsetWidth / 2) + 'px';
menu.style.top = p.top - menu.offsetHeight - 10 + 'px';
menu.classList.add('highlight_menu_animate');
return; //Keep the menu open
}
menu.classList.remove('show'); //Hide the menu
shadowRoot.querySelector("#SearchBTN span")?.remove(); //Return previous HTML
}); //Finishes the mouseup event listener
//AI Menu_______________________________________________________________________________________________________________________________________________________________________________________
var desiredVoice = null, isRecognizing = false;
const HtmlMenu = document.createElement('div'); //Create a container div
HtmlMenu.setAttribute('style', `width: 0px; height: 0px; display: none;`); //Hide the container div by default
const shadowRoot = HtmlMenu.attachShadow({ mode: 'closed' });
const UniqueLangs = navigator.languages.filter((l, i, arr) => !arr.slice(0, i).some(e => e.split('-')[0].toLowerCase() === l.split('-')[0].toLowerCase()) ); //Filter unique languages
const Lang = UniqueLangs.join(' and into '); //Use 1 or 2 languages
shadowRoot.innerHTML = toHTML(GM_getResourceText("AIMenuContent")); //Set the AI menu HTML+CSS
function Generate(Prompt, button) { //Call the AI endpoint
const context = !!shadowRoot.querySelector("#context.show") ? `"${Prompt}"\n\nMainly base yourself on the text below\n\n${document.body.innerText}` : Prompt; //Add the page context if context is enabled
const isQuestion = Prompt.includes('?') ? 'Give me a very short, then a long detailed answer' : 'Help me further understand/learn a term or topic from the text/word';
const isWord = Prompt.split(' ').length < 5 ? `\nAfter showing (in order) (add a heading as "${Prompt}"), a few possible "Synonyms:", "Definition:" and "Example:".` : '';
const msg = button.match('translate') ? `Translate this text: "${Prompt.trim().slice(0, 215)}${Prompt.length > 215 ? '…' : ''}"` : button.match('Prompt') ? `${Prompt.trim().slice(0, 240)}${Prompt.length > 240 ? '…' : ''}` : `Help me further explore a term or topic from the text: "${Prompt.trim().slice(0, 180)}${Prompt.length > 180 ? '…' : ''}"`; //AI Box top text
const AIFunction = button.match('translate') ? `Translate into ${Lang} the following text:\n\n"${Prompt}"\n${isWord}${UniqueLangs.length > 1 ? `\n\nYou must answer using only 1 language first, then use only the other language, don't mix both languages!\n\n"${Prompt}" should be translated for the 2nd language` : ''}` : button.match('Prompt') ? context : `${isQuestion}: "${Prompt}"`; //AI final prompt
function handleState(state) { //Show #AIMenu + #dictate but hide #TopPause for the load/abort states. Do the opposite for the 'start' state.
["#AIMenu", "#dictate", "#TopPause"].forEach(el => {
if (el === "#TopPause") {
shadowRoot.querySelector(el).classList[state !== 'start' ? 'remove' : 'add']('show');
} else {
shadowRoot.querySelector(el).classList[state !== 'start' ? 'add' : 'remove']('show');
}
});
}
const Generating = setInterval(function() { //Start the interval to change the text
if (shadowRoot.querySelector("#finalanswer").innerText === 'ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ▋') { //Start the if condition
shadowRoot.querySelector("#finalanswer").innerText = 'ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ'; //Remove ▋
} else { //Toggle between showing and hiding ▋
shadowRoot.querySelector("#finalanswer").innerText = 'ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ▋'; //Add ▋
}
}, 200);
const request = GM.xmlHttpRequest({
method: "POST",
url: `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:streamGenerateContent?key=${GM_getValue("APIKey")}`,
responseType: 'stream',
headers: { "Content-Type": "application/json" },
data: JSON.stringify({
contents: [{
parts: [{
text: AIFunction //AI prompt
}]
}],
systemInstruction: {
parts: [{
text: `List of things you aren't allowed to say/do anything like:\n1 "Based on the provided text"\n2 "The text is already in"\n3 "No translation is needed"\n4 Ask for more context\n5 "You haven't provided context"\n6 Use bullet points for Synonyms`
}]
},
safetySettings: [
{ category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE" },
{ category: "HARM_CATEGORY_HATE_SPEECH", threshold: "BLOCK_NONE" },
{ category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold: "BLOCK_NONE" },
{ category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_NONE" }
],
}),
onerror: function(err) {
clearInterval(Generating); //Stop showing ▋
shadowRoot.querySelector("#msg").innerHTML = 'Error';
shadowRoot.querySelector("#finalanswer").innerHTML = toHTML(`
Please copy and paste the error below:
Click here to report this bug
Prompt: ${Prompt}
Button: ${button}
Error:
${JSON.stringify(err, null, 2)}