diff options
| author | Fuwn <[email protected]> | 2021-07-05 15:11:11 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2021-07-05 15:11:11 -0700 |
| commit | b15618cec3d3a111ebfbf82772bbe1ba0826d0fc (patch) | |
| tree | 1d559cd246d803590967c1f438217168b15f3743 | |
| parent | feat(whirl_server): implement a demo of the REGOBJID and APPRACTR commands (diff) | |
| download | whirl-b15618cec3d3a111ebfbf82772bbe1ba0826d0fc.tar.xz whirl-b15618cec3d3a111ebfbf82772bbe1ba0826d0fc.zip | |
feat(whirl_api): /api/v1/worlds/vip endpoint
An endpoint for checking if a given user has VIP status at the time of request. Example usage:
https://api.whirlsplash.org/api/v1/worlds/vip?username=fuwn will return `false`.
| -rw-r--r-- | crates/whirl_api/Cargo.toml | 4 | ||||
| -rw-r--r-- | crates/whirl_api/src/lib.rs | 1 | ||||
| -rw-r--r-- | crates/whirl_api/src/routes/mod.rs | 1 | ||||
| -rw-r--r-- | crates/whirl_api/src/routes/worlds/mod.rs | 4 | ||||
| -rw-r--r-- | crates/whirl_api/src/routes/worlds/vip/mod.rs | 53 | ||||
| -rw-r--r-- | crates/whirl_api/src/routes/worlds/vip/structures.rs | 8 |
6 files changed, 71 insertions, 0 deletions
diff --git a/crates/whirl_api/Cargo.toml b/crates/whirl_api/Cargo.toml index dc04cbf..626196d 100644 --- a/crates/whirl_api/Cargo.toml +++ b/crates/whirl_api/Cargo.toml @@ -22,6 +22,7 @@ sysinfo = "0.19.0" whirl_common = { path = "../whirl_common" } tokio = { version = "1.8.0", features = ["full"] } num-traits = "0.2.14" +qstring = "0.7.2" # Serialization serde = "1.0.126" @@ -32,3 +33,6 @@ log = "0.4.14" # Config whirl_config = { path = "../whirl_config" } + +# Web +curl = "0.4.38" diff --git a/crates/whirl_api/src/lib.rs b/crates/whirl_api/src/lib.rs index 3f09ce0..59de414 100644 --- a/crates/whirl_api/src/lib.rs +++ b/crates/whirl_api/src/lib.rs @@ -56,6 +56,7 @@ impl Api { .wrap(actix_cors::Cors::default().allow_any_origin()) .service(resource("/").to(|| async { "Whirlsplash" })) .service(resource("/api/v1/statistics").to(routes::stats::statistics)) + .service(resource("/api/v1/worlds/vip").to(routes::worlds::vip::vip)) }) .bind(address)? .run(); diff --git a/crates/whirl_api/src/routes/mod.rs b/crates/whirl_api/src/routes/mod.rs index ca664cd..562e73d 100644 --- a/crates/whirl_api/src/routes/mod.rs +++ b/crates/whirl_api/src/routes/mod.rs @@ -2,3 +2,4 @@ // SPDX-License-Identifier: GPL-3.0-only pub mod stats; +pub mod worlds; diff --git a/crates/whirl_api/src/routes/worlds/mod.rs b/crates/whirl_api/src/routes/worlds/mod.rs new file mode 100644 index 0000000..32351f8 --- /dev/null +++ b/crates/whirl_api/src/routes/worlds/mod.rs @@ -0,0 +1,4 @@ +// Copyright (C) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +pub mod vip; diff --git a/crates/whirl_api/src/routes/worlds/vip/mod.rs b/crates/whirl_api/src/routes/worlds/vip/mod.rs new file mode 100644 index 0000000..c9455e6 --- /dev/null +++ b/crates/whirl_api/src/routes/worlds/vip/mod.rs @@ -0,0 +1,53 @@ +// Copyright (C) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +mod structures; + +use std::str::from_utf8; + +use actix_web::{HttpRequest, HttpResponse}; + +use crate::routes::worlds::vip::structures::Vip; + +// error: this argument is passed by value, but not consumed in the function +// body +#[allow(clippy::needless_pass_by_value)] +pub fn vip(req: HttpRequest) -> HttpResponse { + let queries = qstring::QString::from(req.query_string()); + let mut easy = curl::easy::Easy::new(); + let mut error = String::new(); + + let username = queries.get("username"); + if username.is_none() || username.map_or(false, str::is_empty) { + error = "no username query parameter provided, defaulting to 'null'".to_string(); + } + + easy + .url(&format!( + "http://www-dynamic.us.worlds.net/cgi-bin/vip.pl?Username={}", + username.unwrap_or("null"), + )) + .unwrap(); + + let mut response = Vec::new(); + + // https://docs.rs/curl/0.4.6/curl/easy/struct.Easy.html + { + let mut transfer = easy.transfer(); + transfer + .write_function(|data| { + response.extend_from_slice(data); + Ok(data.len()) + }) + .unwrap(); + transfer.perform().unwrap(); + } + + HttpResponse::Ok().json(Vip { + vip: from_utf8(&response) + .unwrap() + .to_string() + .contains("You're already a VIP!"), + error: if error.is_empty() { None } else { Some(error) }, + }) +} diff --git a/crates/whirl_api/src/routes/worlds/vip/structures.rs b/crates/whirl_api/src/routes/worlds/vip/structures.rs new file mode 100644 index 0000000..5438b49 --- /dev/null +++ b/crates/whirl_api/src/routes/worlds/vip/structures.rs @@ -0,0 +1,8 @@ +// Copyright (C) 2021-2021 The Whirlsplash Collective +// SPDX-License-Identifier: GPL-3.0-only + +#[derive(Serialize)] +pub struct Vip { + pub vip: bool, + pub error: Option<String>, +} |