Spaces:
Paused
Paused
Upload main.rs
Browse files- src/main.rs +154 -64
src/main.rs
CHANGED
|
@@ -1005,7 +1005,10 @@ async fn gw_light_call(
|
|
| 1005 |
let mut req = if use_get || method == "user.getArl" {
|
| 1006 |
client.get(url)
|
| 1007 |
} else {
|
| 1008 |
-
client
|
|
|
|
|
|
|
|
|
|
| 1009 |
};
|
| 1010 |
|
| 1011 |
let sid = cookie_value(jar, url_deezer, "sid").unwrap_or_default();
|
|
@@ -1035,6 +1038,9 @@ async fn gw_light_call(
|
|
| 1035 |
.header("Connection", "keep-alive")
|
| 1036 |
.header("Origin", "https://www.deezer.com")
|
| 1037 |
.header("Referer", "https://www.deezer.com/")
|
|
|
|
|
|
|
|
|
|
| 1038 |
.header("X-Requested-With", "XMLHttpRequest")
|
| 1039 |
.header("Accept-Language", "en-US,en;q=0.9")
|
| 1040 |
.header("Content-Language", "en-US")
|
|
@@ -1078,12 +1084,22 @@ async fn gw_light_call(
|
|
| 1078 |
Ok(json.results)
|
| 1079 |
}
|
| 1080 |
|
| 1081 |
-
|
| 1082 |
-
|
| 1083 |
-
Err(e1) => match do_req(client, jar, &url_deezer, url, method, api_token, ¶ms, false, None).await {
|
| 1084 |
Ok(v) => Ok(v),
|
| 1085 |
-
Err(
|
| 1086 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1087 |
}
|
| 1088 |
}
|
| 1089 |
|
|
@@ -1109,34 +1125,82 @@ async fn login(Json(req): Json<LoginReq>) -> impl IntoResponse {
|
|
| 1109 |
.build()
|
| 1110 |
.unwrap();
|
| 1111 |
|
| 1112 |
-
let
|
| 1113 |
-
|
| 1114 |
-
|
| 1115 |
-
|
| 1116 |
-
.header(
|
| 1117 |
-
"User-Agent",
|
| 1118 |
-
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36",
|
| 1119 |
-
)
|
| 1120 |
-
.send()
|
| 1121 |
-
.await;
|
| 1122 |
|
| 1123 |
-
|
| 1124 |
-
Ok(
|
| 1125 |
-
|
| 1126 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1127 |
|
| 1128 |
-
|
| 1129 |
-
|
| 1130 |
-
|
| 1131 |
-
|
| 1132 |
-
|
| 1133 |
-
|
| 1134 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1135 |
}
|
| 1136 |
|
| 1137 |
(
|
| 1138 |
StatusCode::OK,
|
| 1139 |
-
Json(json!({
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1140 |
)
|
| 1141 |
.into_response()
|
| 1142 |
}
|
|
@@ -1344,57 +1408,83 @@ async fn pair_complete(State(state): State<AppState>, Form(f): Form<PairComplete
|
|
| 1344 |
.unwrap();
|
| 1345 |
|
| 1346 |
let pass_md5 = format!("{:x}", md5::compute(password.as_bytes()));
|
| 1347 |
-
let
|
| 1348 |
-
|
| 1349 |
-
|
| 1350 |
-
|
| 1351 |
-
|
| 1352 |
-
|
| 1353 |
-
|
| 1354 |
-
)
|
| 1355 |
-
|
| 1356 |
-
|
| 1357 |
-
|
| 1358 |
-
|
| 1359 |
-
|
| 1360 |
-
|
| 1361 |
-
|
| 1362 |
-
|
| 1363 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1364 |
}
|
| 1365 |
-
return Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&e))).into_response();
|
| 1366 |
-
}
|
| 1367 |
-
};
|
| 1368 |
|
| 1369 |
-
|
| 1370 |
-
|
| 1371 |
-
|
| 1372 |
-
|
| 1373 |
-
|
| 1374 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1375 |
}
|
| 1376 |
-
return Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&e))).into_response();
|
| 1377 |
}
|
| 1378 |
-
}
|
| 1379 |
-
|
| 1380 |
-
if
|
| 1381 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1382 |
let mut map = state.pair.write().await;
|
| 1383 |
if let Some(s) = map.get_mut(&code) {
|
| 1384 |
s.error = Some(msg.clone());
|
| 1385 |
}
|
| 1386 |
return Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&msg))).into_response();
|
| 1387 |
}
|
| 1388 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1389 |
|
| 1390 |
{
|
| 1391 |
let mut map = state.pair.write().await;
|
| 1392 |
if let Some(s) = map.get_mut(&code) {
|
| 1393 |
-
s.access_token =
|
| 1394 |
-
s.token =
|
| 1395 |
-
s.user_id =
|
| 1396 |
s.email = Some(email);
|
| 1397 |
-
s.arl =
|
| 1398 |
s.error = None;
|
| 1399 |
}
|
| 1400 |
}
|
|
|
|
| 1005 |
let mut req = if use_get || method == "user.getArl" {
|
| 1006 |
client.get(url)
|
| 1007 |
} else {
|
| 1008 |
+
client
|
| 1009 |
+
.post(url)
|
| 1010 |
+
.header("Content-Type", "text/plain;charset=UTF-8")
|
| 1011 |
+
.body(params.to_string())
|
| 1012 |
};
|
| 1013 |
|
| 1014 |
let sid = cookie_value(jar, url_deezer, "sid").unwrap_or_default();
|
|
|
|
| 1038 |
.header("Connection", "keep-alive")
|
| 1039 |
.header("Origin", "https://www.deezer.com")
|
| 1040 |
.header("Referer", "https://www.deezer.com/")
|
| 1041 |
+
.header("Sec-Fetch-Site", "same-origin")
|
| 1042 |
+
.header("Sec-Fetch-Mode", "cors")
|
| 1043 |
+
.header("Sec-Fetch-Dest", "empty")
|
| 1044 |
.header("X-Requested-With", "XMLHttpRequest")
|
| 1045 |
.header("Accept-Language", "en-US,en;q=0.9")
|
| 1046 |
.header("Content-Language", "en-US")
|
|
|
|
| 1084 |
Ok(json.results)
|
| 1085 |
}
|
| 1086 |
|
| 1087 |
+
if method == "deezer.getUserData" {
|
| 1088 |
+
match do_req(client, jar, &url_deezer, url, method, api_token, ¶ms, true, None).await {
|
|
|
|
| 1089 |
Ok(v) => Ok(v),
|
| 1090 |
+
Err(e1) => match do_req(client, jar, &url_deezer, url, method, api_token, ¶ms, false, None).await {
|
| 1091 |
+
Ok(v) => Ok(v),
|
| 1092 |
+
Err(e2) => Err(format!("getUserData:{e1}; fallback:{e2}")),
|
| 1093 |
+
},
|
| 1094 |
+
}
|
| 1095 |
+
} else {
|
| 1096 |
+
match do_req(client, jar, &url_deezer, url, method, api_token, ¶ms, false, None).await {
|
| 1097 |
+
Ok(v) => Ok(v),
|
| 1098 |
+
Err(e1) => match do_req(client, jar, &url_deezer, url, method, api_token, ¶ms, false, None).await {
|
| 1099 |
+
Ok(v) => Ok(v),
|
| 1100 |
+
Err(e2) => Err(format!("{e1}; retry:{e2}")),
|
| 1101 |
+
},
|
| 1102 |
+
}
|
| 1103 |
}
|
| 1104 |
}
|
| 1105 |
|
|
|
|
| 1125 |
.build()
|
| 1126 |
.unwrap();
|
| 1127 |
|
| 1128 |
+
let mut gw_token: Option<String> = None;
|
| 1129 |
+
let mut gw_uid: Option<String> = None;
|
| 1130 |
+
let mut arl_out: Option<String> = None;
|
| 1131 |
+
let mut gw_err: Option<String> = None;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1132 |
|
| 1133 |
+
match gw_light_call(&client, &jar, "deezer.getUserData", "null", json!({})).await {
|
| 1134 |
+
Ok(ud) => {
|
| 1135 |
+
let token = ud["checkForm"].as_str().unwrap_or("").to_string();
|
| 1136 |
+
if token.is_empty() {
|
| 1137 |
+
gw_err = Some("gw:no_checkForm".to_string());
|
| 1138 |
+
} else {
|
| 1139 |
+
gw_token = Some(token.clone());
|
| 1140 |
+
gw_uid = ud["USER"]["USER_ID"]
|
| 1141 |
+
.as_i64()
|
| 1142 |
+
.map(|n| n.to_string())
|
| 1143 |
+
.filter(|s| !s.trim().is_empty());
|
| 1144 |
+
|
| 1145 |
+
if let Err(e) = gw_light_call(
|
| 1146 |
+
&client,
|
| 1147 |
+
&jar,
|
| 1148 |
+
"user.checkCredentials",
|
| 1149 |
+
&token,
|
| 1150 |
+
json!({
|
| 1151 |
+
"login": email,
|
| 1152 |
+
"password": pass,
|
| 1153 |
+
"checkFormLogin": token
|
| 1154 |
+
}),
|
| 1155 |
+
)
|
| 1156 |
+
.await
|
| 1157 |
+
{
|
| 1158 |
+
return json_error(StatusCode::UNAUTHORIZED, e);
|
| 1159 |
+
}
|
| 1160 |
|
| 1161 |
+
if let Ok(v) = gw_light_call(&client, &jar, "user.getArl", &token, json!({})).await {
|
| 1162 |
+
if let Some(s) = v.as_str() {
|
| 1163 |
+
if s.len() > 20 {
|
| 1164 |
+
arl_out = Some(s.to_string());
|
| 1165 |
+
}
|
| 1166 |
+
}
|
| 1167 |
+
}
|
| 1168 |
+
}
|
| 1169 |
+
}
|
| 1170 |
+
Err(e) => {
|
| 1171 |
+
gw_err = Some(format!("gw:getUserData:{e}"));
|
| 1172 |
+
}
|
| 1173 |
+
}
|
| 1174 |
+
|
| 1175 |
+
let mut access_token_out: Option<String> = None;
|
| 1176 |
+
let mut oauth_uid: Option<String> = None;
|
| 1177 |
+
if let Ok(access_token) = oauth_access_token(&client, &email, &pass).await {
|
| 1178 |
+
oauth_uid = api_deezer_get(&client, "/user/me", &access_token, &[])
|
| 1179 |
+
.await
|
| 1180 |
+
.ok()
|
| 1181 |
+
.and_then(|v| v.get("id").and_then(|x| x.as_i64()))
|
| 1182 |
+
.filter(|id| *id > 0)
|
| 1183 |
+
.map(|id| id.to_string());
|
| 1184 |
+
access_token_out = Some(access_token);
|
| 1185 |
+
}
|
| 1186 |
+
|
| 1187 |
+
let uid_out = gw_uid.or(oauth_uid).unwrap_or_default();
|
| 1188 |
+
|
| 1189 |
+
if gw_token.is_none() && access_token_out.is_none() {
|
| 1190 |
+
return json_error(
|
| 1191 |
+
StatusCode::UNAUTHORIZED,
|
| 1192 |
+
gw_err.unwrap_or_else(|| "login_failed".to_string()),
|
| 1193 |
+
);
|
| 1194 |
}
|
| 1195 |
|
| 1196 |
(
|
| 1197 |
StatusCode::OK,
|
| 1198 |
+
Json(json!({
|
| 1199 |
+
"arl": arl_out.unwrap_or_default(),
|
| 1200 |
+
"token": gw_token,
|
| 1201 |
+
"uid": uid_out,
|
| 1202 |
+
"access_token": access_token_out
|
| 1203 |
+
})),
|
| 1204 |
)
|
| 1205 |
.into_response()
|
| 1206 |
}
|
|
|
|
| 1408 |
.unwrap();
|
| 1409 |
|
| 1410 |
let pass_md5 = format!("{:x}", md5::compute(password.as_bytes()));
|
| 1411 |
+
let mut gw_token: Option<String> = None;
|
| 1412 |
+
let mut gw_uid: Option<String> = None;
|
| 1413 |
+
let mut arl_out: Option<String> = None;
|
| 1414 |
+
let mut access_token_out: Option<String> = None;
|
| 1415 |
+
|
| 1416 |
+
if let Ok(ud) = gw_light_call(&client, &jar, "deezer.getUserData", "null", json!({})).await {
|
| 1417 |
+
let token = ud["checkForm"].as_str().unwrap_or("").to_string();
|
| 1418 |
+
if !token.is_empty() {
|
| 1419 |
+
if let Err(e) = gw_light_call(
|
| 1420 |
+
&client,
|
| 1421 |
+
&jar,
|
| 1422 |
+
"user.checkCredentials",
|
| 1423 |
+
&token,
|
| 1424 |
+
json!({
|
| 1425 |
+
"login": email,
|
| 1426 |
+
"password": pass_md5,
|
| 1427 |
+
"checkFormLogin": token
|
| 1428 |
+
}),
|
| 1429 |
+
)
|
| 1430 |
+
.await
|
| 1431 |
+
{
|
| 1432 |
+
let mut map = state.pair.write().await;
|
| 1433 |
+
if let Some(s) = map.get_mut(&code) {
|
| 1434 |
+
s.error = Some(format!("gw:checkCredentials:{e}"));
|
| 1435 |
+
}
|
| 1436 |
+
return Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&format!("gw:checkCredentials:{e}"))))
|
| 1437 |
+
.into_response();
|
| 1438 |
}
|
|
|
|
|
|
|
|
|
|
| 1439 |
|
| 1440 |
+
gw_token = Some(token.clone());
|
| 1441 |
+
gw_uid = ud["USER"]["USER_ID"]
|
| 1442 |
+
.as_i64()
|
| 1443 |
+
.map(|n| n.to_string())
|
| 1444 |
+
.filter(|s| !s.trim().is_empty());
|
| 1445 |
+
|
| 1446 |
+
if let Ok(v) = gw_light_call(&client, &jar, "user.getArl", &token, json!({})).await {
|
| 1447 |
+
if let Some(s) = v.as_str() {
|
| 1448 |
+
if s.len() > 20 {
|
| 1449 |
+
arl_out = Some(s.to_string());
|
| 1450 |
+
}
|
| 1451 |
+
}
|
| 1452 |
}
|
|
|
|
| 1453 |
}
|
| 1454 |
+
}
|
| 1455 |
+
|
| 1456 |
+
if let Ok(t) = oauth_access_token(&client, &email, &pass_md5).await {
|
| 1457 |
+
access_token_out = Some(t);
|
| 1458 |
+
}
|
| 1459 |
+
|
| 1460 |
+
if gw_token.is_none() && access_token_out.is_none() {
|
| 1461 |
+
let msg = "login_failed".to_string();
|
| 1462 |
let mut map = state.pair.write().await;
|
| 1463 |
if let Some(s) = map.get_mut(&code) {
|
| 1464 |
s.error = Some(msg.clone());
|
| 1465 |
}
|
| 1466 |
return Html(format!("<h3>Ошибка входа</h3><pre>{}</pre>", htmlesc(&msg))).into_response();
|
| 1467 |
}
|
| 1468 |
+
|
| 1469 |
+
if gw_uid.is_none() {
|
| 1470 |
+
if let Some(token) = access_token_out.as_deref() {
|
| 1471 |
+
gw_uid = api_deezer_get(&client, "/user/me", token, &[])
|
| 1472 |
+
.await
|
| 1473 |
+
.ok()
|
| 1474 |
+
.and_then(|v| v.get("id").and_then(|x| x.as_i64()))
|
| 1475 |
+
.filter(|id| *id > 0)
|
| 1476 |
+
.map(|id| id.to_string());
|
| 1477 |
+
}
|
| 1478 |
+
}
|
| 1479 |
|
| 1480 |
{
|
| 1481 |
let mut map = state.pair.write().await;
|
| 1482 |
if let Some(s) = map.get_mut(&code) {
|
| 1483 |
+
s.access_token = access_token_out;
|
| 1484 |
+
s.token = gw_token;
|
| 1485 |
+
s.user_id = gw_uid;
|
| 1486 |
s.email = Some(email);
|
| 1487 |
+
s.arl = arl_out;
|
| 1488 |
s.error = None;
|
| 1489 |
}
|
| 1490 |
}
|