Files
browser-cli/browser_cli/models.py
T
daniel156161 61b774a7a4
Package Extension / package-extension (push) Successful in 12s
Build & Publish Package / publish (push) Successful in 22s
add multi browser mode to arragate data from all browsers by tabs list, tabs count, group list, group count and windows list
remove (unnamed) into the group names just leave it a empty string, remove Focused on windows how should the browser know what windows are focused
2026-04-10 12:49:51 +02:00

134 lines
4.4 KiB
Python

"""
Typed dataclasses returned by the BrowserCLI Python API.
Each object is bound to a BrowserCLI instance so you can call actions
directly on it:
tabs = b.tabs_list()
tabs[0].close()
tabs[0].move(forward=True)
groups = b.group_list()
groups[0].tabs()
groups[0].add_tab("https://example.com")
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from browser_cli import BrowserCLI
# ── Tab ───────────────────────────────────────────────────────────────────────
@dataclass
class Tab:
"""A browser tab."""
id: int
window_id: int
active: bool
title: str
url: str
group_id: int | None = None
browser: str | None = None
_browser: BrowserCLI | None = field(default=None, repr=False, compare=False, init=False)
def _b(self) -> BrowserCLI:
if self._browser is None:
raise RuntimeError("Tab is not bound to a BrowserCLI instance")
return self._browser
def close(self) -> None:
"""Close this tab."""
self._b()._cmd("tabs.close", {"tabId": self.id})
def activate(self) -> None:
"""Switch browser focus to this tab."""
self._b()._cmd("tabs.active", {"tabId": self.id})
def reload(self) -> None:
"""Reload this tab."""
self._b()._cmd("navigate.reload", {"tabId": self.id})
def hard_reload(self) -> None:
"""Hard-reload this tab (bypass cache)."""
self._b()._cmd("navigate.hard_reload", {"tabId": self.id})
def move(
self, *,
forward: bool = False,
backward: bool = False,
group_id: int | None = None,
window_id: int | None = None,
index: int | None = None,
) -> None:
"""Move this tab.
Args:
forward: Move one position to the right within the window.
backward: Move one position to the left within the window.
group_id: Move into the tab group with this ID.
window_id: Move to the window with this ID.
index: Absolute position index in the target window.
"""
self._b()._cmd("tabs.move", {
"tabId": self.id,
"forward": forward,
"backward": backward,
"groupId": group_id,
"windowId": window_id,
"index": index,
})
def html(self) -> str:
"""Return the full HTML source of this tab."""
return self._b()._cmd("tabs.html", {"tabId": self.id})
def open(self, url: str, *, background: bool = False) -> None:
"""Navigate this tab to *url*."""
# Re-uses navigate.open which opens a new tab; for in-place navigation
# we target by tabId via the focus then navigate approach. For now we
# open a new tab in the same window as a convenience.
self._b()._cmd("navigate.open", {"url": url, "background": background})
# ── Group ─────────────────────────────────────────────────────────────────────
@dataclass
class Group:
"""A browser tab group."""
id: int
title: str
color: str
collapsed: bool
tab_count: int
browser: str | None = None
_browser: BrowserCLI | None = field(default=None, repr=False, compare=False, init=False)
def _b(self) -> BrowserCLI:
if self._browser is None:
raise RuntimeError("Group is not bound to a BrowserCLI instance")
return self._browser
def close(self) -> None:
"""Ungroup (and close) this tab group."""
self._b()._cmd("group.close", {"groupId": self.id})
def tabs(self) -> list[Tab]:
"""Return all tabs inside this group."""
return self._b().group_tabs(self.id)
def move(self, *, forward: bool = False, backward: bool = False) -> None:
"""Move this group forward or backward among groups."""
self._b()._cmd("group.move", {
"group": str(self.id),
"forward": forward,
"backward": backward,
})
def add_tab(self, url: str | None = None) -> int | None:
"""Open a new tab inside this group. Returns the new tab ID."""
return self._b().group_add_tab(self.id, url)