diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index aa8c6dd..4fd3982 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -292,29 +292,24 @@ async fn fetch_market_data( .build() .map_err(|e| e.to_string())?; - let joined = symbols.join(","); - let url = format!( - "https://query1.finance.yahoo.com/v7/finance/quote?symbols={}", - joined - ); - let body: serde_json::Value = client - .get(&url) - .send() - .await - .map_err(|e| e.to_string())? - .json() - .await - .map_err(|e| e.to_string())?; - + // v7/finance/quote now requires a cookie+crumb pair Yahoo stopped issuing + // to plain API clients (returns 401); v8 chart still answers anonymously, + // one symbol per request. let mut prices = std::collections::HashMap::new(); - if let Some(results) = body["quoteResponse"]["result"].as_array() { - for item in results { - let sym = item["symbol"].as_str().unwrap_or("").to_string(); - // regularMarketPrice is in the quote currency (USD for US stocks) - if let Some(price) = item["regularMarketPrice"].as_f64() { - if price > 0.0 && !sym.is_empty() { - prices.insert(sym, price); - } + for sym in &symbols { + let url = format!( + "https://query1.finance.yahoo.com/v8/finance/chart/{}?range=1d&interval=1d", + sym + ); + let Ok(resp) = client.get(&url).send().await else { + continue; + }; + let Ok(body) = resp.json::().await else { + continue; + }; + if let Some(price) = body["chart"]["result"][0]["meta"]["regularMarketPrice"].as_f64() { + if price > 0.0 { + prices.insert(sym.clone(), price); } } } diff --git a/src/main.ts b/src/main.ts index 71ec438..ba24916 100644 --- a/src/main.ts +++ b/src/main.ts @@ -548,7 +548,8 @@ async function refreshRates(force = false): Promise { // ---------- market data -const MARKET_SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META", "SBER", "GAZP"]; +// Yahoo delisted Russian tickers (SBER/GAZP) in 2022 — dropped, they always miss. +const MARKET_SYMBOLS = ["AAPL", "MSFT", "GOOGL", "AMZN", "TSLA", "NVDA", "META"]; let marketPrices: Record = {}; let marketFetchedAt = 0;