Download Game! Currently 103 players. Last logged in:UglinessNikanaJagomanArcanaut

Blitzer's Blog >> 72765

Back to blogs index
Posted: 24 Sep 2026 12:57 [ permalink ]
import asyncio
from playwright.async_api import async_playwright

class CDPSniper:
    def __init__(self, port: int = 9222):
        self.cdp_url = f"http://localhost:{port}"
        self.playwright = None
        self.browser = None

    async def connect(self):
        """Avaa pysyvC$n yhteyden selaimeen suorituskyvyn maksimoimiseksi."""
        if not self.playwright:
            self.playwright = await async_playwright().start()
        if not self.browser:
            self.browser = await self.playwright.chromium.connect_over_cdp(self
.cdp_url)

    async def disconnect(self):
        """Sulkee yhteyden."""
        if self.browser:
            await self.browser.close()
            self.browser = None
        if self.playwright:
            await self.playwright.stop()
            self.playwright = None

    async def get_element_at_absolute_pos(self, x: int, y: int):
        """
        Muuntaa X11 absoluuttiset koordinaatit selaimen viewport-koordinaateiks
i
        ja palauttaa elementin tiedot.
        """
        if not self.browser:
            await self.connect()

        # Oletetaan, ettC$ haluamme aina operoida pC$C$llimmC$isellC$ sivulla
        # (Monimutkaisemmissa X11-setupissa voit iteroida browser.contexts)
        context = self.browser.contexts[0]
        page = context.pages[0]

        # Injektoitava JavaScript-koodi
        js_snippet = """
        ([absX, absY]) => {
            // 1. Offsetin laskenta: Selaimen sijainti nC$ytC6llC$ +
UI-reunukset
            // window.screenY kertoo selainikkunan ylC$reunan absoluuttisen
sijainnin
            // window.outerHeight - innerHeight kertoo selainpalkin
(vC$lilehdet, url) koon
            const uiTopOffset = window.outerHeight - window.innerHeight;
            
            // Modernissa Chromessa sivureunukset ovat usein 0px tai
minimaalisia
            const uiLeftOffset = window.outerWidth - window.innerWidth;
            
            const viewportTopOnScreen = window.screenY + uiTopOffset;
            
            // Jaetaan vasen offset (esim. varjo/reunus) kahdella
            const viewportLeftOnScreen = window.screenX + (uiLeftOffset > 0 ?
(uiLeftOffset / 2) : 0);

            // 2. Koordinaattimuunnos: Absoluuttinen -> Viewport-relatiivinen
            const relX = absX - viewportLeftOnScreen;
            const relY = absY - viewportTopOnScreen;

            // Tarkistetaan osuuko klikkaus edes sivun sisC$lle
            if (relX < 0 || relY < 0 || relX > window.innerWidth || relY >
window.innerHeight) {
                return { 
                    status: "miss", 
                    reason: "Koordinaatti on viewportin ulkopuolella", 
                    rel_coords: { x: relX, y: relY } 
                };
            }

            // 3. JS Hit-Testing
            let el = document.elementFromPoint(relX, relY);
            if (!el) {
                return { status: "miss", reason: "Ei elementtiC$ tC$ssC$
pisteessC$", rel_coords: { x: relX, y: relY } };
            }

            // Jos elementti on iframe, elementFromPoint palauttaa iframen, ei
sen sisC$ltC6C$.
            const isIframe = el.tagName.toLowerCase() === 'iframe';

            // 4. Attribuuttien poiminta
            // Puhdistetaan teksti rivinvaihdoista ja turhasta tyhjC$stC$
tilasta
            const cleanText = (el.textContent || '').replace(/\\s+/g, '
').trim().substring(0, 150);

            return {
                status: "hit",
                rel_coords: { x: Math.round(relX), y: Math.round(relY) },
                element: {
                    tag: el.tagName.toLowerCase(),
                    role: el.getAttribute('role'),
                    test_id: el.getAttribute('data-testid') ||
el.getAttribute('data-som-id'),
                    aria_label: el.getAttribute('aria-label'),
                    text: cleanText,
                    id: el.id,
                    classes: el.className,
                    is_iframe: isIframe
                }
            };
        }
        """

        try:
            # Suoritetaan koko logiikka suoraan selaimen sisC$llC$ yhdellC$
CDP-kutsulla
            result = await page.evaluate(js_snippet, [x, y])
            return result
        except Exception as e:
            return {"status": "error", "reason": str(e)}

# === Esimerkki X11-kuuntelijan integroinnista ===
if __name__ == "__main__":
    async def main():
        sniper = CDPSniper(port=9222)
        
        # Simuloidaan X11-kuuntelijalta tuleva klikkaus
        click_x11_x = 835
        click_x11_y = 998
        
        print(f"Ammutaan koordinaatteihin X:{click_x11_x}, Y:{click_x11_y}...")
        
        result = await sniper.get_element_at_absolute_pos(click_x11_x,
click_x11_y)
        
        import json
        print(json.dumps(result, indent=2, ensure_ascii=False))
        
        await sniper.disconnect()

    asyncio.run(main())