1
0
mirror of https://git.ngram.ca/OpenJam/rc-servers synced 2026-08-23 23:08:52 +00:00

Implement basic chat functionality

This commit is contained in:
NGnius (Graham)
2025-04-14 21:17:41 -04:00
parent 4d2ddaeafb
commit 792a6362e3
37 changed files with 1119 additions and 34 deletions

View File

@@ -36,3 +36,27 @@ pub enum WebServicesError {
UsernameTooShort = 206,
SaleEnded = 207
}
#[repr(i16)]
#[allow(dead_code)]
#[derive(Debug)]
pub enum ChatErrorCodes {
None = 0,
UnexpectedError = 1,
Flood = 2,
Muted = 3,
NotOnline = 4,
DoesNotExist = 5,
NoConnection = 6,
ModeratorsOnly = 7,
AdminsOnly = 8,
SanctionAlreadyExists = 9,
AlreadyWarned = 10,
NoSanctionExists = 11,
MaintenanceMode = 12,
ChannelExists = 13,
IncorrectPassword = 14,
ChannelNotExists = 15,
PasswordRequired = 16,
ChannelExpired = 17,
}

View File

@@ -0,0 +1,15 @@
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ChatConfig {
#[serde(default = "default_pub_channs")]
pub public_channels: Vec<String>,
}
fn default_pub_channs() -> Vec<String> {
vec![
"main".to_owned(),
"sys".to_owned(),
"openjam_worship".to_owned(),
]
}

View File

@@ -5,7 +5,7 @@ use serde::{Serialize, Deserialize};
use polariton::operation::{Typed, Dict};
use polariton::serdes::TypePrefix;
use super::super::{MovementCategoryData, MovementData, Cube, ItemCategory, ItemTier, BattleConfig, Settings};
use super::super::{MovementCategoryData, MovementData, Cube, ItemCategory, ItemTier, BattleConfig, Settings, ChatConfig};
const CUBE_CONFIG_FILENAME: &str = "config.json";
@@ -15,6 +15,7 @@ pub struct CubeConfig {
movement: HashMap<ItemCategory, MovementCategoryData>,
lerp_value: f32,
battle: BattleConfig,
chat: ChatConfig,
settings: Settings,
}
@@ -247,4 +248,11 @@ impl <C: Clone> super::ConfigProvider<C> for CubeConfig {
fn login_messages(&self) -> super::DevMessageProvider<C> {
super::DevMessageProvider::new(self.settings.banners.iter().map(|msg| (msg.message.clone(), msg.duration as i32)).collect())
}
fn public_channels(&self) -> Typed<C> {
Typed::Arr(polariton::operation::Arr {
ty: TypePrefix::Str,
items: self.chat.public_channels.iter().map(|s| Typed::Str(s.into())).collect(),
})
}
}

View File

@@ -17,6 +17,7 @@ pub trait ConfigProvider<C: Clone> {
fn campaign_details(&self) -> CompleteCampaignProvider;
fn client_config(&self) -> Typed<C>;
fn login_messages(&self) -> DevMessageProvider<C>;
fn public_channels(&self) -> Typed<C>;
}
pub struct CompleteCampaignProvider {

View File

@@ -29,6 +29,9 @@ pub use client_config::GameplaySettings;
mod settings;
pub use settings::Settings;
mod chat;
pub use chat::ChatConfig;
pub(self) const VALID_ROBOT: &[u8] = &[64,
0,
0,

View File

@@ -34,7 +34,7 @@ impl AccountProvider {
}
impl <C: Clone> super::UserProvider<C> for AccountProvider {
fn authenticate(&self, token: super::UserToken) -> Result<Box<dyn super::User<C> + Send + Sync>, String> {
fn authenticate(&self, token: super::UserToken, ext: std::collections::HashMap<std::any::TypeId, Box<dyn std::any::Any + Send + Sync + 'static>>) -> Result<Box<dyn super::User<C> + Send + Sync>, String> {
let new_root = self.root.join(&token.uuid);
let secret = jsonwebtoken::DecodingKey::from_secret(&self.secret);
let mut validation = jsonwebtoken::Validation::new(jsonwebtoken::Algorithm::HS256);
@@ -46,6 +46,7 @@ impl <C: Clone> super::UserProvider<C> for AccountProvider {
token,
account: account_info,
cubes: self.cubes.clone(),
extensions: ext,
}))
//Err("Unable to authenticate".to_string())
}
@@ -124,6 +125,7 @@ struct UserData {
token: super::UserToken,
account: AccountInfo,
cubes: std::sync::Arc<Vec<u32>>,
extensions: std::collections::HashMap<std::any::TypeId, Box<dyn std::any::Any + Send + Sync + 'static>>,
}
impl UserData {
@@ -159,6 +161,10 @@ const INVALID_ROBOT_ERR: i16 = 140;
const DATABASE_ERR: i16 = 8;
impl <C: Clone> super::User<C> for UserData {
fn ext(&self, ty: std::any::TypeId) -> Option<&'_ (dyn std::any::Any + Send + Sync + 'static)> {
self.extensions.get(&ty).map(|x| x.as_ref())
}
fn token(&self) -> &'_ super::UserToken {
&self.token
}
@@ -312,7 +318,6 @@ impl <C: Clone> super::User<C> for UserData {
],
}.as_transmissible())
}
}
#[derive(Serialize, Deserialize, Clone, Debug)]

View File

@@ -26,7 +26,7 @@ pub struct UserLoginInfo {
}
pub trait UserProvider<C> {
fn authenticate(&self, user: UserToken) -> Result<Box<dyn User<C> + Send + Sync>, String>;
fn authenticate(&self, user: UserToken, ext: std::collections::HashMap<std::any::TypeId, Box<dyn std::any::Any + Send + Sync + 'static>>) -> Result<Box<dyn User<C> + Send + Sync>, String>;
}
pub trait UserAuthenticator {
@@ -34,6 +34,7 @@ pub trait UserAuthenticator {
}
pub trait User<C> {
fn ext(&self, ty: std::any::TypeId) -> Option<&'_ (dyn std::any::Any + Send + Sync + 'static)>;
fn token(&self) -> &'_ super::UserToken;
fn is_mod(&self) -> bool;
fn is_admin(&self) -> bool;

View File

@@ -8,6 +8,10 @@ pub struct UserState<C: Clone = ()> {
impl <C: Clone> UserState<C> {
pub fn update_with_auth(&self, auth_str: &str) -> bool {
self.update_with_auth_ext(auth_str, |_| Some(Default::default()))
}
pub fn update_with_auth_ext<F: FnOnce(&crate::persist::user::UserToken) -> Option<std::collections::HashMap<std::any::TypeId, Box<dyn std::any::Any + Send + Sync + 'static>>>>(&self, auth_str: &str, ext_f: F) -> bool {
let mut lock = self.state.write().unwrap();
match &*lock {
InitState::Unauthenticated(auth) => {
@@ -21,7 +25,12 @@ impl <C: Clone> UserState<C> {
token: splits[1].to_owned(),
refresh_token: splits[2].to_owned(),
};
match auth.authenticate(token) {
let ext = if let Some(ext) = ext_f(&token) {
ext
} else {
return false;
};
match auth.authenticate(token, ext) {
Ok(user) => {
*lock = InitState::Authenticated(std::sync::Arc::new(user));
true