Automatisieren der Erstellung und Übermittlung von LeetCode-Lösungsbeiträgen: Herausforderungen mit DOM-Manipulation, ClJavaScript

Javascript-Forum
Guest
 Automatisieren der Erstellung und Übermittlung von LeetCode-Lösungsbeiträgen: Herausforderungen mit DOM-Manipulation, Cl

Post by Guest »

Ich erstelle eine Chrome-Erweiterung, um die Erstellung von Lösungsbeiträgen auf LeetCode zu automatisieren, nachdem eine Lösung angenommen wurde. Das Ziel ist: 1. Öffnen Sie die Seite „Lösung posten“.2. Füllen Sie das Eingabefeld „Titel“ automatisch mit einer benutzerdefinierten Zeichenfolge.3. Füllen Sie den Monaco-Editor mit einer formatierten Lösungsvorlage.
Das Setup
1. Umgebung:
• Chrome-Erweiterung (Manifest V3) mit Plasmo Framework.
• Die Erweiterung enthält:
• Ein Hintergrundskript für die Tab-Erstellung und Nachrichtenübermittlung.
• Ein Inhaltsskript für DOM-Interaktion auf der Seite „Lösung veröffentlichen“.
2. Ansatz:
• Das Hintergrundskript öffnet die Lösungsbeitragsseite und sendet eine Nachricht mit der einzufügenden Vorlage an das Inhaltsskript.
• Das Inhaltsskript übernimmt die DOM-Manipulation, einschließlich:
• Eingeben von Text in das Eingabefeld.
• Kopieren und Einfügen von Inhalten in den Monaco-Editor.
Herausforderungen und was wir versucht haben
  • Das Titeleingabefeld füllen
Problem:
Das Eingabefeld wird manchmal teilweise aktualisiert (z. B. wird „Automatisierter Titel“ zu „tomierter Titel“) oder überhaupt nicht aktualisiert.
Versuche:
1. Wert direkt festlegen:

Code: Select all

inputElement.value = "Automated Title";
inputElement.dispatchEvent(new Event("input", { bubbles: true }));
inputElement.dispatchEvent(new Event("change", { bubbles: true }));
•Ergebnis: Funktioniert manchmal, aktualisiert das Feld jedoch häufig nicht ordnungsgemäß oder löst Listener aus, die den Wert zurücksetzen.
2. Tastendruckereignisse simulieren :

Code: Select all

for (const char of text) {
inputElement.value += char;
inputElement.dispatchEvent(new KeyboardEvent("keydown", { key: char }));
inputElement.dispatchEvent(new KeyboardEvent("keypress", { key: char }));
inputElement.dispatchEvent(new KeyboardEvent("keyup", { key: char }));
}
•Ergebnis: Dies funktioniert besser, führt aber gelegentlich zu unvollständigem Text. Es scheint, dass externe Ereignis-Listener oder DOM-Updates den Prozess stören.
  • Text in die Zwischenablage kopieren und einfügen:

Code: Select all

await navigator.clipboard.writeText("Automated Title");
const pasteEvent = new ClipboardEvent("paste", { bubbles: true });
inputElement.dispatchEvent(pasteEvent);
•Ergebnis: Die Zwischenablage-API schlägt mit einem NotAllowedError fehl, sofern sie nicht durch eine Benutzerinteraktion (z. B. Klicken auf eine Schaltfläche) ausgelöst wird.
  • Auffüllen des Monaco-Editors
Problem:
Der Monaco-Editor verlässt sich auf seine monaco.editor.getModels()[ 0] API, auf die nicht direkt zugegriffen werden kann das Inhaltsskript, da das Skript in einem anderen Ausführungskontext ausgeführt wird.
Versuche:
1. Verwenden der Monaco-API:

Code: Select all

const model = monaco.editor.getModels()[0];
model.setValue(template);
•Ergebnis: Funktioniert perfekt in der Browserkonsole, schlägt jedoch im Inhaltsskript fehl, da Monaco nicht definiert ist.
2. Code in die Hauptwelt einfügen:
• Eine Funktion mit chrome.scripting.executeScript eingefügt:

Code: Select all

chrome.scripting.executeScript({
target: { tabId: tab.id },
world: "MAIN",
func: pasteTemplateIntoPage,
args: [template],
});
•Ergebnis: Monaco ist in der Hauptwelt aufgrund von CSP-Einschränkungen undefiniert.
  • Handhabung Ratenbegrenzung (429 Fehler)
Problem:
Gelegentlich löst das Festlegen des Titels LeetCodes Backend-Anfragen aus, die zu 429 Too Many Requests führen.
Versuche:
1. Verzögerungen zwischen Aktionen hinzugefügt.
2. Reduzierte unnötige Ereignisauslösung.
3. Entprellen wurde verwendet, um schnelle Interaktionen zu vermeiden.
•Ergebnis: Die Ratenbegrenzung bleibt bestehen, wenn Aktionen zu häufig sind.
Codeausschnitte
Hintergrundskript:

Code: Select all

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === "openSubmissionPage") {
chrome.tabs.create({ url: message.url, active: true }, (tab) => {
if (tab?.id) {
chrome.tabs.onUpdated.addListener(function listener(tabId, changeInfo) {
if (tabId === tab.id && changeInfo.status === "complete") {
chrome.tabs.onUpdated.removeListener(listener);
chrome.tabs.sendMessage(tab.id, { action: "pasteTemplate", template:            message.template });
}
});
}
});
Inhaltsskript:

Code: Select all

async function typeIntoInputField(selector, text) {
const inputElement = document.querySelector(selector);
if (!inputElement) return;

inputElement.value = "";
for (const char of text) {
inputElement.value += char;
inputElement.dispatchEvent(new KeyboardEvent("keydown", { key: char }));
inputElement.dispatchEvent(new KeyboardEvent("keypress", { key: char }));
inputElement.dispatchEvent(new KeyboardEvent("keyup", { key: char }));
await new Promise((r) => setTimeout(r, 100));
}
}
Wobei wir Hilfe benötigen:
1. Wie können wir den Wert des Titeleingabefelds zuverlässig festlegen (z. B. „Automatisierter Titel“) und gleichzeitig Teilaktualisierungen oder Zurücksetzungen vermeiden?
2. Wie kann ich in einer Chrome-Erweiterung am besten auf den Monaco-Editor zugreifen und ihn bearbeiten?
3. Wie können wir vermeiden, dass die Geschwindigkeitsbegrenzung von LeetCode (429 Fehler) während der DOM-Manipulation ausgelöst wird?
4. Gibt es andere robuste Methoden, um Benutzerinteraktionen (Eingabe, Einfügen) programmgesteuert zu simulieren?
Was wir versucht haben:
• Direkte DOM-Manipulation (Wert, setAttribute).
• Simulieren von Tastenanschlägen mit KeyboardEvent.
• Kopieren in die Zwischenablage und Einfügen mit ClipboardEvent.
• Einfügen von Code in die Hauptwelt, um auf die Monaco-API zuzugreifen.
Trotz allem diese Trotz aller Versuche habe ich immer noch Probleme mit der Zuverlässigkeit und Kompatibilität. Für Ratschläge, Einblicke oder alternative Ansätze wäre ich sehr dankbar!

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post