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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ rdt comment 3 "Great post!" # Comment on result #3
rdt-cli supports browser cookie extraction to authenticate with Reddit:

1. **Saved cookies** — loads from `~/.config/rdt-cli/credential.json`
2. **Browser cookies** — auto-detects installed browsers and extracts cookies (supports Chrome, Firefox, Edge, Brave)
2. **Browser cookies** — auto-detects installed browsers and extracts cookies (supports Chromium, Chrome, Firefox, Edge, Brave)

`rdt login` automatically tries all installed browsers and uses the first one with valid cookies.

Expand Down Expand Up @@ -364,7 +364,7 @@ rdt comment 3 "Great post!" # 评论
rdt-cli 支持浏览器 Cookie 提取来认证 Reddit:

1. **已保存 Cookie** — 从 `~/.config/rdt-cli/credential.json` 加载
2. **浏览器 Cookie** — 自动检测已安装浏览器并提取(支持 Chrome、Firefox、Edge、Brave)
2. **浏览器 Cookie** — 自动检测已安装浏览器并提取(支持 Chromium、Chrome、Firefox、Edge、Brave)

Cookie 保存后有效期 **7 天**,超时后自动尝试从浏览器刷新。

Expand Down
14 changes: 10 additions & 4 deletions rdt_cli/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import time
from typing import Any

from .constants import CONFIG_DIR, CREDENTIAL_FILE, REQUIRED_COOKIES
from .constants import BROWSER_COOKIE_FNS, CONFIG_DIR, CREDENTIAL_FILE, REQUIRED_COOKIES

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -140,7 +140,10 @@ def _extract_subprocess() -> Credential | None:
script = '''
import browser_cookie3, json
cookies = {}
for browser_fn in [browser_cookie3.chrome, browser_cookie3.firefox, browser_cookie3.edge, browser_cookie3.brave]:
for name in ["chromium", "chrome", "firefox", "edge", "brave"]:
browser_fn = getattr(browser_cookie3, name, None)
if browser_fn is None:
continue
try:
jar = browser_fn(domain_name=".reddit.com")
for c in jar:
Expand Down Expand Up @@ -178,12 +181,15 @@ def _extract_direct() -> Credential | None:
logger.warning("browser-cookie3 not available for direct extraction")
return None

for fn in [browser_cookie3.chrome, browser_cookie3.firefox, browser_cookie3.edge, browser_cookie3.brave]:
for name in BROWSER_COOKIE_FNS:
fn = getattr(browser_cookie3, name, None)
if fn is None:
continue
try:
jar = fn(domain_name=".reddit.com")
cookies = {c.name: c.value for c in jar}
if any(k in cookies for k in REQUIRED_COOKIES):
cred = Credential(cookies=cookies, source=f"browser:{fn.__name__}")
cred = Credential(cookies=cookies, source=f"browser:{name}")
save_credential(cred)
return cred
except Exception:
Expand Down
5 changes: 5 additions & 0 deletions rdt_cli/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
# ── Cookie keys required for authenticated sessions ─────────────────
REQUIRED_COOKIES = {"reddit_session"}

# Chromium first: Arch/Omarchy and many Linux defaults use it, not Chrome.
# browser_cookie3.chrome() only reads ~/.config/google-chrome and cannot
# decrypt Chromium's cookie DB, so chromium must be a first-class loader.
BROWSER_COOKIE_FNS = ("chromium", "chrome", "firefox", "edge", "brave")

# ── Sort options ────────────────────────────────────────────────────
SORT_OPTIONS = ["hot", "new", "top", "rising", "controversial", "best"]

Expand Down
6 changes: 6 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ def test_required_cookies(self):
from rdt_cli.constants import REQUIRED_COOKIES
assert "reddit_session" in REQUIRED_COOKIES

def test_browser_cookie_fns_include_chromium(self):
from rdt_cli.constants import BROWSER_COOKIE_FNS
assert BROWSER_COOKIE_FNS[0] == "chromium"
assert "chrome" in BROWSER_COOKIE_FNS
assert "firefox" in BROWSER_COOKIE_FNS

def test_search_sort_options(self):
from rdt_cli.constants import SEARCH_SORT_OPTIONS
assert "relevance" in SEARCH_SORT_OPTIONS
Expand Down