Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions agent_reach/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ def main():
p_conf.add_argument("value", nargs="*", help="The value(s) to set")
p_conf.add_argument("--from-browser", metavar="BROWSER",
choices=["chrome", "firefox", "edge", "brave", "opera"],
help="Auto-extract ALL platform cookies from browser (chrome/firefox/edge/brave/opera)")
help="Auto-extract platform cookies from browser")
p_conf.add_argument("--platform", metavar="PLATFORM",
choices=["twitter", "xhs", "bilibili", "xueqiu"],
help="Only extract cookies for this platform (omit for all)")

# ── doctor ──
p_doctor = sub.add_parser("doctor", help="Check platform availability")
Expand Down Expand Up @@ -1031,7 +1034,10 @@ def _cmd_configure(args):
print(f"Extracting cookies from {browser}...")
print()

results = configure_from_browser(browser, config)
results = configure_from_browser(
browser, config,
platform=getattr(args, "platform", None),
)

found_any = False
for platform, success, message in results:
Expand Down
32 changes: 24 additions & 8 deletions agent_reach/cookie_extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,27 @@
]


def extract_all(browser: str = "chrome") -> Dict[str, dict]:
def extract_all(browser: str = "chrome", platform: str | None = None) -> Dict[str, dict]:
"""
Extract cookies for all supported platforms from the specified browser.

Extract cookies for supported platforms from the specified browser.

When *platform* is given, only that platform's cookies are
extracted (#446). Otherwise all platforms are extracted.

Returns:
{
"twitter": {"auth_token": "xxx", "ct0": "yyy"},
"xhs": {"cookie_string": "a=1; b=2; ..."},
"bilibili": {"SESSDATA": "xxx", "bili_jct": "yyy"},
}
"""
# Filter platforms if a specific one is requested
specs = PLATFORM_SPECS
if platform:
specs = [s for s in PLATFORM_SPECS if s["config_key"] == platform]
if not specs:
raise ValueError(f"Unknown platform: {platform}")

# Try rookiepy first (Rust-based, more stable), fallback to browser_cookie3
use_rookiepy = False
try:
Expand Down Expand Up @@ -113,7 +123,7 @@ def __init__(self, d):

results = {}

for spec in PLATFORM_SPECS:
for spec in specs:
platform_cookies = {}
all_cookies_for_domain = []

Expand Down Expand Up @@ -229,16 +239,22 @@ def _sync_bird_env(auth_token: str, ct0: str) -> None:
_sync_bird_credentials = _sync_bird_env


def configure_from_browser(browser: str, config) -> List[Tuple[str, bool, str]]:
def configure_from_browser(
browser: str, config, platform: str | None = None
) -> List[Tuple[str, bool, str]]:
"""
Extract cookies and configure all found platforms.

Extract cookies and configure found platforms.

When *platform* is given, only that platform is extracted and
configured, avoiding over-collection of unrelated browser cookies
(#446).

Returns list of (platform_name, success, message) tuples.
"""
results_list = []

try:
extracted = extract_all(browser)
extracted = extract_all(browser, platform=platform)
except Exception as e:
return [("Browser", False, str(e))]

Expand Down
31 changes: 31 additions & 0 deletions tests/test_cookie_extract_perms.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,34 @@ def test_configure_xhs_cookies_tightens_local_fallback_file(tmp_path, monkeypatc
data = json.loads(cookie_path.read_text(encoding="utf-8"))
assert data[0]["name"] == "web_session"
assert data[0]["value"] == "xhs_secret"


class TestPlatformFilter:
"""extract_all / configure_from_browser --platform filter (#446)."""

def test_extract_all_filters_by_platform(self):
"""extract_all with platform='twitter' only returns twitter."""
from agent_reach.cookie_extract import PLATFORM_SPECS, extract_all

# All browser-backed tests are skipped when no browser is available;
# we test the filter logic at the spec level.
twitter_specs = [s for s in PLATFORM_SPECS if s["config_key"] == "twitter"]
assert len(twitter_specs) == 1
assert twitter_specs[0]["name"] == "Twitter/X"

def test_unknown_platform_raises(self):
"""extract_all with an unknown platform raises ValueError."""
import pytest
from agent_reach.cookie_extract import extract_all

with pytest.raises(ValueError, match="Unknown platform"):
extract_all("chrome", platform="nonexistent")

def test_platform_filter_accepts_all_valid_keys(self):
"""Every config_key in PLATFORM_SPECS is a valid --platform value."""
from agent_reach.cookie_extract import PLATFORM_SPECS

for spec in PLATFORM_SPECS:
key = spec["config_key"]
filtered = [s for s in PLATFORM_SPECS if s["config_key"] == key]
assert len(filtered) >= 1, f"no spec matches config_key={key}"