switched to rust 2021 edition, using cookie jar

This commit is contained in:
uh wot 2021-10-21 17:54:50 +02:00
parent 4773b190b2
commit 89a9303321
Signed by: uhwot
GPG key ID: CB2454984587B781
4 changed files with 83 additions and 51 deletions

View file

@ -1,8 +1,8 @@
use serde::{Serialize, Deserialize, de::DeserializeOwned};
use std::{env, marker::Sized, time::Instant};
use std::{env, marker::Sized, time::Instant, sync::Arc};
use thiserror::Error;
use serde_json::{json, value::from_value};
use regex::Regex;
use reqwest::{Client, Response, cookie::Jar, Url};
#[derive(Deserialize)]
struct DeezerResponse {
@ -52,23 +52,28 @@ pub enum APIError {
#[derive(Clone)]
pub struct APIClient {
client: reqwest::Client,
license_token: String,
client: Client,
pub license_token: String,
check_form: String,
pub sid: String,
arl: String,
renew_instant: Option<Instant>,
}
impl APIClient {
pub fn new() -> Self {
if let Ok(arl) = env::var("ARL") {
let builder = Client::builder();
let cookie = format!("arl={}; Domain=.deezer.com", arl);
let url = "https://www.deezer.com".parse::<Url>().unwrap();
let jar = Jar::default();
jar.add_cookie_str(&cookie, &url);
let builder = builder.cookie_provider(Arc::new(jar));
Self {
client: reqwest::Client::new(),
client: builder.build().unwrap(),
license_token: String::new(),
check_form: String::new(),
sid: String::new(),
arl,
renew_instant: None,
}
} else {
@ -76,8 +81,9 @@ impl APIClient {
}
}
async fn raw_api_call<T>(&self, method: &str, params: &T) -> Result<reqwest::Response, reqwest::Error>
where T: Serialize + ?Sized
async fn no_renew_api_call<P, T>(&mut self, method: &str, params: &P) -> Result<T, APIError>
where P: Serialize + ?Sized,
T: DeserializeOwned
{
let check_form;
if method == "deezer.getUserData" {
@ -86,13 +92,7 @@ impl APIClient {
check_form = &self.check_form;
}
let mut cookies = format!("arl={}", self.arl);
if self.sid != "" && method != "deezer.getUserData" {
cookies.push_str(&format!("; sid={}", self.sid))
}
self.client.post("https://www.deezer.com/ajax/gw-light.php")
let json: DeezerResponse = self.client.post("https://www.deezer.com/ajax/gw-light.php")
.query(&[
("method", method),
("input", "3"),
@ -100,26 +100,9 @@ impl APIClient {
("api_token", check_form)
])
.json(params)
.header("cookie", &cookies)
.send()
.await
}
pub async fn api_call<P, T>(&mut self, method: &str, params: &P) -> Result<T, APIError>
where P: Serialize + ?Sized,
T: DeserializeOwned
{
if let Some(i) = self.renew_instant {
if i.elapsed().as_secs() >= 3600 {
self.renew().await?;
}
} else {
self.renew().await?;
}
let json = self.raw_api_call(method, params)
.await?
.json::<DeezerResponse>()
.json()
.await?;
if let Some(error) = json.error.as_object() {
@ -134,24 +117,33 @@ impl APIClient {
Ok(from_value(json.results)?)
}
async fn renew(&mut self) -> Result<(), reqwest::Error> {
let resp = self.raw_api_call("deezer.getUserData", &json!({})).await?;
pub async fn api_call<P, T>(&mut self, method: &str, params: &P) -> Result<T, APIError>
where P: Serialize + ?Sized,
T: DeserializeOwned
{
if let Some(i) = self.renew_instant {
if i.elapsed().as_secs() >= 3600 {
self.renew().await?;
}
} else {
self.renew().await?;
}
let sid = resp.headers().get("set-cookie").unwrap().to_str().unwrap();
let sid = Regex::new("^sid=(fr[\\da-f]+)").unwrap().captures(sid).unwrap();
self.sid = (&sid[1]).to_string();
self.no_renew_api_call(method, params).await
}
let json = resp.json::<DeezerResponse>().await?.results;
async fn renew(&mut self) -> Result<(), APIError> {
let user_data: serde_json::Value = self.no_renew_api_call("deezer.getUserData", &json!({})).await?;
self.check_form = json["checkForm"].as_str().unwrap().to_string();
self.license_token = json["USER"]["OPTIONS"]["license_token"].as_str().unwrap().to_string();
self.check_form = user_data["checkForm"].as_str().unwrap().to_string();
self.license_token = user_data["USER"]["OPTIONS"]["license_token"].as_str().unwrap().to_string();
self.renew_instant = Some(Instant::now());
Ok(())
}
pub async fn get_media(&self, formats: &Vec<Format>, track_tokens: Vec<&str>) -> Result<reqwest::Response, reqwest::Error> {
pub async fn get_media(&self, formats: &Vec<Format>, track_tokens: Vec<&str>) -> Result<Response, reqwest::Error> {
let formats: Vec<DeezerFormat> = formats.iter().map(|f| DeezerFormat { cipher: "BF_CBC_STRIPE", format: f }).collect();
let req = json!({

View file

@ -46,10 +46,10 @@ async fn get_url(req: Json<RequestParams>, state_data: &State<RwLock<StateData>>
}
let mut client: APIClient;
let old_sid: String;
let old_license: String;
{
let state_data_read = state_data.read().unwrap();
old_sid = state_data_read.client.sid.clone();
old_license = state_data_read.client.license_token.clone();
client = state_data_read.client.clone();
}
@ -73,7 +73,7 @@ async fn get_url(req: Json<RequestParams>, state_data: &State<RwLock<StateData>>
Err(_) => return (Status::InternalServerError, "Error while getting response from media.deezer.com".to_string())
};
if client.sid != old_sid {
if client.license_token != old_license {
let mut state_data_write = state_data.write().unwrap();
state_data_write.client = client;
}