twstock/lib.rs
1//! # Taiwan Stock Exchange (TWSE) API
2//!
3//! `twstock` is a library for fetching data from the Taiwan Stock Exchange (TWSE) API.
4//!
5//! Behind the scenes, it uses the reqwest crate to make HTTP requests to their server.
6//!
7//! # Example:
8//! ```rust
9//! use twstock::*;
10//!
11//! async fn fetch() {
12//! let client = Client::new();
13//! match client
14//! .realtime()
15//! .fetch(Stock {
16//! kind: StockKind::Live,
17//! code: 2330,
18//! })
19//! .await
20//! {
21//! Ok(x) => assert_eq!(x.name, "台積電"),
22//! Err(err) => match err {
23//! Error::MarketClosed => {}
24//! _ => panic!("unexpected error: {:?}", err),
25//! },
26//! };
27//! }
28//! ```
29//!
30//! # Features:
31//! - `serde`: Enable serde support
32//! - `native-tls`: Use the native-tls backend
33//! - `native-tls-vendored`: Use the native-tls backend with vendored OpenSSL
34//! - `rustls-tls`: Use the rustls backend
35//!
36//! Don't forget to disable default features if you want to use a specific TLS backend.
37
38pub mod history;
39pub mod list;
40pub mod realtime;
41
42use reqwest::Client as HttpClient;
43
44fn get_time_zone() -> chrono::FixedOffset {
45 chrono::FixedOffset::east_opt(8 * 3600).unwrap()
46}
47
48/// Error type that may occur when interacting with the TWSE API
49#[derive(Debug, thiserror::Error)]
50pub enum Error {
51 #[error(transparent)]
52 Reqwest(#[from] reqwest::Error),
53 #[error("Rate limit exceeded")]
54 RateLimitExceeded,
55 /// Incompatible API, the upstream API has changed
56 #[error("incompatible upstream api")]
57 IncompatibleApi,
58 #[error("date does not exist")]
59 DateDoesNotExist,
60 #[error("Error message from upstream: `{0}`")]
61 StatMessage(String),
62 #[error("market is closed")]
63 MarketClosed,
64}
65
66#[derive(Debug, Hash, Clone, PartialEq, PartialOrd, Default)]
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68/// Stock identifier and its variant
69pub struct Stock {
70 pub kind: StockKind,
71 pub code: u32,
72}
73
74#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
75#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
76/// variant of stock
77///
78/// The number is intentionally set to match the value used in the upstream API
79pub enum StockKind {
80 #[default]
81 Live = 2,
82 OverTheCounter = 4,
83}
84
85/// Client for fetching data from the Taiwan Stock Exchange (TWSE) API
86#[derive(Default)]
87pub struct Client(HttpClient);
88
89impl Client {
90 /// Create a new client
91 pub fn new() -> Self {
92 Self::default()
93 }
94}
95
96// if not TLS feature enabled, compile error
97#[cfg(not(any(
98 feature = "default-tls",
99 feature = "native-tls",
100 feature = "native-tls-vendored",
101 feature = "rustls-tls"
102)))]
103compile_error!("TLS feature is not enabled");