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
|
/venv
|
||||||
.cargo
|
.cargo
|
||||||
assets
|
assets
|
||||||
|
out.json
|
||||||
|
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1336,7 +1336,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reminder_rs"
|
name = "reminder_rs"
|
||||||
version = "1.2.3"
|
version = "1.3.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"Inflector",
|
"Inflector",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "reminder_rs"
|
name = "reminder_rs"
|
||||||
version = "1.2.3"
|
version = "1.3.0-dev"
|
||||||
authors = ["jellywx <judesouthworth@pm.me>"]
|
authors = ["jellywx <judesouthworth@pm.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ use crate::{
|
|||||||
SQLPool, THEME_COLOR,
|
SQLPool, THEME_COLOR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::language_manager::LanguageManager;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
@ -31,16 +32,18 @@ async fn ping(ctx: &Context, msg: &Message, _args: String) {
|
|||||||
#[command]
|
#[command]
|
||||||
#[can_blacklist(false)]
|
#[can_blacklist(false)]
|
||||||
async fn help(ctx: &Context, msg: &Message, _args: String) {
|
async fn help(ctx: &Context, msg: &Message, _args: String) {
|
||||||
let pool = ctx
|
let data = ctx.data.read().await;
|
||||||
.data
|
|
||||||
.read()
|
let pool = data
|
||||||
.await
|
|
||||||
.get::<SQLPool>()
|
.get::<SQLPool>()
|
||||||
.cloned()
|
.cloned()
|
||||||
.expect("Could not get SQLPool from data");
|
.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 desc = user_data.response(&pool, "help").await;
|
|
||||||
|
let language = UserData::language_of(&msg.author, &ctx, &pool).await;
|
||||||
|
|
||||||
|
let desc = lm.get(&language, "help");
|
||||||
|
|
||||||
let _ = msg
|
let _ = msg
|
||||||
.channel_id
|
.channel_id
|
||||||
@ -63,22 +66,22 @@ async fn help(ctx: &Context, msg: &Message, _args: String) {
|
|||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
async fn info(ctx: &Context, msg: &Message, _args: String) {
|
async fn info(ctx: &Context, msg: &Message, _args: String) {
|
||||||
let pool = ctx
|
let data = ctx.data.read().await;
|
||||||
.data
|
|
||||||
.read()
|
let pool = data
|
||||||
.await
|
|
||||||
.get::<SQLPool>()
|
.get::<SQLPool>()
|
||||||
.cloned()
|
.cloned()
|
||||||
.expect("Could not get SQLPool from data");
|
.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)
|
let guild_data = GuildData::from_guild(msg.guild(&ctx).await.unwrap(), &pool)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let desc = user_data
|
let desc = lm
|
||||||
.response(&pool, "info")
|
.get(&language, "info")
|
||||||
.await
|
|
||||||
.replacen("{user}", &ctx.cache.current_user().await.name, 1)
|
.replacen("{user}", &ctx.cache.current_user().await.name, 1)
|
||||||
.replace("{default_prefix}", &*DEFAULT_PREFIX)
|
.replace("{default_prefix}", &*DEFAULT_PREFIX)
|
||||||
.replace("{prefix}", &guild_data.prefix);
|
.replace("{prefix}", &guild_data.prefix);
|
||||||
@ -104,16 +107,17 @@ async fn info(ctx: &Context, msg: &Message, _args: String) {
|
|||||||
|
|
||||||
#[command]
|
#[command]
|
||||||
async fn donate(ctx: &Context, msg: &Message, _args: String) {
|
async fn donate(ctx: &Context, msg: &Message, _args: String) {
|
||||||
let pool = ctx
|
let data = ctx.data.read().await;
|
||||||
.data
|
|
||||||
.read()
|
let pool = data
|
||||||
.await
|
|
||||||
.get::<SQLPool>()
|
.get::<SQLPool>()
|
||||||
.cloned()
|
.cloned()
|
||||||
.expect("Could not get SQLPool from data");
|
.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 desc = user_data.response(&pool, "donate").await;
|
|
||||||
|
let language = UserData::language_of(&msg.author, &ctx, &pool).await;
|
||||||
|
let desc = lm.get(&language, "donate");
|
||||||
|
|
||||||
let _ = msg
|
let _ = msg
|
||||||
.channel_id
|
.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 commands;
|
||||||
mod consts;
|
mod consts;
|
||||||
mod framework;
|
mod framework;
|
||||||
|
mod language_manager;
|
||||||
mod models;
|
mod models;
|
||||||
mod time_parser;
|
mod time_parser;
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ use crate::{
|
|||||||
commands::{info_cmds, moderation_cmds, reminder_cmds, todo_cmds},
|
commands::{info_cmds, moderation_cmds, reminder_cmds, todo_cmds},
|
||||||
consts::{CNC_GUILD, DEFAULT_PREFIX, SUBSCRIPTION_ROLES, THEME_COLOR},
|
consts::{CNC_GUILD, DEFAULT_PREFIX, SUBSCRIPTION_ROLES, THEME_COLOR},
|
||||||
framework::RegexFramework,
|
framework::RegexFramework,
|
||||||
|
language_manager::LanguageManager,
|
||||||
};
|
};
|
||||||
|
|
||||||
use serenity::futures::TryFutureExt;
|
use serenity::futures::TryFutureExt;
|
||||||
@ -229,11 +231,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
|||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let language_manager = LanguageManager::from_compiled("out.json")?;
|
||||||
|
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
data.insert::<SQLPool>(pool);
|
data.insert::<SQLPool>(pool);
|
||||||
data.insert::<ReqwestClient>(Arc::new(reqwest::Client::new()));
|
data.insert::<ReqwestClient>(Arc::new(reqwest::Client::new()));
|
||||||
data.insert::<FrameworkCtx>(framework_arc);
|
data.insert::<FrameworkCtx>(framework_arc);
|
||||||
|
data.insert::<LanguageManager>(language_manager)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok((Some(lower), Some(upper))) = env::var("SHARD_RANGE").map(|sr| {
|
if let Ok((Some(lower), Some(upper))) = env::var("SHARD_RANGE").map(|sr| {
|
||||||
|
@ -191,6 +191,25 @@ pub struct UserData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl 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(
|
pub async fn from_user(
|
||||||
user: &User,
|
user: &User,
|
||||||
ctx: impl CacheHttp,
|
ctx: impl CacheHttp,
|
||||||
@ -266,25 +285,8 @@ UPDATE users SET name = ?, language = ?, timezone = ? WHERE id = ?
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn response(&self, pool: &MySqlPool, name: &str) -> String {
|
pub async fn response(&self, _pool: &MySqlPool, _name: &str) -> String {
|
||||||
struct StringRow {
|
unimplemented!()
|
||||||
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 fn timezone(&self) -> Tz {
|
pub fn timezone(&self) -> Tz {
|
||||||
|
Loading…
Reference in New Issue
Block a user