lrclib_api_rs/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
use std::borrow::Cow;

use http::{Method, Request};

mod types;
pub use types::*;

const BASE_URL: &str = "https://lrclib.net";

pub struct LRCLibAPI;

impl LRCLibAPI {
    pub fn get_lyrics_request(
        track_name: &str,
        artist_name: &str,
        album_name: Option<&str>,
        duration: Option<u64>,
    ) -> Result<Request<()>, ApiError> {
        let mut query_params: Vec<(&str, Cow<'_, str>)> = vec![
            ("track_name", track_name.into()),
            ("artist_name", artist_name.into()),
        ];

        if let Some(album) = album_name {
            query_params.push(("album_name", album.into()));
        }
        if let Some(dur) = duration {
            let dur_s = dur.to_string();
            query_params.push(("duration", Cow::Owned(dur_s)));
        }

        let query_string: String = query_params
            .into_iter()
            .map(|(key, value)| format!("{}={}", key, value))
            .collect::<Vec<String>>()
            .join("&");

        let uri = format!("{}/api/get?{}", BASE_URL, query_string);

        Request::builder()
            .method(Method::GET)
            .uri(uri)
            .header("User-Agent", "LRCAPIWrapper/0.1.0")
            .body(())
            .map_err(ApiError::from)
    }

    pub fn get_lyrics_by_id_request(id: u64) -> Result<Request<()>, ApiError> {
        let uri = format!("{}/api/get/{}", BASE_URL, id);

        Request::builder()
            .method(Method::GET)
            .uri(uri)
            .header("User-Agent", "LRCAPIWrapper/0.1.0")
            .body(())
            .map_err(ApiError::from)
    }

    pub fn search_lyrics_request(
        query: Option<&str>,
        track_name: Option<&str>,
        artist_name: Option<&str>,
        album_name: Option<&str>,
    ) -> Result<Request<()>, ApiError> {
        let mut query_params = vec![];

        if let Some(q) = query {
            query_params.push(("q", q));
        }
        if let Some(track) = track_name {
            query_params.push(("track_name", track));
        }
        if let Some(artist) = artist_name {
            query_params.push(("artist_name", artist));
        }
        if let Some(album) = album_name {
            query_params.push(("album_name", album));
        }

        let query_string: String = query_params
            .into_iter()
            .map(|(key, value)| format!("{}={}", key, value))
            .collect::<Vec<String>>()
            .join("&");

        let uri = format!("{}/api/search?{}", BASE_URL, query_string);

        Request::builder()
            .method(Method::GET)
            .uri(uri)
            .header("User-Agent", "LRCAPIWrapper/0.1.0")
            .body(())
            .map_err(ApiError::from)
    }

    pub fn request_publish_challenge_request() -> Result<Request<()>, ApiError> {
        let uri = format!("{}/api/request-challenge", BASE_URL);

        Request::builder()
            .method(Method::POST)
            .uri(uri)
            .header("User-Agent", "LRCAPIWrapper/0.1.0")
            .body(())
            .map_err(ApiError::from)
    }

    pub fn publish_lyrics_request(
        lyrics: &LyricsData,
        publish_token: &str,
    ) -> Result<Request<String>, ApiError> {
        let uri = format!("{}/api/publish", BASE_URL);

        let body = serde_json::to_string(lyrics)?;

        Request::builder()
            .method(Method::POST)
            .uri(uri)
            .header("User-Agent", "LRCAPIWrapper/0.1.0")
            .header("X-Publish-Token", publish_token)
            .header("Content-Type", "application/json")
            .body(body)
            .map_err(ApiError::from)
    }
}