new language manager that loads strings from compiled json file
This commit is contained in:
parent
1927d381ab
commit
6a7491d094
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
||||
/venv
|
||||
.cargo
|
||||
assets
|
||||
out.json
|
||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1336,7 +1336,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reminder_rs"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0-dev"
|
||||
dependencies = [
|
||||
"Inflector",
|
||||
"async-trait",
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "reminder_rs"
|
||||
version = "1.2.3"
|
||||
version = "1.3.0-dev"
|
||||
authors = ["jellywx <judesouthworth@pm.me>"]
|
||||
edition = "2018"
|
||||
|
||||
|
@ -10,6 +10,7 @@ use crate::{
|
||||
SQLPool, THEME_COLOR,
|
||||
};
|
||||
|
||||
use crate::language_manager::LanguageManager;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[command]
|
||||
@ -31,16 +32,18 @@ async fn ping(ctx: &Context, msg: &Message, _args: String) {
|
||||
#[command]
|
||||
#[can_blacklist(false)]
|
||||
async fn help(ctx: &Context, msg: &Message, _args: String) {
|
||||
let pool = ctx
|
||||
.data
|
||||
.read()
|
||||
.await
|
||||
let data = ctx.data.read().await;
|
||||
|
||||
let pool = data
|
||||
.get::<SQLPool>()
|
||||
.cloned()
|
||||
.expect("Could not get SQLPool from data");
|
||||
|
||||
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
||||
let desc = user_data.response(&pool, "help").await;
|
||||
let lm = data.get::<LanguageManager>().unwrap();
|
||||
|
||||
let language = UserData::language_of(&msg.author, &ctx, &pool).await;
|
||||
|
||||
let desc = lm.get(&language, "help");
|
||||
|
||||
let _ = msg
|
||||
.channel_id
|
||||
@ -63,22 +66,22 @@ async fn help(ctx: &Context, msg: &Message, _args: String) {
|
||||
|
||||
#[command]
|
||||
async fn info(ctx: &Context, msg: &Message, _args: String) {
|
||||
let pool = ctx
|
||||
.data
|
||||
.read()
|
||||
.await
|
||||
let data = ctx.data.read().await;
|
||||
|
||||
let pool = data
|
||||
.get::<SQLPool>()
|
||||
.cloned()
|
||||
.expect("Could not get SQLPool from data");
|
||||
|
||||
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
||||
let lm = data.get::<LanguageManager>().unwrap();
|
||||
|
||||
let language = UserData::language_of(&msg.author, &ctx, &pool).await;
|
||||
let guild_data = GuildData::from_guild(msg.guild(&ctx).await.unwrap(), &pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let desc = user_data
|
||||
.response(&pool, "info")
|
||||
.await
|
||||
let desc = lm
|
||||
.get(&language, "info")
|
||||
.replacen("{user}", &ctx.cache.current_user().await.name, 1)
|
||||
.replace("{default_prefix}", &*DEFAULT_PREFIX)
|
||||
.replace("{prefix}", &guild_data.prefix);
|
||||
@ -104,16 +107,17 @@ async fn info(ctx: &Context, msg: &Message, _args: String) {
|
||||
|
||||
#[command]
|
||||
async fn donate(ctx: &Context, msg: &Message, _args: String) {
|
||||
let pool = ctx
|
||||
.data
|
||||
.read()
|
||||
.await
|
||||
let data = ctx.data.read().await;
|
||||
|
||||
let pool = data
|
||||
.get::<SQLPool>()
|
||||
.cloned()
|
||||
.expect("Could not get SQLPool from data");
|
||||
|
||||
let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
|
||||
let desc = user_data.response(&pool, "donate").await;
|
||||
let lm = data.get::<LanguageManager>().unwrap();
|
||||
|
||||
let language = UserData::language_of(&msg.author, &ctx, &pool).await;
|
||||
let desc = lm.get(&language, "donate");
|
||||
|
||||
let _ = msg
|
||||
.channel_id
|
||||
|
48
src/language_manager.rs
Normal file
48
src/language_manager.rs
Normal file
@ -0,0 +1,48 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::Deserialize;
|
||||
use serde_json::from_reader;
|
||||
use serenity::prelude::TypeMapKey;
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::BufReader;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct LanguageManager {
|
||||
languages: HashMap<String, String>,
|
||||
strings: HashMap<String, HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl LanguageManager {
|
||||
pub(crate) fn from_compiled<P>(path: P) -> Result<Self, Box<dyn Error + Send + Sync>>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
let file = File::open(path)?;
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
let new: Self = from_reader(reader)?;
|
||||
|
||||
Ok(new)
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, language: &str, name: &'static str) -> &str {
|
||||
self.strings
|
||||
.get(language)
|
||||
.map(|sm| sm.get(name))
|
||||
.expect(&format!(r#"Language does not exist: "{}""#, language))
|
||||
.expect(&format!(r#"String does not exist: "{}""#, name))
|
||||
}
|
||||
|
||||
fn all_languages(&self) -> Vec<(&str, &str)> {
|
||||
self.languages
|
||||
.iter()
|
||||
.map(|(k, v)| (k.as_str(), v.as_str()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeMapKey for LanguageManager {
|
||||
type Value = Self;
|
||||
}
|
@ -4,6 +4,7 @@ extern crate lazy_static;
|
||||
mod commands;
|
||||
mod consts;
|
||||
mod framework;
|
||||
mod language_manager;
|
||||
mod models;
|
||||
mod time_parser;
|
||||
|
||||
@ -33,6 +34,7 @@ use crate::{
|
||||
commands::{info_cmds, moderation_cmds, reminder_cmds, todo_cmds},
|
||||
consts::{CNC_GUILD, DEFAULT_PREFIX, SUBSCRIPTION_ROLES, THEME_COLOR},
|
||||
framework::RegexFramework,
|
||||
language_manager::LanguageManager,
|
||||
};
|
||||
|
||||
use serenity::futures::TryFutureExt;
|
||||
@ -229,11 +231,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let language_manager = LanguageManager::from_compiled("out.json")?;
|
||||
|
||||
let mut data = client.data.write().await;
|
||||
|
||||
data.insert::<SQLPool>(pool);
|
||||
data.insert::<ReqwestClient>(Arc::new(reqwest::Client::new()));
|
||||
data.insert::<FrameworkCtx>(framework_arc);
|
||||
data.insert::<LanguageManager>(language_manager)
|
||||
}
|
||||
|
||||
if let Ok((Some(lower), Some(upper))) = env::var("SHARD_RANGE").map(|sr| {
|
||||
|
@ -191,6 +191,25 @@ pub struct UserData {
|
||||
}
|
||||
|
||||
impl UserData {
|
||||
pub async fn language_of(user: &User, ctx: impl CacheHttp, pool: &MySqlPool) -> String {
|
||||
let user_id = user.id.as_u64().to_owned();
|
||||
|
||||
match sqlx::query!(
|
||||
"
|
||||
SELECT IF(language IS NULL, ?, language) AS language FROM users WHERE user = ?
|
||||
",
|
||||
*LOCAL_LANGUAGE,
|
||||
user_id
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
{
|
||||
Ok(r) => r.language.unwrap(),
|
||||
|
||||
Err(_) => LOCAL_LANGUAGE.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn from_user(
|
||||
user: &User,
|
||||
ctx: impl CacheHttp,
|
||||
@ -266,25 +285,8 @@ UPDATE users SET name = ?, language = ?, timezone = ? WHERE id = ?
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub async fn response(&self, pool: &MySqlPool, name: &str) -> String {
|
||||
struct StringRow {
|
||||
value: String,
|
||||
}
|
||||
|
||||
sqlx::query_as!(
|
||||
StringRow,
|
||||
"
|
||||
SELECT value FROM strings WHERE (language = ? OR language = ?) AND name = ? ORDER BY language = ?
|
||||
",
|
||||
self.language,
|
||||
&*LOCAL_LANGUAGE,
|
||||
name,
|
||||
&*LOCAL_LANGUAGE
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.unwrap()
|
||||
.value
|
||||
pub async fn response(&self, _pool: &MySqlPool, _name: &str) -> String {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
pub fn timezone(&self) -> Tz {
|
||||
|
Loading…
Reference in New Issue
Block a user