nordnet_api/resources/news.rs
1//! Resource methods for the `news` API group.
2//!
3//! # Operations
4//!
5//! | Method | Op | Path |
6//! |--------|-----|------|
7//! | GET | `get_news_item` | `/news/{item_id}` |
8//! | GET | `list_news_sources` | `/news_sources` |
9//!
10//!
11//! ## Multi-ID lookups for `get_news_item`
12//!
13//! The Nordnet API path parameter for `get_news_item` accepts a
14//! comma-separated list of news article IDs. This method covers the
15//! single-ID case via the [`NewsId`] newtype, mirroring the
16//! [`Client::get_market`] pattern. A future helper may be added for
17//! multi-ID lookups when needed (Phase 3X).
18//!
19//!
20//! ## 204 No Content
21//!
22//! `GET /news/{item_id}` may return HTTP 204 (No Content) when no matching
23//! article is found. The base [`Client::get`] method attempts to parse the
24//! empty response body as JSON, which fails. `get_news_item` detects this
25//! specific case (a [`Error::Decode`] with an empty body) and maps it to
26//! an empty `Vec`, mirroring [`Client::get_country`] / [`Client::get_market`].
27//!
28//!
29//! ## `body_format` query parameter
30//!
31//! The `body_format` query parameter is documented as deprecated with no
32//! effect on the response. It is intentionally NOT exposed on this method.
33
34use crate::client::Client;
35use crate::error::Error;
36use nordnet_model::models::news::{NewsArticle, NewsId, NewsSource};
37
38impl Client {
39 /// `GET /news/{item_id}` — Retrieve a news article by ID.
40 ///
41 /// Returns an empty `Vec` when the API responds with 204 No Content
42 /// (no matching article).
43 ///
44 /// # Errors
45 ///
46 /// Returns [`Error::BadRequest`] (400), [`Error::Unauthorized`] (401),
47 /// [`Error::TooManyRequests`] (429), or [`Error::ServiceUnavailable`]
48 /// (503) as documented.
49 #[doc(alias = "GET /news/{item_id}")]
50 pub async fn get_news_item(&self, id: NewsId) -> Result<Vec<NewsArticle>, Error> {
51 let path = format!("/news/{}", id.0);
52 match self.get::<Vec<NewsArticle>>(&path).await {
53 Ok(v) => Ok(v),
54 // HTTP 204 No Content: the base client sees an empty body and
55 // produces a Decode error. Map it to an empty Vec instead.
56 Err(Error::Decode { ref body, .. }) if body.trim().is_empty() => Ok(vec![]),
57 Err(e) => Err(e),
58 }
59 }
60
61 /// `GET /news_sources` — Returns the news sources the user has access to.
62 ///
63 /// # Errors
64 ///
65 /// Returns [`Error::Unauthorized`] (401), [`Error::TooManyRequests`]
66 /// (429), or [`Error::ServiceUnavailable`] (503) as documented.
67 #[doc(alias = "GET /news_sources")]
68 pub async fn list_news_sources(&self) -> Result<Vec<NewsSource>, Error> {
69 self.get("/news_sources").await
70 }
71}