#![allow(dead_code)]
use super::helpers::{fmt_date, json_f64_opt, json_str};
use super::types::{ForecastCninfo, RankThsEntry};
use crate::client::AkShareClient;
use crate::error::{Error, Result};
const DEFAULT_HEXIN_V: &str = "D3GBCzofiVFQJGEFaqWKYPGlGIFsVoWqYoWP0fQNQFJYlY0G4JdlVYoGNl8C";
impl AkShareClient {
async fn ths_rank_fetch(
&self,
url_template: &str,
page: i64,
hexin_v: &str,
) -> Result<Vec<serde_json::Value>> {
let url = url_template.replace("{}", &page.to_string());
let resp = self.get(&url)
.header("Accept", "text/html, */*; q=0.01")
.header("Accept-Encoding", "gzip, deflate")
.header("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8")
.header("Cache-Control", "no-cache")
.header("Connection", "keep-alive")
.header("hexin-v", hexin_v)
.header("Host", "data.10jqka.com.cn")
.header("Pragma", "no-cache")
.header("Referer", "http://data.10jqka.com.cn/funds/hyzjl/")
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36")
.header("X-Requested-With", "XMLHttpRequest")
.send().await.map_err(Error::from)?
.error_for_status().map_err(Error::from)?;
let text = resp.text().await.map_err(Error::from)?;
Ok(vec![serde_json::json!({"html": text})])
}
pub async fn stock_rank_cxd_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f12,f14",
"5000",
"f3",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_cxfl_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f12,f14",
"5000",
"f3",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_cxg_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f12,f14",
"5000",
"f3",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_cxsl_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f12,f14",
"5000",
"f3",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_lxsz_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f12,f14",
"5000",
"f3",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_lxxd_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f12,f14",
"5000",
"f3",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_ljqd_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f10,f12,f14",
"5000",
"f10",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: json_f64_opt(v, "f10"),
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_ljqs_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self
.clist_spot_fetch(
"m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048",
"f2,f3,f10,f12,f14",
"5000",
"f10",
)
.await?;
Ok(data
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: json_f64_opt(v, "f10"),
amount: None,
extra: None,
})
.collect())
}
pub async fn stock_rank_xstp_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self.cistock_rank_fetch("f3", "-1").await?;
Ok(data)
}
pub async fn stock_rank_xxtp_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self.cistock_rank_fetch("f3", "-1").await?;
Ok(data)
}
pub async fn stock_rank_xzjp_ths(&self) -> Result<Vec<RankThsEntry>> {
let data = self.cistock_rank_fetch("f3", "1").await?;
Ok(data)
}
pub async fn stock_rank_forecast_cninfo(&self, date: &str) -> Result<Vec<ForecastCninfo>> {
let url = "http://webapi.cninfo.com.cn/api/sysapi/p_sysapi1133";
let sd = fmt_date(date);
let resp = self
.post(url)
.form(&[("sdate", sd.as_str())])
.header("User-Agent", "Mozilla/5.0")
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let json: serde_json::Value = resp.json().await.map_err(Error::from)?;
let records = json
.get("records")
.and_then(|r| r.as_array())
.cloned()
.unwrap_or_default();
Ok(records
.iter()
.map(|v| ForecastCninfo { data: v.clone() })
.collect())
}
async fn cistock_rank_fetch(
&self,
sort_field: &str,
sort_order: &str,
) -> Result<Vec<RankThsEntry>> {
let resp = self
.get("https://push2.eastmoney.com/api/qt/clist/get")
.query(&[
("pn", "1"),
("pz", "5000"),
("po", sort_order),
("np", "1"),
("ut", "bd1d9ddb04089700cf9c27f6f7426281"),
("fltt", "2"),
("invt", "2"),
("fid", sort_field),
("fs", "m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048"),
("fields", "f2,f3,f12,f14"),
])
.send()
.await
.map_err(Error::from)?
.error_for_status()
.map_err(Error::from)?;
let payload: super::helpers::ClistSpotEnvelope = resp.json().await.map_err(Error::from)?;
let items = payload.data.and_then(|d| d.diff).unwrap_or_default();
Ok(items
.iter()
.map(|v| RankThsEntry {
code: json_str(v, "f12"),
name: json_str(v, "f14"),
latest_price: json_f64_opt(v, "f2"),
change_pct: json_f64_opt(v, "f3"),
volume: None,
amount: None,
extra: None,
})
.collect())
}
}