live-probed: /stalk/genshin was NOT real — it just pass-through the raw SvelteKit __data.json (only nickname/level/nameCardId/profilePicture), not a full Genshin profile like the Shirokami source (which parses characters/element/costume/stats via enka-network-api -> get_profile_for_uid). That proper API is now 404 without an enka token. Removed. stalk now has 3 real endpoints: github, youtube, twitter.
This commit is contained in:
@@ -18,13 +18,6 @@ pub async fn youtube(username: &str) -> Result<Value, ScrapingError> {
|
||||
.map_err(ScrapingError::Http)
|
||||
}
|
||||
|
||||
/// Genshin Impact player stalk.
|
||||
pub async fn genshin(user_id: &str) -> Result<Value, ScrapingError> {
|
||||
Repo::fetch_genshin_stalk(user_id)
|
||||
.await
|
||||
.map_err(ScrapingError::Http)
|
||||
}
|
||||
|
||||
/// Twitter/X user stalk.
|
||||
pub async fn twitter(username: &str) -> Result<Value, ScrapingError> {
|
||||
Repo::fetch_twitter_stalk(username)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Infrastructure — Stalk utilities (github, youtube, genshin, twitter).
|
||||
//! Infrastructure — Stalk utilities (github, youtube, twitter).
|
||||
//!
|
||||
//! Ported from Shirokami-API `scraper/stalk/*.js`.
|
||||
|
||||
@@ -417,33 +417,6 @@ fn video_from_grid_video(gv: &Value) -> Value {
|
||||
v
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Genshin Impact — enka.network public API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
pub async fn fetch_genshin_stalk(user_id: &str) -> Result<Value, String> {
|
||||
let url = format!("https://enka.network/u/{}/__data.json", user_id);
|
||||
let resp = http_client()
|
||||
.client()
|
||||
.get(&url)
|
||||
.header(
|
||||
USER_AGENT,
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0 Safari/537.36",
|
||||
)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|e| format!("HTTP: {}", e))?;
|
||||
if resp.status() == reqwest::StatusCode::NOT_FOUND {
|
||||
return Err("User tidak ditemukan".into());
|
||||
}
|
||||
if !resp.status().is_success() {
|
||||
return Err(format!("HTTP {}", resp.status()));
|
||||
}
|
||||
let data: Value = resp.json().await.map_err(|e| format!("JSON: {}", e))?;
|
||||
// Pass through the raw JSON (Enka __data.json is already structured).
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Twitter — fxtwitter API
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -74,7 +74,6 @@ use utoipa::OpenApi;
|
||||
// ── Stalk module ───────────────────────────────────────────
|
||||
crate::presentation::handler::stalk::github_handler,
|
||||
crate::presentation::handler::stalk::youtube_handler,
|
||||
crate::presentation::handler::stalk::genshin_handler,
|
||||
crate::presentation::handler::stalk::twitter_handler,
|
||||
// ── Search module ──────────────────────────────────────────
|
||||
crate::presentation::handler::search::bmkg_handler,
|
||||
@@ -105,7 +104,7 @@ use utoipa::OpenApi;
|
||||
(name = "komik", description = "Komik endpoints"),
|
||||
(name = "download", description = "Media download endpoints (23 platforms)"),
|
||||
(name = "misc", description = "Miscellaneous utilities (currency, gold, server)"),
|
||||
(name = "stalk", description = "User profile stalking (GitHub, YT, Twitter, Genshin)"),
|
||||
(name = "stalk", description = "User profile stalking (GitHub, YT, Twitter)"),
|
||||
(name = "search", description = "Search endpoints (BMKG, prayer times, weather, YouTube, Google)"),
|
||||
(name = "tool", description = "Utility tools (WHOIS, IP lookup, URL shortener, tracking, hosting)"),
|
||||
(name = "image", description = "Image generation (brat static & animated)"),
|
||||
|
||||
@@ -68,30 +68,6 @@ pub async fn youtube_handler(
|
||||
Ok((StatusCode::OK, Json(result)))
|
||||
}
|
||||
|
||||
/// GET /stalk/genshin-impact?user_id=... (alias: userid)
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/stalk/genshin-impact",
|
||||
tag = "stalk",
|
||||
operation_id = "stalk_genshin",
|
||||
params(StalkParams),
|
||||
responses(
|
||||
(status = 200, description = "Genshin Impact profile", body = Value),
|
||||
(status = 400, description = "Missing user_id"),
|
||||
(status = 502, description = "Upstream error"),
|
||||
)
|
||||
)]
|
||||
pub async fn genshin_handler(
|
||||
Query(params): Query<StalkParams>,
|
||||
) -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
let user_id = params
|
||||
.user_id
|
||||
.or(params.userid)
|
||||
.ok_or_else(|| AppError::BadRequest("Missing 'user_id' parameter".to_string()))?;
|
||||
let result = use_cases::genshin(&user_id).await?;
|
||||
Ok((StatusCode::OK, Json(result)))
|
||||
}
|
||||
|
||||
/// GET /stalk/twitter?username=...
|
||||
#[utoipa::path(
|
||||
get,
|
||||
|
||||
@@ -282,10 +282,6 @@ pub fn build_router(app_state: Arc<AppState>) -> anyhow::Result<Router> {
|
||||
"/stalk/youtube",
|
||||
axum::routing::get(crate::presentation::handler::stalk::youtube_handler),
|
||||
)
|
||||
.route(
|
||||
"/stalk/genshin-impact",
|
||||
axum::routing::get(crate::presentation::handler::stalk::genshin_handler),
|
||||
)
|
||||
.route(
|
||||
"/stalk/twitter",
|
||||
axum::routing::get(crate::presentation::handler::stalk::twitter_handler),
|
||||
|
||||
Reference in New Issue
Block a user