ExtraChat/server/src/util.rs

270 lines
7.9 KiB
Rust

use anyhow::{Context, Result};
use futures_util::SinkExt;
use prefixed_api_key::ApiKey;
use sha3::Sha3_256;
use tokio::sync::RwLock;
use tokio_tungstenite::tungstenite::Message as WsMessage;
use uuid::Uuid;
use crate::{Digest, ResponseContainer, State, types::protocol::ResponseKind, World, WsStream};
pub mod redacted;
pub async fn send(conn: &mut WsStream, number: u32, msg: impl Into<ResponseKind>) -> Result<()> {
let container = ResponseContainer {
number,
kind: msg.into(),
};
conn.send(WsMessage::Binary(rmp_serde::to_vec(&container)?)).await?;
Ok(())
}
pub async fn send_to_all(state: &RwLock<State>, channel_id: Uuid, number: u32, msg: impl Into<ResponseKind>) -> Result<()> {
let members = get_raw_members(state, channel_id).await?
.into_iter()
.chain(get_raw_invited_members(state, channel_id).await?.into_iter());
let resp = ResponseContainer {
number,
kind: msg.into(),
};
for member in members {
if let Some(client) = state.read().await.clients.get(&(member.lodestone_id as u64)) {
client.read().await.tx.send(resp.clone()).await.ok();
}
}
Ok(())
}
#[derive(Debug)]
pub struct RawMember {
pub lodestone_id: i64,
pub name: String,
pub world: String,
pub rank: i64,
}
pub async fn get_raw_members(state: &RwLock<State>, channel: Uuid) -> Result<Vec<RawMember>> {
let id = channel.as_simple().to_string();
sqlx::query_as!(
RawMember,
// language=sqlite
"select users.lodestone_id, users.name, users.world, user_channels.rank from user_channels inner join users on users.lodestone_id = user_channels.lodestone_id where user_channels.channel_id = ?",
id,
)
.fetch_all(&state.read().await.db)
.await
.context("could not get channel members")
}
pub async fn get_raw_invited_members(state: &RwLock<State>, channel: Uuid) -> Result<Vec<RawMember>> {
let id = channel.as_simple().to_string();
sqlx::query_as!(
RawMember,
// language=sqlite
"select users.lodestone_id, users.name, users.world, cast(0 as int) as rank from channel_invites inner join users on users.lodestone_id = channel_invites.invited where channel_invites.channel_id = ?",
id,
)
.fetch_all(&state.read().await.db)
.await
.context("could not get channel members")
}
pub async fn is_invited(state: &RwLock<State>, channel: Uuid, id: u64) -> Result<bool> {
let channel_id = channel.as_simple().to_string();
let id = id as i64;
sqlx::query!(
// language=sqlite
"select count(*) as count from channel_invites where channel_id = ? and invited = ?",
channel_id,
id,
)
.fetch_one(&state.read().await.db)
.await
.context("could not get channel members")
.map(|x| x.count > 0)
}
pub fn hash_key(key: &ApiKey) -> String {
let mut hasher = Sha3_256::new();
hasher.update(&key.long_bytes);
hex::encode(&hasher.finalize()[..])
}
pub fn id_from_world(world: World) -> u16 {
match world {
World::Ravana => 21,
World::Bismarck => 22,
World::Asura => 23,
World::Belias => 24,
World::Pandaemonium => 28,
World::Shinryu => 29,
World::Unicorn => 30,
World::Yojimbo => 31,
World::Zeromus => 32,
World::Twintania => 33,
World::Brynhildr => 34,
World::Famfrit => 35,
World::Lich => 36,
World::Mateus => 37,
World::Omega => 39,
World::Jenova => 40,
World::Zalera => 41,
World::Zodiark => 42,
World::Alexander => 43,
World::Anima => 44,
World::Carbuncle => 45,
World::Fenrir => 46,
World::Hades => 47,
World::Ixion => 48,
World::Kujata => 49,
World::Typhon => 50,
World::Ultima => 51,
World::Valefor => 52,
World::Exodus => 53,
World::Faerie => 54,
World::Lamia => 55,
World::Phoenix => 56,
World::Siren => 57,
World::Garuda => 58,
World::Ifrit => 59,
World::Ramuh => 60,
World::Titan => 61,
World::Diabolos => 62,
World::Gilgamesh => 63,
World::Leviathan => 64,
World::Midgardsormr => 65,
World::Odin => 66,
World::Shiva => 67,
World::Atomos => 68,
World::Bahamut => 69,
World::Chocobo => 70,
World::Moogle => 71,
World::Tonberry => 72,
World::Adamantoise => 73,
World::Coeurl => 74,
World::Malboro => 75,
World::Tiamat => 76,
World::Ultros => 77,
World::Behemoth => 78,
World::Cactuar => 79,
World::Cerberus => 80,
World::Goblin => 81,
World::Mandragora => 82,
World::Louisoix => 83,
World::Spriggan => 85,
World::Sephirot => 86,
World::Sophia => 87,
World::Zurvan => 88,
World::Aegis => 90,
World::Balmung => 91,
World::Durandal => 92,
World::Excalibur => 93,
World::Gungnir => 94,
World::Hyperion => 95,
World::Masamune => 96,
World::Ragnarok => 97,
World::Ridill => 98,
World::Sargatanas => 99,
World::Sagittarius => 400,
World::Phantom => 401,
World::Alpha => 402,
World::Raiden => 403,
World::Marilith => 404,
World::Seraph => 405,
World::Halicarnassus => 406,
World::Maduin => 407,
}
}
pub fn world_from_id(id: u16) -> Option<World> {
let world = match id {
21 => World::Ravana,
22 => World::Bismarck,
23 => World::Asura,
24 => World::Belias,
28 => World::Pandaemonium,
29 => World::Shinryu,
30 => World::Unicorn,
31 => World::Yojimbo,
32 => World::Zeromus,
33 => World::Twintania,
34 => World::Brynhildr,
35 => World::Famfrit,
36 => World::Lich,
37 => World::Mateus,
39 => World::Omega,
40 => World::Jenova,
41 => World::Zalera,
42 => World::Zodiark,
43 => World::Alexander,
44 => World::Anima,
45 => World::Carbuncle,
46 => World::Fenrir,
47 => World::Hades,
48 => World::Ixion,
49 => World::Kujata,
50 => World::Typhon,
51 => World::Ultima,
52 => World::Valefor,
53 => World::Exodus,
54 => World::Faerie,
55 => World::Lamia,
56 => World::Phoenix,
57 => World::Siren,
58 => World::Garuda,
59 => World::Ifrit,
60 => World::Ramuh,
61 => World::Titan,
62 => World::Diabolos,
63 => World::Gilgamesh,
64 => World::Leviathan,
65 => World::Midgardsormr,
66 => World::Odin,
67 => World::Shiva,
68 => World::Atomos,
69 => World::Bahamut,
70 => World::Chocobo,
71 => World::Moogle,
72 => World::Tonberry,
73 => World::Adamantoise,
74 => World::Coeurl,
75 => World::Malboro,
76 => World::Tiamat,
77 => World::Ultros,
78 => World::Behemoth,
79 => World::Cactuar,
80 => World::Cerberus,
81 => World::Goblin,
82 => World::Mandragora,
83 => World::Louisoix,
85 => World::Spriggan,
86 => World::Sephirot,
87 => World::Sophia,
88 => World::Zurvan,
90 => World::Aegis,
91 => World::Balmung,
92 => World::Durandal,
93 => World::Excalibur,
94 => World::Gungnir,
95 => World::Hyperion,
96 => World::Masamune,
97 => World::Ragnarok,
98 => World::Ridill,
99 => World::Sargatanas,
400 => World::Sagittarius,
401 => World::Phantom,
402 => World::Alpha,
403 => World::Raiden,
404 => World::Marilith,
405 => World::Seraph,
406 => World::Halicarnassus,
407 => World::Maduin,
_ => return None,
};
Some(world)
}