recycleactor commited on
Commit
268da2c
·
verified ·
1 Parent(s): e7d0ccb

Upload 2 files

Browse files
Files changed (1) hide show
  1. src/main.rs +110 -4
src/main.rs CHANGED
@@ -1180,6 +1180,60 @@ async fn gw_fetch_arl(
1180
  Err(format!("getArl:{last_err}"))
1181
  }
1182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1183
  async fn oauth_access_token(
1184
  client: &reqwest::Client,
1185
  email: &str,
@@ -1819,13 +1873,49 @@ async fn pair_oauth(State(state): State<AppState>, Json(req): Json<PairOauthReq>
1819
  return json_error(StatusCode::BAD_REQUEST, "code/access_token required");
1820
  }
1821
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1822
  let mut map = state.pair.write().await;
1823
  let Some(sess) = map.get_mut(&code) else {
1824
  return json_error(StatusCode::NOT_FOUND, "no such code");
1825
  };
1826
  sess.access_token = Some(access_token);
1827
- if !user_id.is_empty() {
1828
- sess.user_id = Some(user_id);
 
 
 
 
 
 
 
 
 
1829
  }
1830
  sess.error = None;
1831
  drop(map);
@@ -2008,6 +2098,22 @@ async fn pair_complete(State(state): State<AppState>, Form(f): Form<PairComplete
2008
  Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&e))).into_response()
2009
  }
2010
  Ok(login) => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2011
  let mut map = state.pair.write().await;
2012
  if let Some(s) = map.get_mut(&code) {
2013
  s.arl = login.arl.clone();
@@ -2020,7 +2126,7 @@ async fn pair_complete(State(state): State<AppState>, Form(f): Form<PairComplete
2020
  if !login.uid.is_empty() {
2021
  s.user_id = Some(login.uid.clone());
2022
  }
2023
- s.email = Some(email);
2024
  s.error = None;
2025
  }
2026
  drop(map);
@@ -2169,7 +2275,7 @@ async fn oauth_arl(Json(req): Json<OauthArlReq>) -> impl IntoResponse {
2169
  Ok((arl, _, _)) if arl.len() >= 20 => {
2170
  (StatusCode::OK, Json(json!({ "arl": arl }))).into_response()
2171
  }
2172
- Err(e) => json_error(StatusCode::SERVICE_UNAVAILABLE, e),
2173
  }
2174
  }
2175
 
 
1180
  Err(format!("getArl:{last_err}"))
1181
  }
1182
 
1183
+ async fn try_fetch_arl_for_token(
1184
+ access_token: &str,
1185
+ user_id: Option<&str>,
1186
+ ) -> (Option<String>, Option<String>) {
1187
+ let jar = Arc::new(Jar::default());
1188
+ let url_deezer = match "https://www.deezer.com".parse::<Url>() {
1189
+ Ok(u) => u,
1190
+ Err(_) => return (None, None),
1191
+ };
1192
+ jar.add_cookie_str("comeback=1; Domain=.deezer.com; Path=/", &url_deezer);
1193
+
1194
+ let client = match reqwest::Client::builder()
1195
+ .no_proxy()
1196
+ .cookie_provider(jar.clone())
1197
+ .timeout(std::time::Duration::from_secs(20))
1198
+ .build()
1199
+ {
1200
+ Ok(c) => c,
1201
+ Err(_) => return (None, None),
1202
+ };
1203
+
1204
+ let _ = client
1205
+ .get("https://www.deezer.com/")
1206
+ .header(ACCEPT, "*/*")
1207
+ .header("User-Agent", gw_browser_ua())
1208
+ .send()
1209
+ .await;
1210
+
1211
+ if ensure_anonymous_sid(&client, &jar).await.is_err() {
1212
+ return (None, None);
1213
+ }
1214
+
1215
+ establish_oauth_session(&client, &jar, access_token).await;
1216
+
1217
+ let uid = if let Some(uid) = user_id.filter(|s| !s.trim().is_empty()) {
1218
+ Some(uid.to_string())
1219
+ } else {
1220
+ api_deezer_get(&client, "/user/me", access_token, &[])
1221
+ .await
1222
+ .ok()
1223
+ .and_then(|v| v.get("id").and_then(|x| x.as_i64()))
1224
+ .filter(|id| *id > 0)
1225
+ .map(|id| id.to_string())
1226
+ };
1227
+
1228
+ match gw_fetch_arl(&client, "", "", uid.as_deref()).await {
1229
+ Ok((arl, token, _)) if arl.len() >= 20 => {
1230
+ let gw_token = if token.is_empty() { None } else { Some(token) };
1231
+ (Some(arl), gw_token)
1232
+ }
1233
+ _ => (None, None),
1234
+ }
1235
+ }
1236
+
1237
  async fn oauth_access_token(
1238
  client: &reqwest::Client,
1239
  email: &str,
 
1873
  return json_error(StatusCode::BAD_REQUEST, "code/access_token required");
1874
  }
