1pub(crate) use http::{header, HeaderValue, Request};
2use longportwhale_httpcli::{HttpClient, HttpClientConfig};
3use num_enum::IntoPrimitive;
4use tokio_tungstenite::tungstenite::client::IntoClientRequest;
5
6use crate::error::Result;
7
8const TRADE_WS_URL: &str = "wss://openapi-trade.longportapp.com";
9
10#[derive(Debug, Copy, Clone, PartialEq, Eq, IntoPrimitive)]
12#[allow(non_camel_case_types)]
13#[repr(i32)]
14pub enum Language {
15 ZH_CN = 0,
17 ZH_HK = 2,
19 EN = 1,
21}
22
23impl Language {
24 pub(crate) fn as_str(&self) -> &'static str {
25 match self {
26 Language::ZH_CN => "zh-CN",
27 Language::ZH_HK => "zh-HK",
28 Language::EN => "en",
29 }
30 }
31}
32
33#[derive(Debug, Clone)]
35pub struct Config {
36 pub(crate) http_cli_config: HttpClientConfig,
37 pub(crate) trade_ws_url: String,
38 pub(crate) language: Language,
39}
40
41impl Config {
42 pub fn new(
44 app_key: impl Into<String>,
45 app_secret: impl Into<String>,
46 access_token: impl Into<String>,
47 ) -> Self {
48 Self {
49 http_cli_config: HttpClientConfig::new(app_key, app_secret, access_token),
50 trade_ws_url: TRADE_WS_URL.to_string(),
51 language: Language::EN,
52 }
53 }
54
55 pub fn from_env() -> Result<Self> {
69 let _ = dotenv::dotenv();
70
71 let http_cli_config = HttpClientConfig::from_env()?;
72 let trade_ws_url =
73 std::env::var("LONGPORT_TRADE_WS_URL").unwrap_or_else(|_| TRADE_WS_URL.to_string());
74
75 Ok(Config {
76 http_cli_config,
77 trade_ws_url,
78 language: Language::EN,
79 })
80 }
81
82 #[must_use]
88 pub fn http_url(mut self, url: impl Into<String>) -> Self {
89 self.http_cli_config = self.http_cli_config.http_url(url);
90 self
91 }
92
93 #[must_use]
99 pub fn trade_ws_url(self, url: impl Into<String>) -> Self {
100 Self {
101 trade_ws_url: url.into(),
102 ..self
103 }
104 }
105
106 pub fn language(self, language: Language) -> Self {
110 Self { language, ..self }
111 }
112
113 pub fn create_http_client(&self) -> HttpClient {
115 HttpClient::new(self.http_cli_config.clone())
116 .header(header::ACCEPT_LANGUAGE, self.language.as_str())
117 }
118
119 fn create_ws_request(&self, url: &str) -> tokio_tungstenite::tungstenite::Result<Request<()>> {
120 let mut request = url.into_client_request()?;
121 request.headers_mut().append(
122 header::ACCEPT_LANGUAGE,
123 HeaderValue::from_str(self.language.as_str()).unwrap(),
124 );
125 Ok(request)
126 }
127
128 #[inline]
129 pub(crate) fn create_trade_ws_request(
130 &self,
131 ) -> tokio_tungstenite::tungstenite::Result<Request<()>> {
132 self.create_ws_request(&self.trade_ws_url)
133 }
134}