Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate to new API #345

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/rest-api-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Build RESTful API binaries
on:
push:
workflow_dispatch:
pull_request:

permissions:
actions: write
Expand Down
63 changes: 12 additions & 51 deletions engines/pyncm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,6 @@ use url::Url;
#[derive(Deserialize)]
#[non_exhaustive]
struct PyNCMResponse {
/// The status code of this response.
pub code: i32,
pub data: Vec<PyNCMResponseEntry>,
}

#[derive(Deserialize)]
#[non_exhaustive]
struct PyNCMResponseEntry {
/// The NCM ID of this song.
pub id: i64,
/// The URL of this song.
pub url: Option<String>,
}
Expand All @@ -43,24 +33,13 @@ impl Engine for PyNCMEngine {
info!("Searching with PyNCM engine…");

let response = fetch_song_info(&info.id, ctx).await?;

if response.code == 200 {
// We return the URL we got from PyNCM as the song identifier,
// so we can return the URL in retrieve() easily.
let match_result = find_match(&response.data, &info.id)?.map(|url| {
SongSearchInformation::builder()
.source(ENGINE_ID.into())
.identifier(url)
.build()
});

Ok(match_result)
} else {
Err(anyhow::anyhow!(
"failed to request. code: {}",
response.code
))
}
let match_result = response.url.map(|url| {
SongSearchInformation::builder()
.source(ENGINE_ID.into())
.identifier(url)
.build()
});
Ok(match_result)
}

async fn retrieve<'a>(
Expand All @@ -82,31 +61,16 @@ impl Engine for PyNCMEngine {
async fn fetch_song_info(id: &str, ctx: &Context) -> anyhow::Result<PyNCMResponse> {
debug!("Fetching the song information…");

let bitrate = if ctx.enable_flac { 999000 } else { 320000 };
let bitrate = if ctx.enable_flac { 999 } else { 320 };
// Credit: This API is provided by GD studio (music.gdstudio.xyz).
let url = Url::parse_with_params(
"https://pyncmd.apis.imouto.in/api/pyncm?module=track&method=GetTrackAudio",
&[("song_ids", id), ("bitrate", &bitrate.to_string())],
"https://music-api.gdstudio.xyz/api.php?types=url&source=netease",
&[("id", id), ("br", &bitrate.to_string())],
)?;

let client = build_client(ctx.proxy_uri.as_deref())?;
let response = client.get(url).send().await?;
Ok(response.json::<PyNCMResponse>().await?)
}

/// Find the matched song from an array of [`PyNCMResponseEntry`].
fn find_match(data: &[PyNCMResponseEntry], song_id: &str) -> anyhow::Result<Option<String>> {
info!("Finding the matched song…");

data.iter()
.find(|entry| {
// Test if the ID of this entry matched what we want to fetch,
// and there is content in its URL.
entry.id.to_string() == song_id && entry.url.is_some()
})
.map(|v| v.url.clone())
.ok_or_else(|| anyhow::anyhow!("no matched song"))
}

#[cfg(test)]
mod tests {
use unm_types::ContextBuilder;
Expand All @@ -119,10 +83,7 @@ mod tests {
let result = fetch_song_info(song_id, &ContextBuilder::default().build().unwrap()).await;

if let Ok(response) = result {
assert_eq!(response.code, 200);
assert_eq!(response.data.len(), 1);
assert_eq!(response.data[0].id.to_string(), song_id);
assert!(response.data[0].url.is_some());
assert!(response.url.is_some());
} else {
panic!("failed to fetch song info");
}
Expand Down