Best School Cheat

Drag OCR → send to SambaNova API → show answer in floating panel (even if OCR empty)

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Best School Cheat
// @namespace    http://tampermonkey.net/
// @version      V12
// @description  Drag OCR → send to SambaNova API → show answer in floating panel (even if OCR empty)
// @match        *://*/*
// @grant        GM_setClipboard
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.min.js
// @require      https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js
// ==/UserScript==

/* 🔑 YOUR SAMBANOVA API KEY — paste it here */
const SN_API_KEY = "24ae777f-31a3-43ba-85a0-e10a7469581b";

/* 🌐 SambaNova API endpoint */
const SN_URL = "https://api.sambanova.ai/v1/chat/completions";

(function () {

let armed = false;
let startX, startY, box;
let zoomLevel = 2;
let promptType = "solve";

/* ---------- BUTTON ---------- */

function makeBtn(txt){
  let b = document.createElement("button");
  b.textContent = txt;
  Object.assign(b.style,{
    padding:"6px 8px",
    background:"#007bff",
    color:"#fff",
    border:"none",
    borderRadius:"6px",
    cursor:"pointer",
    fontSize:"12px"
  });
  return b;
}

/* ---------- COLLAPSE REOPEN BUTTON ---------- */

const reopenBtn = makeBtn("+");
Object.assign(reopenBtn.style,{
  position:"fixed",
  bottom:"20px",
  right:"20px",
  zIndex:999999,
  display:"none"
});
document.body.appendChild(reopenBtn);

/* ---------- CONTROL BAR ---------- */

const bar = document.createElement("div");
Object.assign(bar.style,{
  position:"fixed",
  bottom:"20px",
  right:"20px",
  zIndex:999998,
  padding:"8px",
  background:"rgba(20,20,20,0.9)",
  borderRadius:"8px",
  display:"flex",
  gap:"6px",
  alignItems:"center",
  color:"#fff",
  fontFamily:"system-ui, sans-serif",
  fontSize:"12px"
});

/* OCR BUTTON */

const ocrBtn = makeBtn("OCR-Drag");
ocrBtn.onclick = () => {
  armed = !armed;
  ocrBtn.style.background = armed ? "#28a745" : "#007bff";
};
bar.appendChild(ocrBtn);

/* PROMPT SELECT */

const select = document.createElement("select");
["solve","explain","summarize"].forEach(v=>{
  let o = document.createElement("option");
  o.value = v;
  o.textContent = v;
  select.appendChild(o);
});
select.onchange = () => promptType = select.value;
bar.appendChild(select);

/* ZOOM CONTROLS */

const zoomMinus = makeBtn("−");
const zoomPlus = makeBtn("+");
const zoomLabel = document.createElement("span");

function updateZoom(){
  zoomLabel.textContent = `Zoom:${zoomLevel}x`;
}
updateZoom();

zoomPlus.onclick = () => {
  zoomLevel = Math.min(5, zoomLevel + 0.5);
  updateZoom();
};

/* ---------- FULL COLLAPSE ---------- */

zoomMinus.onclick = () => {
  bar.style.display = "none";
  panel.style.display = "none";
  reopenBtn.style.display = "block";
};

reopenBtn.onclick = () => {
  bar.style.display = "flex";
  reopenBtn.style.display = "none";
};

bar.append(zoomMinus, zoomLabel, zoomPlus);
document.body.appendChild(bar);

/* ---------- ANSWER PANEL ---------- */

const panel = document.createElement("div");
Object.assign(panel.style,{
  position:"fixed",
  bottom:"70px",
  right:"20px",
  width:"360px",
  maxHeight:"60vh",
  background:"#111",
  color:"#eee",
  borderRadius:"10px",
  padding:"12px",
  display:"none",
  zIndex:999997,
  fontFamily:"system-ui, sans-serif",
  fontSize:"12px",
  overflow:"auto",
  boxShadow:"0 2px 10px rgba(0,0,0,0.5)"
});

const body = document.createElement("div");
body.style.whiteSpace = "pre-wrap";
panel.appendChild(body);
document.body.appendChild(panel);

function showPanel(text){
  body.textContent = text;
  panel.style.display = "block";
}

/* ---------- SCREENSHOT (lab() color fix) ---------- */

async function screenshot(rect){
  return await html2canvas(document.body,{
    x:rect.left,
    y:rect.top,
    width:rect.width,
    height:rect.height,
    scale:zoomLevel,
    onclone:(doc)=>{
      doc.querySelectorAll("[style*='lab(']").forEach(el=>{
        el.style.cssText = el.style.cssText.replace(/lab\([^)]*\)/g,"rgb(0,0,0)");
      });
    }
  });
}

/* ---------- PROMPT BUILDER ---------- */

function buildPrompt(text){
  if(promptType === "explain")
    return `Explain this clearly:\n\n${text}`;
  if(promptType === "summarize")
    return `Summarize this:\n\n${text}`;
  return `Solve this step-by-step:\n\n${text}`;
}

/* ---------- SAMBANOVA CALL ---------- */

async function askSambaNova(text){
  const prompt = buildPrompt(text);

  const res = await fetch(SN_URL, {
    method: "POST",
    headers: {
      "Authorization": "Bearer " + SN_API_KEY,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      stream: false,
      model: "ALLaM-7B-Instruct-preview",
      messages: [
        {
          role: "system",
          content: "You are a helpful assistant"
        },
        {
          role: "user",
          content: prompt
        }
      ]
    })
  });

  const data = await res.json();
  const answer =
    data?.choices?.[0]?.message?.content ||
    "[No answer returned]";

  return { prompt, answer };
}

/* ---------- DRAG ---------- */

document.addEventListener("mousedown", e => {
  if(!armed) return;

  startX = e.clientX;
  startY = e.clientY;

  box = document.createElement("div");
  Object.assign(box.style,{
    position:"fixed",
    border:"2px dashed red",
    background:"rgba(255,0,0,0.15)",
    left:startX+"px",
    top:startY+"px",
    zIndex:999996
  });

  document.body.appendChild(box);
});

document.addEventListener("mousemove", e => {
  if(!armed || !box) return;

  let w = e.clientX - startX;
  let h = e.clientY - startY;

  box.style.width = Math.abs(w) + "px";
  box.style.height = Math.abs(h) + "px";
  box.style.left = (w < 0 ? e.clientX : startX) + "px";
  box.style.top = (h < 0 ? e.clientY : startY) + "px";
});

document.addEventListener("mouseup", async () => {

  if(!armed || !box) return;

  const rect = box.getBoundingClientRect();
  box.remove();
  box = null;
  armed = false;
  ocrBtn.style.background = "#007bff";

  try{

    /* ---------- OCR ---------- */

    const canvas = await screenshot(rect);
    const img = canvas.toDataURL("image/png");

    const result = await Tesseract.recognize(img,"eng",{logger:()=>{}});
    let text = (result.data.text || "").trim();

    if(!text){
      text = "[No OCR text found – sending anyway]";
    }

    showPanel(
`⏳ OCR done. Sending to SambaNova...

--- OCR TEXT ---
${text}`
    );

    /* ---------- SAMBANOVA ---------- */

    const { prompt, answer } = await askSambaNova(text);

    GM_setClipboard(prompt);

    showPanel(
`✅ OCR Copied
✅ Prompt Copied
✅ SambaNova Answer Received

--- OCR TEXT ---
${text}

--- PROMPT SENT TO SAMBANOVA ---
${prompt}

--- SAMBANOVA ANSWER ---
${answer}`
    );

  } catch(err){
    showPanel("[ERROR] " + String(err));
  }

});

})();