nuke old api, add html
This commit is contained in:
parent
747998e3c6
commit
29a3bdcda7
6 changed files with 81 additions and 435 deletions
|
@ -1,109 +0,0 @@
|
||||||
use crate::redispool::RedisPool;
|
|
||||||
use core::time;
|
|
||||||
use rocket_db_pools::deadpool_redis::redis::{pipe, AsyncCommands};
|
|
||||||
use rocket_db_pools::Connection;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::ops::Sub;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct ClassCounts {
|
|
||||||
world_id: String,
|
|
||||||
classes: Classes,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct Classes {
|
|
||||||
light_assault: i32,
|
|
||||||
engineer: i32,
|
|
||||||
combat_medic: i32,
|
|
||||||
heavy_assault: i32,
|
|
||||||
infiltrator: i32,
|
|
||||||
max: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/w/<world_id>/classes")]
|
|
||||||
pub async fn get_classes(world_id: String, mut con: Connection<RedisPool>) -> serde_json::Value {
|
|
||||||
let cache_key = format!("cache:classes:{}", world_id);
|
|
||||||
|
|
||||||
match con.get::<String, String>(cache_key.clone()).await {
|
|
||||||
Ok(cached) => {
|
|
||||||
return serde_json::from_str(&cached).unwrap();
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let classes = fetch_classes(world_id.clone(), &mut con).await;
|
|
||||||
|
|
||||||
// I hate this but it's fast???
|
|
||||||
// The type only allows 12 at a time.
|
|
||||||
|
|
||||||
let response = ClassCounts { world_id, classes };
|
|
||||||
|
|
||||||
let out = json!(response);
|
|
||||||
|
|
||||||
con.set_ex::<String, String, ()>(cache_key, out.to_string(), 5)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn fetch_classes(world_id: String, con: &mut Connection<RedisPool>) -> Classes {
|
|
||||||
let filter_timestamp = SystemTime::now()
|
|
||||||
.sub(time::Duration::from_secs(60 * 15))
|
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
|
||||||
.unwrap()
|
|
||||||
.as_secs();
|
|
||||||
|
|
||||||
let (light_assault, engineer, combat_medic, heavy_assault, infiltrator, max): (
|
|
||||||
i32,
|
|
||||||
i32,
|
|
||||||
i32,
|
|
||||||
i32,
|
|
||||||
i32,
|
|
||||||
i32,
|
|
||||||
) = pipe()
|
|
||||||
.zcount(
|
|
||||||
format!("c:{}/{}", world_id, "light_assault"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("c:{}/{}", world_id, "engineer"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("c:{}/{}", world_id, "combat_medic"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("c:{}/{}", world_id, "heavy_assault"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("c:{}/{}", world_id, "infiltrator"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("c:{}/{}", world_id, "max"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.query_async(&mut **con)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Classes {
|
|
||||||
light_assault,
|
|
||||||
engineer,
|
|
||||||
combat_medic,
|
|
||||||
heavy_assault,
|
|
||||||
infiltrator,
|
|
||||||
max,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -84,6 +84,11 @@ pub fn playground() -> RawHtml<String> {
|
||||||
juniper_rocket::playground_source("/graphql", None)
|
juniper_rocket::playground_source("/graphql", None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/playground")]
|
||||||
|
pub fn playground2() -> RawHtml<String> {
|
||||||
|
juniper_rocket::playground_source("/graphql", None)
|
||||||
|
}
|
||||||
|
|
||||||
#[post("/", data = "<query>")]
|
#[post("/", data = "<query>")]
|
||||||
pub async fn post_graphql(
|
pub async fn post_graphql(
|
||||||
query: juniper_rocket::GraphQLRequest,
|
query: juniper_rocket::GraphQLRequest,
|
||||||
|
|
55
services/api/src/html/index.html
Normal file
55
services/api/src/html/index.html
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Saerro Listening Post</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: monospace;
|
||||||
|
background-color: #010101;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #cead42;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<h1>Saerro Listening Post</h1>
|
||||||
|
<h2>Live Population Stats API for PlanetSide 2</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/graphql/playground">Check out the GraphQL Playground</a></li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/graphql?query=%7B%20health%20%7B%20pc%20redis%20ps4us%20ps4eu%20%7D%7D"
|
||||||
|
>Current system status</a
|
||||||
|
>
|
||||||
|
(<a
|
||||||
|
href="/graphql/playground?query=%7B%20health%20%7B%20pc%20redis%20ps4us%20ps4eu%20%7D%7D"
|
||||||
|
>or in playground</a
|
||||||
|
>)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
href="/graphql?query=%7B%0A%20%20allWorlds%20%7B%0A%20%20%20%20name%0A%20%20%20%20population%0A%20%20%7D%0A%7D%0A"
|
||||||
|
>
|
||||||
|
Current population of all worlds
|
||||||
|
</a>
|
||||||
|
(<a
|
||||||
|
href="/graphql/playground?query=%7B%0A%20%20allWorlds%20%7B%0A%20%20%20%20name%0A%20%20%20%20population%0A%20%20%7D%0A%7D%0A"
|
||||||
|
>or in playground</a
|
||||||
|
>)
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
All data is an aggregate of the last 15 minutes of Death and VehicleDestroy
|
||||||
|
events, including both attacker and victim.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
This API is provided by Genudine Dynamics.<br />As always, we take no
|
||||||
|
responsibility for your use of this data... or our weapons. :)
|
||||||
|
</p>
|
||||||
|
<p>For help, please contact us in #api-dev on the PlanetSide 2 Discord.</p>
|
||||||
|
<p>[<a href="https://github.com/genudine/saerro">github</a>]</p>
|
|
@ -1,12 +1,11 @@
|
||||||
pub mod classes;
|
|
||||||
pub mod cors;
|
pub mod cors;
|
||||||
pub mod graphql;
|
pub mod graphql;
|
||||||
pub mod population;
|
|
||||||
pub mod redispool;
|
pub mod redispool;
|
||||||
pub mod vehicles;
|
|
||||||
|
|
||||||
use redispool::RedisPool;
|
use redispool::RedisPool;
|
||||||
use rocket::fairing::AdHoc;
|
use rocket::fairing::AdHoc;
|
||||||
|
use rocket::response::content::RawHtml;
|
||||||
|
use rocket::response::status;
|
||||||
use rocket::{error, Build, Rocket};
|
use rocket::{error, Build, Rocket};
|
||||||
use rocket_db_pools::deadpool_redis::redis::{cmd, pipe};
|
use rocket_db_pools::deadpool_redis::redis::{cmd, pipe};
|
||||||
use rocket_db_pools::{Connection, Database};
|
use rocket_db_pools::{Connection, Database};
|
||||||
|
@ -16,42 +15,15 @@ extern crate rocket;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_json;
|
extern crate serde_json;
|
||||||
|
|
||||||
fn hello_world(host: String, world_id: &str) -> serde_json::Value {
|
|
||||||
json!({
|
|
||||||
"population": format!("https://{}/w/{}", host, world_id),
|
|
||||||
"vehicles": format!("https://{}/w/{}/vehicles", host, world_id),
|
|
||||||
"classes": format!("https://{}/w/{}/classes", host, world_id),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hello(host: String) -> serde_json::Value {
|
|
||||||
json!({
|
|
||||||
"@": "Saerro Listening Post - PlanetSide 2 Live Population API",
|
|
||||||
"@GitHub": "https://github.com/genudine/saerro",
|
|
||||||
"@Disclaimer": "Genudine Dynamics is not responsible for any damages caused by this software. Use at your own risk.",
|
|
||||||
"@Support": "#api-dev in https://discord.com/servers/planetside-2-community-251073753759481856",
|
|
||||||
"GraphQL": format!("https://{}/graphql", host),
|
|
||||||
"Worlds": {
|
|
||||||
"Connery": hello_world(host.clone(), "1"),
|
|
||||||
"Miller": hello_world(host.clone(), "10"),
|
|
||||||
"Cobalt": hello_world(host.clone(), "13"),
|
|
||||||
"Emerald": hello_world(host.clone(), "17"),
|
|
||||||
"Jaeger": hello_world(host.clone(), "19"),
|
|
||||||
"SolTech": hello_world(host.clone(), "40"),
|
|
||||||
"Genudine": hello_world(host.clone(), "1000"),
|
|
||||||
"Ceres": hello_world(host.clone(), "2000"),
|
|
||||||
},
|
|
||||||
// "All World Population": format!("https://{}/m/?ids=1,10,13,17,19,40,1000,2000", host),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
fn index() -> serde_json::Value {
|
async fn index() -> RawHtml<String> {
|
||||||
hello("saerro.harasse.rs".to_string())
|
RawHtml(include_str!("html/index.html").to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/health")]
|
#[get("/health")]
|
||||||
async fn health(mut con: Connection<RedisPool>) -> serde_json::Value {
|
async fn health(
|
||||||
|
mut con: Connection<RedisPool>,
|
||||||
|
) -> Result<serde_json::Value, status::Custom<serde_json::Value>> {
|
||||||
let (ping, pc, ps4us, ps4eu): (String, bool, bool, bool) = pipe()
|
let (ping, pc, ps4us, ps4eu): (String, bool, bool, bool) = pipe()
|
||||||
.cmd("PING")
|
.cmd("PING")
|
||||||
.get("heartbeat:pc")
|
.get("heartbeat:pc")
|
||||||
|
@ -61,13 +33,23 @@ async fn health(mut con: Connection<RedisPool>) -> serde_json::Value {
|
||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
if ping != "PONG" {
|
||||||
|
return Err(status::Custom(
|
||||||
|
rocket::http::Status::ServiceUnavailable,
|
||||||
json!({
|
json!({
|
||||||
|
"status": "error",
|
||||||
|
"message": "Redis is not responding",
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(json!({
|
||||||
"status": if ping == "PONG" && pc && ps4us && ps4eu { "ok" } else { "degraded" },
|
"status": if ping == "PONG" && pc && ps4us && ps4eu { "ok" } else { "degraded" },
|
||||||
"redis": ping == "PONG",
|
"redis": ping == "PONG",
|
||||||
"pc": if pc { "primary" } else { "backup/down" },
|
"pc": if pc { "primary" } else { "backup/down" },
|
||||||
"ps4us": if ps4us { "primary" } else { "backup/down" },
|
"ps4us": if ps4us { "primary" } else { "backup/down" },
|
||||||
"ps4eu": if ps4eu { "primary" } else { "backup/down" },
|
"ps4eu": if ps4eu { "primary" } else { "backup/down" },
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[launch]
|
#[launch]
|
||||||
|
@ -95,21 +77,13 @@ fn rocket() -> Rocket<Build> {
|
||||||
rocket
|
rocket
|
||||||
}))
|
}))
|
||||||
.manage(graphql::schema())
|
.manage(graphql::schema())
|
||||||
.mount(
|
.mount("/", routes![index, health,])
|
||||||
"/",
|
|
||||||
routes![
|
|
||||||
index,
|
|
||||||
health,
|
|
||||||
population::get_world_pop,
|
|
||||||
vehicles::get_vehicles,
|
|
||||||
classes::get_classes,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.mount(
|
.mount(
|
||||||
"/graphql",
|
"/graphql",
|
||||||
routes![
|
routes![
|
||||||
graphql::graphiql,
|
graphql::graphiql,
|
||||||
graphql::playground,
|
graphql::playground,
|
||||||
|
graphql::playground2,
|
||||||
graphql::get_graphql,
|
graphql::get_graphql,
|
||||||
graphql::post_graphql
|
graphql::post_graphql
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
use core::time;
|
|
||||||
use std::{ops::Sub, time::SystemTime};
|
|
||||||
|
|
||||||
use rocket_db_pools::{deadpool_redis::redis::pipe, Connection};
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::redispool::RedisPool;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct Factions {
|
|
||||||
pub tr: i32,
|
|
||||||
pub nc: i32,
|
|
||||||
pub vs: i32,
|
|
||||||
pub ns: i32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct WorldPopulation {
|
|
||||||
world_id: i32,
|
|
||||||
pub total: i32,
|
|
||||||
pub factions: Factions,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
pub struct MultipleWorldPopulation {
|
|
||||||
worlds: Vec<WorldPopulation>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/w/<world_id>")]
|
|
||||||
pub async fn get_world_pop(world_id: String, mut con: Connection<RedisPool>) -> serde_json::Value {
|
|
||||||
json!(fetch_world_pop(world_id, &mut con).await)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn fetch_world_pop(world_id: String, con: &mut Connection<RedisPool>) -> WorldPopulation {
|
|
||||||
let filter_timestamp = SystemTime::now()
|
|
||||||
.sub(time::Duration::from_secs(60 * 15))
|
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
|
||||||
.unwrap()
|
|
||||||
.as_secs();
|
|
||||||
|
|
||||||
let (vs, nc, tr, ns): (i32, i32, i32, i32) = pipe()
|
|
||||||
.zcount(format!("wp:{}/{}", world_id, 1), filter_timestamp, "+inf")
|
|
||||||
.zcount(format!("wp:{}/{}", world_id, 2), filter_timestamp, "+inf")
|
|
||||||
.zcount(format!("wp:{}/{}", world_id, 3), filter_timestamp, "+inf")
|
|
||||||
.zcount(format!("wp:{}/{}", world_id, 4), filter_timestamp, "+inf")
|
|
||||||
.query_async(&mut **con)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let total = tr + vs + nc;
|
|
||||||
|
|
||||||
WorldPopulation {
|
|
||||||
world_id: world_id.parse().unwrap(),
|
|
||||||
total,
|
|
||||||
factions: Factions { tr, nc, vs, ns },
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,222 +0,0 @@
|
||||||
use core::time;
|
|
||||||
use rocket_db_pools::deadpool_redis::redis::{pipe, AsyncCommands};
|
|
||||||
use rocket_db_pools::Connection;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::ops::Sub;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
use crate::redispool::RedisPool;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct VehiclesCounts {
|
|
||||||
world_id: String,
|
|
||||||
total: u32,
|
|
||||||
vehicles: Vehicles,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
|
||||||
struct Vehicles {
|
|
||||||
flash: u32,
|
|
||||||
sunderer: u32,
|
|
||||||
lightning: u32,
|
|
||||||
scythe: u32,
|
|
||||||
vanguard: u32,
|
|
||||||
prowler: u32,
|
|
||||||
reaver: u32,
|
|
||||||
mosquito: u32,
|
|
||||||
galaxy: u32,
|
|
||||||
valkyrie: u32,
|
|
||||||
liberator: u32,
|
|
||||||
ant: u32,
|
|
||||||
harasser: u32,
|
|
||||||
dervish: u32,
|
|
||||||
chimera: u32,
|
|
||||||
javelin: u32,
|
|
||||||
corsair: u32,
|
|
||||||
magrider: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[get("/w/<world_id>/vehicles")]
|
|
||||||
pub async fn get_vehicles(world_id: String, mut con: Connection<RedisPool>) -> serde_json::Value {
|
|
||||||
let cache_key = format!("cache:vehicles:{}", world_id);
|
|
||||||
|
|
||||||
match con.get::<String, String>(cache_key.clone()).await {
|
|
||||||
Ok(cached) => {
|
|
||||||
return serde_json::from_str(&cached).unwrap();
|
|
||||||
}
|
|
||||||
Err(_) => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
let filter_timestamp = SystemTime::now()
|
|
||||||
.sub(time::Duration::from_secs(60 * 15))
|
|
||||||
.duration_since(SystemTime::UNIX_EPOCH)
|
|
||||||
.unwrap()
|
|
||||||
.as_secs();
|
|
||||||
|
|
||||||
// I hate this but it's fast???
|
|
||||||
// The type only allows 12 at a time.
|
|
||||||
let (
|
|
||||||
flash,
|
|
||||||
sunderer,
|
|
||||||
lightning,
|
|
||||||
scythe,
|
|
||||||
vanguard,
|
|
||||||
prowler,
|
|
||||||
reaver,
|
|
||||||
mosquito,
|
|
||||||
galaxy,
|
|
||||||
valkyrie,
|
|
||||||
liberator,
|
|
||||||
ant
|
|
||||||
): (u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32) = pipe()
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "flash"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "sunderer"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "lightning"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "scythe"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "vanguard"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "prowler"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "reaver"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "mosquito"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "galaxy"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "valkyrie"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "liberator"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "ant"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.query_async(&mut *con)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (harasser, dervish, chimera, javelin, corsair, magrider): (u32, u32, u32, u32, u32, u32) = pipe()
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "harasser"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "dervish"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "chimera"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "javelin"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "corsair"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.zcount(
|
|
||||||
format!("v:{}/{}", world_id, "magrider"),
|
|
||||||
filter_timestamp,
|
|
||||||
"+inf",
|
|
||||||
)
|
|
||||||
.query_async(&mut *con)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let total = flash
|
|
||||||
+ sunderer
|
|
||||||
+ lightning
|
|
||||||
+ scythe
|
|
||||||
+ vanguard
|
|
||||||
+ prowler
|
|
||||||
+ reaver
|
|
||||||
+ mosquito
|
|
||||||
+ galaxy
|
|
||||||
+ valkyrie
|
|
||||||
+ liberator
|
|
||||||
+ ant
|
|
||||||
+ harasser
|
|
||||||
+ dervish
|
|
||||||
+ chimera
|
|
||||||
+ javelin
|
|
||||||
+ corsair
|
|
||||||
+ magrider;
|
|
||||||
|
|
||||||
let response = VehiclesCounts {
|
|
||||||
world_id,
|
|
||||||
total,
|
|
||||||
vehicles: Vehicles {
|
|
||||||
flash,
|
|
||||||
sunderer,
|
|
||||||
lightning,
|
|
||||||
scythe,
|
|
||||||
vanguard,
|
|
||||||
prowler,
|
|
||||||
reaver,
|
|
||||||
mosquito,
|
|
||||||
galaxy,
|
|
||||||
valkyrie,
|
|
||||||
liberator,
|
|
||||||
ant,
|
|
||||||
harasser,
|
|
||||||
dervish,
|
|
||||||
chimera,
|
|
||||||
javelin,
|
|
||||||
corsair,
|
|
||||||
magrider
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let out = json!(response);
|
|
||||||
|
|
||||||
con.set_ex::<String, String, ()>(cache_key, out.to_string(), 5)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
out
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue