computers/default/scrapybara.py (173 lines of code) (raw):
import os
import time
from dotenv import load_dotenv
from scrapybara import Scrapybara
from playwright.sync_api import sync_playwright, Browser, Page
from utils import BLOCKED_DOMAINS
load_dotenv()
CUA_KEY_TO_SCRAPYBARA_KEY = {
"/": "slash",
"\\": "backslash",
"arrowdown": "Down",
"arrowleft": "Left",
"arrowright": "Right",
"arrowup": "Up",
"backspace": "BackSpace",
"capslock": "Caps_Lock",
"cmd": "Meta_L",
"delete": "Delete",
"end": "End",
"enter": "Return",
"esc": "Escape",
"home": "Home",
"insert": "Insert",
"option": "Alt_L",
"pagedown": "Page_Down",
"pageup": "Page_Up",
"tab": "Tab",
"win": "Meta_L",
}
class ScrapybaraBrowser:
"""
Scrapybara provides virtual desktops and browsers in the cloud. https://scrapybara.com
You can try OpenAI CUA for free at https://computer.new or read our CUA Quickstart at https://computer.new/cua.
"""
def get_environment(self):
return "browser"
def get_dimensions(self):
return (1024, 768)
def __init__(self):
self.client = Scrapybara(api_key=os.getenv("SCRAPYBARA_API_KEY"))
self._playwright = None
self._browser: Browser | None = None
self._page: Page | None = None
def __enter__(self):
print("Starting scrapybara browser")
blocked_domains = [
domain.replace("https://", "").replace("www.", "")
for domain in BLOCKED_DOMAINS
]
self.instance = self.client.start_browser(blocked_domains=blocked_domains)
print("Scrapybara browser started ₍ᐢ•(ܫ)•ᐢ₎")
print(
f"You can view and interact with the stream at {self.instance.get_stream_url().stream_url}"
)
self._playwright = sync_playwright().start()
self._browser = self._playwright.chromium.connect_over_cdp(
self.instance.get_cdp_url().cdp_url
)
self._page = self._browser.contexts[0].pages[0]
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Stopping scrapybara browser")
self.instance.stop()
print("Scrapybara browser stopped ₍ᐢ-(ェ)-ᐢ₎")
def goto(self, url: str) -> None:
self._page.goto(url)
def get_current_url(self) -> str:
return self.instance.get_current_url().current_url
def screenshot(self) -> str:
return self.instance.screenshot().base_64_image
def click(self, x: int, y: int, button: str = "left") -> None:
button = "middle" if button == "wheel" else button
self.instance.computer(
action="click_mouse",
click_type="click",
button=button,
coordinates=[x, y],
num_clicks=1,
)
def double_click(self, x: int, y: int) -> None:
self.instance.computer(
action="click_mouse",
click_type="click",
button="left",
coordinates=[x, y],
num_clicks=2,
)
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None:
self.instance.computer(
action="scroll",
coordinates=[x, y],
delta_x=scroll_x // 20,
delta_y=scroll_y // 20,
)
def type(self, text: str) -> None:
self.instance.computer(action="type_text", text=text)
def wait(self, ms: int = 1000) -> None:
time.sleep(ms / 1000)
# Scrapybara also has `self.instance.computer(action="wait", duration=ms / 1000)`
def move(self, x: int, y: int) -> None:
self.instance.computer(action="move_mouse", coordinates=[x, y])
def keypress(self, keys: list[str]) -> None:
mapped_keys = [
CUA_KEY_TO_SCRAPYBARA_KEY.get(key.lower(), key.lower()) for key in keys
]
self.instance.computer(action="press_key", keys=mapped_keys)
def drag(self, path: list[dict[str, int]]) -> None:
if not path:
return
path = [[point["x"], point["y"]] for point in path]
self.instance.computer(action="drag_mouse", path=path)
class ScrapybaraUbuntu:
"""
Scrapybara provides virtual desktops and browsers in the cloud.
You can try OpenAI CUA for free at https://computer.new or read our CUA Quickstart at https://computer.new/cua.
"""
def get_environment(self):
return "linux"
def get_dimensions(self):
return (1024, 768)
def __init__(self):
self.client = Scrapybara(api_key=os.getenv("SCRAPYBARA_API_KEY"))
def __enter__(self):
print("Starting Scrapybara Ubuntu instance")
blocked_domains = [
domain.replace("https://", "").replace("www.", "")
for domain in BLOCKED_DOMAINS
]
self.instance = self.client.start_ubuntu(blocked_domains=blocked_domains)
print("Scrapybara Ubuntu instance started ₍ᐢ•(ܫ)•ᐢ₎")
print(
f"You can view and interact with the stream at {self.instance.get_stream_url().stream_url}"
)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Stopping Scrapybara Ubuntu instance")
self.instance.stop()
print("Scrapybara Ubuntu instance stopped ₍ᐢ-(ェ)-ᐢ₎")
def screenshot(self) -> str:
return self.instance.screenshot().base_64_image
def click(self, x: int, y: int, button: str = "left") -> None:
button = "middle" if button == "wheel" else button
self.instance.computer(
action="click_mouse",
click_type="click",
button=button,
coordinates=[x, y],
num_clicks=1,
)
def double_click(self, x: int, y: int) -> None:
self.instance.computer(
action="click_mouse",
click_type="click",
button="left",
coordinates=[x, y],
num_clicks=2,
)
def scroll(self, x: int, y: int, scroll_x: int, scroll_y: int) -> None:
self.instance.computer(
action="scroll",
coordinates=[x, y],
delta_x=scroll_x // 20,
delta_y=scroll_y // 20,
)
def type(self, text: str) -> None:
self.instance.computer(action="type_text", text=text)
def wait(self, ms: int = 1000) -> None:
time.sleep(ms / 1000)
# Scrapybara also has `self.instance.computer(action="wait", duration=ms / 1000)`
def move(self, x: int, y: int) -> None:
self.instance.computer(action="move_mouse", coordinates=[x, y])
def keypress(self, keys: list[str]) -> None:
mapped_keys = [
CUA_KEY_TO_SCRAPYBARA_KEY.get(key.lower(), key.lower()) for key in keys
]
self.instance.computer(action="press_key", keys=mapped_keys)
def drag(self, path: list[dict[str, int]]) -> None:
if not path:
return
path = [[point["x"], point["y"]] for point in path]
self.instance.computer(action="drag_mouse", path=path)
def get_current_url(self):
return None