Skip to main content

ncm_api_rs/api/
playlist_track_all.rs

1use super::Query;
2use crate::error::Result;
3/// 歌单所有歌曲
4/// 对应 Node.js module/playlist_track_all.js
5use crate::request::{ApiClient, ApiResponse, CryptoType};
6use serde_json::json;
7
8impl ApiClient {
9    /// 歌单所有歌曲(两步请求:先获取 trackIds,再获取歌曲详情)
10    /// 对应 /playlist/track/all
11    pub async fn playlist_track_all(&self, query: &Query) -> Result<ApiResponse> {
12        let id = query.get_or("id", "0");
13        let limit = query.get_or("limit", "1000").parse::<i64>().unwrap_or(1000);
14        let offset = query.get_or("offset", "0").parse::<i64>().unwrap_or(0);
15
16        // Step 1: 获取歌单详情(含 trackIds)
17        let data1 = json!({
18            "id": id,
19            "n": 100000,
20            "s": query.get_or("s", "8").parse::<i64>().unwrap_or(8)
21        });
22        let res = self
23            .request(
24                "/api/v6/playlist/detail",
25                data1,
26                query.to_option(CryptoType::default()),
27            )
28            .await?;
29
30        // Step 2: 从 trackIds 中截取分页范围
31        if let Some(track_ids) = res.body["playlist"]["trackIds"].as_array() {
32            let start = offset as usize;
33            let end = std::cmp::min(start + limit as usize, track_ids.len());
34            let sliced = &track_ids[start..end];
35
36            let c: Vec<String> = sliced
37                .iter()
38                .filter_map(|t| t["id"].as_i64())
39                .map(|id| format!(r#"{{"id":{}}}"#, id))
40                .collect();
41
42            let data2 = json!({
43                "c": format!("[{}]", c.join(","))
44            });
45            self.request(
46                "/api/v3/song/detail",
47                data2,
48                query.to_option(CryptoType::default()),
49            )
50            .await
51        } else {
52            Ok(res)
53        }
54    }
55}