1875
 
1876
+ let http = reqwest::Client::builder()
1877
+ .no_proxy()
1878
+ .timeout(std::time::Duration::from_secs(15))
1879
+ .build()
1880
+ .unwrap();
1881
+ let email = api_deezer_get(&http, "/user/me", &access_token, &[])
1882
+ .await
1883
+ .ok()
1884
+ .and_then(|v| v.get("email").and_then(|x| x.as_str()).map(|s| s.to_string()));
1885
+
1886
+ let uid_from_api = if user_id.is_empty() {
1887
+ api_deezer_get(&http, "/user/me", &access_token, &[])
1888
+ .await
1889
+ .ok()
1890
+ .and_then(|v| v.get("id").and_then(|x| x.as_i64()))
1891
+ .filter(|id| *id > 0)
1892
+ .map(|id| id.to_string())
1893
+ } else {
1894
+ Some(user_id.clone())
1895
+ };
1896
+
1897
+ let (arl_opt, token_opt) = try_fetch_arl_for_token(
1898
+ &access_token,
1899
+ uid_from_api.as_deref(),
1900
+ )
1901
+ .await;
1902
+
1903
  let mut map = state.pair.write().await;
1904
  let Some(sess) = map.get_mut(&code) else {
1905
  return json_error(StatusCode::NOT_FOUND, "no such code");
1906
  };
1907
  sess.access_token = Some(access_token);
1908
+ if let Some(uid) = uid_from_api {
1909
+ sess.user_id = Some(uid);
1910
+ }
1911
+ if let Some(arl) = arl_opt {
1912
+ sess.arl = Some(arl);
1913
+ }
1914
+ if let Some(token) = token_opt {
1915
+ sess.token = Some(token);
1916
+ }
1917
+ if let Some(email) = email {
1918
+ sess.email = Some(email);
1919
  }
1920
  sess.error = None;
1921
  drop(map);
 
2098
  Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&e))).into_response()
2099
  }
2100
  Ok(login) => {
2101
+ let email_from_api = {
2102
+ let http = reqwest::Client::builder()
2103
+ .no_proxy()
2104
+ .timeout(std::time::Duration::from_secs(10))
2105
+ .build()
2106
+ .ok();
2107
+ if let Some(http) = http {
2108
+ api_deezer_get(&http, "/user/me", &login.access_token, &[])
2109
+ .await
2110
+ .ok()
2111
+ .and_then(|v| v.get("email").and_then(|x| x.as_str()).map(|s| s.to_string()))
2112
+ } else {
2113
+ None
2114
+ }
2115
+ };
2116
+
2117
  let mut map = state.pair.write().await;
2118
  if let Some(s) = map.get_mut(&code) {
2119
  s.arl = login.arl.clone();
 
2126
  if !login.uid.is_empty() {
2127
  s.user_id = Some(login.uid.clone());
2128
  }
2129
+ s.email = email_from_api.or(Some(email));
2130
  s.error = None;
2131
  }
2132
  drop(map);
 
2275
  Ok((arl, _, _)) if arl.len() >= 20 => {
2276
  (StatusCode::OK, Json(json!({ "arl": arl }))).into_response()
2277
  }
2278
+ Err(e) => json_error(StatusCode::SERVICE_UNAVAILABLE, format!("oauth_arl:{e}")),
2279
  }
2280
  }
2281