feat(tools): add whois(RDAP), iplocation, tinyurl, check-hosting, cek-resi, hargapangan
Ported from Shirokami-API scraper/tool/*.js: - /tool/whois - RDAP lookup (whois.com HTML .df-raw is dead/JS-rendered since 2026; RDAP returns structured register/expiry/registrar data) - /tool/iplocation - ipapi.co JSON - /tool/tinyurl - tinyurl.com API - /tool/check-hosting - hosting-checker.net API - /tool/cek-resi - cekresi.com AES-128-CBC encrypted form POST - /tool/hargapangan - Bapanas government API (upstream unreachable from VPS) Fixes: scraper crate has no :has-text() pseudo-class -> replaced history-table scan with 2-cell-row detection; Html held across .await makes future non-Send -> scoped doc parsing
This commit is contained in:
@@ -7,4 +7,5 @@ pub mod misc;
|
||||
pub mod proxy;
|
||||
pub mod search;
|
||||
pub mod stalk;
|
||||
pub mod tools;
|
||||
pub mod weebs;
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
//! Axum handlers for tools.
|
||||
|
||||
use axum::extract::Query;
|
||||
use axum::http::StatusCode;
|
||||
use axum::Json;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::application::tools as use_cases;
|
||||
use crate::presentation::error::AppError;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct DomainParams {
|
||||
pub domain: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct IpParams {
|
||||
pub ip: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct UrlParams {
|
||||
pub url: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ResiParams {
|
||||
pub resi: Option<String>,
|
||||
pub ekspedisi: Option<String>,
|
||||
}
|
||||
|
||||
pub async fn whois_handler(
|
||||
Query(params): Query<DomainParams>,
|
||||
) -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
let domain = params
|
||||
.domain
|
||||
.ok_or_else(|| AppError::BadRequest("domain parameter is required".into()))?;
|
||||
Ok((StatusCode::OK, Json(use_cases::whois(&domain).await?)))
|
||||
}
|
||||
|
||||
pub async fn ip_location_handler(
|
||||
Query(params): Query<IpParams>,
|
||||
) -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
let ip = params
|
||||
.ip
|
||||
.ok_or_else(|| AppError::BadRequest("ip parameter is required".into()))?;
|
||||
Ok((StatusCode::OK, Json(use_cases::ip_location(&ip).await?)))
|
||||
}
|
||||
|
||||
pub async fn tinyurl_handler(
|
||||
Query(params): Query<UrlParams>,
|
||||
) -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
let url = params
|
||||
.url
|
||||
.ok_or_else(|| AppError::BadRequest("url parameter is required".into()))?;
|
||||
Ok((StatusCode::OK, Json(use_cases::tinyurl(&url).await?)))
|
||||
}
|
||||
|
||||
pub async fn check_hosting_handler(
|
||||
Query(params): Query<DomainParams>,
|
||||
) -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
let domain = params
|
||||
.domain
|
||||
.ok_or_else(|| AppError::BadRequest("domain parameter is required".into()))?;
|
||||
Ok((
|
||||
StatusCode::OK,
|
||||
Json(use_cases::check_hosting(&domain).await?),
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn hargapangan_handler() -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
Ok((StatusCode::OK, Json(use_cases::hargapangan().await?)))
|
||||
}
|
||||
|
||||
pub async fn cek_resi_handler(
|
||||
Query(params): Query<ResiParams>,
|
||||
) -> Result<(StatusCode, Json<Value>), AppError> {
|
||||
let ResiParams { resi, ekspedisi } = params;
|
||||
let resi = resi.ok_or_else(|| AppError::BadRequest("resi parameter is required".into()))?;
|
||||
Ok((
|
||||
StatusCode::OK,
|
||||
Json(use_cases::cek_resi(resi, ekspedisi).await?),
|
||||
))
|
||||
}
|
||||
@@ -324,6 +324,31 @@ pub fn build_router(app_state: Arc<AppState>) -> anyhow::Result<Router> {
|
||||
"/search/yt",
|
||||
axum::routing::get(crate::presentation::handler::search::yt_handler),
|
||||
)
|
||||
// Tool routes
|
||||
.route(
|
||||
"/tool/whois",
|
||||
axum::routing::get(crate::presentation::handler::tools::whois_handler),
|
||||
)
|
||||
.route(
|
||||
"/tool/iplocation",
|
||||
axum::routing::get(crate::presentation::handler::tools::ip_location_handler),
|
||||
)
|
||||
.route(
|
||||
"/tool/tinyurl",
|
||||
axum::routing::get(crate::presentation::handler::tools::tinyurl_handler),
|
||||
)
|
||||
.route(
|
||||
"/tool/check-hosting",
|
||||
axum::routing::get(crate::presentation::handler::tools::check_hosting_handler),
|
||||
)
|
||||
.route(
|
||||
"/tool/hargapangan",
|
||||
axum::routing::get(crate::presentation::handler::tools::hargapangan_handler),
|
||||
)
|
||||
.route(
|
||||
"/tool/cek-resi",
|
||||
axum::routing::get(crate::presentation::handler::tools::cek_resi_handler),
|
||||
)
|
||||
// Health
|
||||
.route(
|
||||
"/health",
|
||||
|
||||
Reference in New Issue
Block a user