Periodically refresh user list every hour

This commit is contained in:
Elnu 2025-03-28 13:37:41 -07:00
parent 5e848ffe76
commit c202e4e250
7 changed files with 35 additions and 25 deletions

1
Cargo.lock generated
View file

@ -3358,6 +3358,7 @@ dependencies = [
"dotenv",
"gettext",
"gh-emoji",
"lazy_static",
"poise",
"r2d2",
"r2d2_sqlite",

View file

@ -14,6 +14,7 @@ derive_more = { version = "2.0", features = ["full"] }
dotenv = "0.15"
gettext = "0.4"
gh-emoji = "1.0"
lazy_static = "1.5.0"
poise = "0.5" # TODO: update to 0.6
r2d2 = "0.8"
r2d2_sqlite = "0.27"

View file

@ -4,11 +4,12 @@ extern crate rocket;
use clap::{Parser, Subcommand};
use poise::serenity_prelude::Http;
use rocket::{
fs::{relative, FileServer},
Ignite, Rocket,
fs::{relative, FileServer}, futures::task, Ignite, Rocket
};
use rocket_dyn_templates::{tera, Template};
use std::{collections::HashMap, env};
use tokio::time;
use std::{collections::HashMap, env, time::Duration};
use lazy_static::lazy_static;
mod models;
use models::{Database, Settings};
@ -61,6 +62,15 @@ async fn main() {
}
},
None => {
tokio::task::spawn(async {
let mut interval = time::interval(Duration::from_millis(60 * 60 * 1000)); // every hour
loop {
if let Err(err) = DATABASE.refresh_users(&HTTP).await {
error!("{:?}", err);
}
interval.tick().await;
}
});
rocket().await.expect("Failed to launch rocket");
}
}
@ -75,11 +85,12 @@ fn http() -> Http {
Http::new(&token)
}
async fn rocket() -> Result<Rocket<Ignite>, rocket::Error> {
let http = http();
let database = load_database();
database.refresh_users(&http).await.unwrap();
lazy_static! {
static ref DATABASE: Database = load_database();
static ref HTTP: Http = http();
}
async fn rocket() -> Result<Rocket<Ignite>, rocket::Error> {
let config = rocket::Config::figment().merge(("port", 1313)).merge((
"secret_key",
env::var("SECRET")
@ -87,9 +98,8 @@ async fn rocket() -> Result<Rocket<Ignite>, rocket::Error> {
));
rocket::custom(config)
.manage(Settings::new(&http).await.unwrap())
.manage(http)
.manage(database)
.manage(Settings::new(&HTTP).await.unwrap())
// .manage(http)
.mount(
"/",
routes![

View file

@ -6,8 +6,8 @@ use rocket_dyn_templates::{context, Template};
use crate::{
cookies::LANG_COOKIE,
i18n::DEFAULT as DEFAULT_LANG,
models::{Challenge, Database, SessionUser, Settings},
utils::AcceptLanguage,
models::{Challenge, SessionUser, Settings},
utils::AcceptLanguage, DATABASE,
};
#[get("/<challenge>")]
@ -15,10 +15,9 @@ pub async fn get_challenge(
challenge: u32,
cookies: &CookieJar<'_>,
settings: &State<Settings>,
database: &State<Database>,
accept_language: AcceptLanguage,
) -> Template {
let (submissions, users) = database.get_challenge_user_data(challenge).unwrap();
let (submissions, users) = DATABASE.get_challenge_user_data(challenge).unwrap();
Template::render(
"challenge",
context! {

View file

@ -2,6 +2,7 @@ use poise::serenity_prelude::Http;
use rocket::response::stream::{Event, EventStream};
use rocket::{http::CookieJar, State};
use crate::HTTP;
use crate::{cookies::user::USER_ID_COOKIE, models::Settings};
// TODO: Incrementally send guilds
@ -9,7 +10,6 @@ use crate::{cookies::user::USER_ID_COOKIE, models::Settings};
pub async fn get_guilds<'a>(
cookies: &'a CookieJar<'_>,
settings: &'a State<Settings>,
http: &'a State<Http>,
) -> EventStream![Event + 'a] {
// EventStream![] is shorthand for EventStream[Event],
// but we need to pass in a lifetime parameter.
@ -28,7 +28,7 @@ pub async fn get_guilds<'a>(
if guild.hidden {
continue;
}
yield Event::data(format!("{},{}", guild.id, http.get_member(guild.id, user_id).await.is_ok()));
yield Event::data(format!("{},{}", guild.id, HTTP.get_member(guild.id, user_id).await.is_ok()));
}
}
}

View file

@ -9,8 +9,8 @@ use rocket_dyn_templates::{context, Template};
use crate::{
cookies::LANG_COOKIE,
i18n::DEFAULT as DEFAULT_LANG,
models::{Database, DatabaseError, SessionUser, Settings},
utils::AcceptLanguage,
models::{DatabaseError, SessionUser, Settings},
utils::AcceptLanguage, DATABASE,
};
#[get("/users/<user>")]
@ -18,10 +18,9 @@ pub async fn get_user(
user: String,
cookies: &CookieJar<'_>,
settings: &State<Settings>,
database: &State<Database>,
accept_language: AcceptLanguage,
) -> Result<Template, Status> {
let profile_user = match database.get_user_by_name(&user) {
let profile_user = match DATABASE.get_user_by_name(&user) {
Ok(profile_user) => profile_user,
Err(DatabaseError::Rusqlite(rusqlite::Error::QueryReturnedNoRows)) => {
return Err(Status::NotFound)
@ -35,7 +34,7 @@ pub async fn get_user(
"user",
context! {
profile_user,
submissions: database.get_submissions_by_user_name(&user).unwrap(),
submissions: DATABASE.get_submissions_by_user_name(&user).unwrap(),
settings: settings.deref(),
lang: cookies
.get(LANG_COOKIE)

View file

@ -3,18 +3,18 @@ use std::ops::Deref;
use poise::serenity_prelude::Http;
use rocket::{http::CookieJar, State};
use crate::models::SessionUser;
use crate::{models::SessionUser, HTTP};
#[get("/testing")]
pub async fn testing(cookies: &CookieJar<'_>, http: &State<Http>) -> String {
pub async fn testing(cookies: &CookieJar<'_>) -> String {
// Get logged in user's join date in 字ちゃん server
format!(
"{:?}",
http.get_guild(814700630958276649)
HTTP.get_guild(814700630958276649)
.await
.expect("Failed to get testing guild")
.member(
http.deref(),
HTTP.deref(),
SessionUser::get(cookies)
.await
.expect("Failed to get logged in user data")