use night_fury_core::BrowserSession;
use serde_json::Value;
use crate::error::TailFinError;
pub async fn install_interceptor(
session: &BrowserSession,
pattern: &str,
) -> Result<(), TailFinError> {
let pattern_escaped = serde_json::to_string(pattern).unwrap_or_default();
let js = format!(
r#"
(() => {{
if (window.__tailfin_interceptor_active) return 'already_installed';
window.__tailfin_captured = [];
window.__tailfin_interceptor_active = true;
window.__tailfin_original_fetch = window.fetch;
const _originalFetch = window.fetch;
window.fetch = async function(...args) {{
const resp = await _originalFetch.apply(this, args);
try {{
const url = typeof args[0] === 'string' ? args[0] : (args[0]?.url || '');
if (url.includes({pattern_escaped})) {{
const clone = resp.clone();
const json = await clone.json();
window.__tailfin_captured.push({{ url: url, data: json }});
}}
}} catch (e) {{
// Silently ignore parse errors for non-JSON responses
}}
return resp;
}};
return 'installed';
}})()
"#
);
session.eval(&js).await?;
Ok(())
}
pub async fn read_captured(session: &BrowserSession) -> Result<Vec<Value>, TailFinError> {
let result = session
.eval("JSON.parse(JSON.stringify(window.__tailfin_captured || []))")
.await?;
match result {
Value::Array(arr) => Ok(arr),
Value::Null => Ok(vec![]),
_ => Err(TailFinError::Parse(
"unexpected interceptor result type".into(),
)),
}
}
pub async fn clear_captured(session: &BrowserSession) -> Result<(), TailFinError> {
session.eval("window.__tailfin_captured = []").await?;
Ok(())
}
pub async fn remove_interceptor(session: &BrowserSession) -> Result<(), TailFinError> {
let js = r#"
(() => {
if (window.__tailfin_interceptor_active) {
window.fetch = window.__tailfin_original_fetch || window.fetch;
window.__tailfin_interceptor_active = false;
window.__tailfin_captured = [];
delete window.__tailfin_original_fetch;
}
return 'removed';
})()
"#;
session.eval(js).await?;
Ok(())
}