mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-18 16:28:55 +00:00
Implement Codeforces announcer
This commit is contained in:
parent
3998617f97
commit
3a14c401cd
4 changed files with 111 additions and 5 deletions
96
youmubot-cf/src/announcer.rs
Normal file
96
youmubot-cf/src/announcer.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
use crate::db::{CfSavedUsers, CfUser};
|
||||
use announcer::MemberToChannels;
|
||||
use chrono::{DateTime, Utc};
|
||||
use codeforces::{RatingChange, User};
|
||||
use serenity::{
|
||||
framework::standard::{CommandError, CommandResult},
|
||||
http::CacheHttp,
|
||||
model::id::{ChannelId, UserId},
|
||||
CacheAndHttp,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use youmubot_prelude::*;
|
||||
|
||||
type Reqwest = <HTTPClient as TypeMapKey>::Value;
|
||||
|
||||
/// Updates the rating and rating changes of the users.
|
||||
pub fn updates(
|
||||
http: Arc<CacheAndHttp>,
|
||||
data: AppData,
|
||||
channels: MemberToChannels,
|
||||
) -> CommandResult {
|
||||
let mut users = CfSavedUsers::open(&*data.read()).borrow()?.clone();
|
||||
let reqwest = data.get_cloned::<HTTPClient>();
|
||||
|
||||
for (user_id, cfu) in users.iter_mut() {
|
||||
if let Err(e) = update_user(http.clone(), &channels, &reqwest, *user_id, cfu) {
|
||||
dbg!((*user_id, e));
|
||||
}
|
||||
}
|
||||
|
||||
*CfSavedUsers::open(&*data.read()).borrow_mut()? = users;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_user(
|
||||
http: Arc<CacheAndHttp>,
|
||||
channels: &MemberToChannels,
|
||||
reqwest: &Reqwest,
|
||||
user_id: UserId,
|
||||
cfu: &mut CfUser,
|
||||
) -> CommandResult {
|
||||
let info = User::info(reqwest, &[cfu.handle.as_str()])?
|
||||
.into_iter()
|
||||
.next()
|
||||
.ok_or(CommandError::from("Not found"))?;
|
||||
|
||||
let rating_changes = {
|
||||
let mut v = info.rating_changes(reqwest)?;
|
||||
v.reverse();
|
||||
v
|
||||
};
|
||||
|
||||
let mut channels_list: Option<Vec<ChannelId>> = None;
|
||||
let last_update = std::mem::replace(&mut cfu.last_update, Utc::now());
|
||||
// Update the rating
|
||||
cfu.rating = info.rating;
|
||||
|
||||
let mut send_message = |rc: RatingChange| -> CommandResult {
|
||||
let (contest, _, _) =
|
||||
codeforces::Contest::standings(reqwest, rc.contest_id, |f| f.limit(1, 1))?;
|
||||
let channels =
|
||||
channels_list.get_or_insert_with(|| channels.channels_of(http.clone(), user_id));
|
||||
for channel in channels {
|
||||
if let Err(e) = channel.send_message(http.http(), |e| {
|
||||
e.content(format!("Rating change for {}!", user_id.mention()))
|
||||
.embed(|c| {
|
||||
crate::embed::rating_change_embed(
|
||||
&rc,
|
||||
&info,
|
||||
&contest,
|
||||
&user_id.mention(),
|
||||
c,
|
||||
)
|
||||
})
|
||||
}) {
|
||||
dbg!(e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// Check for any good announcements to make
|
||||
for rc in rating_changes {
|
||||
let date: DateTime<Utc> = DateTime::from_utc(
|
||||
chrono::NaiveDateTime::from_timestamp(rc.rating_update_time_seconds as i64, 0),
|
||||
Utc,
|
||||
);
|
||||
if &date > &last_update {
|
||||
if let Err(v) = send_message(rc) {
|
||||
dbg!(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -64,7 +64,7 @@ pub fn rating_change_embed<'a>(
|
|||
) -> &'a mut CreateEmbed {
|
||||
let delta = (rating_change.new_rating as i64) - (rating_change.old_rating as i64);
|
||||
let color = if delta < 0 { 0xff0000 } else { 0x00ff00 };
|
||||
let message = if delta < 0 {
|
||||
let message = if delta > 0 {
|
||||
MessageBuilder::new()
|
||||
.push(tag)
|
||||
.push(" competed in ")
|
||||
|
@ -89,11 +89,19 @@ pub fn rating_change_embed<'a>(
|
|||
};
|
||||
|
||||
e.author(|a| {
|
||||
a.icon_url(&user.avatar)
|
||||
a.icon_url(format!("http:{}", &user.avatar))
|
||||
.url(user.profile_url())
|
||||
.name(&user.handle)
|
||||
})
|
||||
.color(color)
|
||||
.description(message)
|
||||
.field("Contest Link", contest.url(), true)
|
||||
.field(
|
||||
"Rating Change",
|
||||
format!(
|
||||
"from **{}** to **{}**",
|
||||
rating_change.old_rating, rating_change.new_rating
|
||||
),
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use serenity::{
|
|||
};
|
||||
use youmubot_prelude::*;
|
||||
|
||||
mod announcer;
|
||||
mod db;
|
||||
mod embed;
|
||||
mod hook;
|
||||
|
@ -20,9 +21,10 @@ use db::CfSavedUsers;
|
|||
pub use hook::codeforces_info_hook;
|
||||
|
||||
/// Sets up the CF databases.
|
||||
pub fn setup(path: &std::path::Path, data: &mut ShareMap) {
|
||||
pub fn setup(path: &std::path::Path, data: &mut ShareMap, announcers: &mut AnnouncerHandler) {
|
||||
CfSavedUsers::insert_into(data, path.join("cf_saved_users.yaml"))
|
||||
.expect("Must be able to set up DB")
|
||||
.expect("Must be able to set up DB");
|
||||
announcers.add("codeforces", announcer::updates);
|
||||
}
|
||||
|
||||
#[group]
|
||||
|
|
|
@ -87,7 +87,7 @@ fn main() {
|
|||
.expect("osu! is initialized");
|
||||
// codeforces
|
||||
#[cfg(feature = "codeforces")]
|
||||
youmubot_cf::setup(&db_path, &mut data);
|
||||
youmubot_cf::setup(&db_path, &mut data, &mut announcers);
|
||||
}
|
||||
|
||||
#[cfg(feature = "core")]
|
||||
|
|
Loading…
Add table
Reference in a new issue