mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
fix(sentiment): treat an empty MSN response as no votes, not a parse error
MSN SentimentBrowser returns `[]` for every IDX ticker checked live (BBCA, BBRI, TLKM), so `stocks sentiment` always failed with PARSEERROR. Return empty statistics instead; the table prints a one-line notice and JSON gets `"statistics": []` with exit 0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ld3fDSDiBzAaQvgZJX5NKM
This commit is contained in:
parent
0ba3d805a7
commit
f77f81c97b
2 changed files with 20 additions and 3 deletions
|
|
@ -460,9 +460,15 @@ pub(super) fn parse_sentiment(
|
||||||
symbol: &str,
|
symbol: &str,
|
||||||
raw: &[RawSentiment],
|
raw: &[RawSentiment],
|
||||||
) -> Result<SentimentData, IdxError> {
|
) -> Result<SentimentData, IdxError> {
|
||||||
let item = raw
|
// MSN answers `[]` for tickers nobody has voted on (all IDX names as of
|
||||||
.first()
|
// 2026-10). That is "no votes", not a malformed response.
|
||||||
.ok_or_else(|| IdxError::ParseError("no sentiment data".into()))?;
|
let Some(item) = raw.first() else {
|
||||||
|
let ticker = ticker_from_symbol(symbol).unwrap_or_default();
|
||||||
|
return Ok(SentimentData {
|
||||||
|
symbol: normalized_symbol(symbol, &ticker),
|
||||||
|
statistics: Vec::new(),
|
||||||
|
});
|
||||||
|
};
|
||||||
let stats = item
|
let stats = item
|
||||||
.sentiment_statistics
|
.sentiment_statistics
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
|
@ -929,6 +935,13 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn empty_sentiment_response_is_empty_data_not_an_error() {
|
||||||
|
let sentiment = parse_sentiment("BBCA", &[]).expect("empty sentiment is valid");
|
||||||
|
assert_eq!(sentiment.symbol, "BBCA.JK");
|
||||||
|
assert!(sentiment.statistics.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parses_msn_chart_price_only_fixture_as_synthetic_ohlc() {
|
fn parses_msn_chart_price_only_fixture_as_synthetic_ohlc() {
|
||||||
let raw: Vec<RawChartResponse> = serde_json::from_str(include_str!(
|
let raw: Vec<RawChartResponse> = serde_json::from_str(include_str!(
|
||||||
|
|
|
||||||
|
|
@ -768,6 +768,10 @@ pub fn print_earnings(report: &EarningsReport) -> Result<(), IdxError> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print_sentiment(data: &SentimentData) -> Result<(), IdxError> {
|
pub fn print_sentiment(data: &SentimentData) -> Result<(), IdxError> {
|
||||||
|
if data.statistics.is_empty() {
|
||||||
|
println!("No sentiment votes for {}.", data.symbol);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
let mut table = Table::new();
|
let mut table = Table::new();
|
||||||
table
|
table
|
||||||
.load_preset(UTF8_FULL)
|
.load_preset(UTF8_FULL)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue