mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 16:58:55 +00:00
Update to codeforces package with sound ratelimiting
This commit is contained in:
parent
68142c6236
commit
e36c385f15
5 changed files with 26 additions and 38 deletions
5
Cargo.lock
generated
5
Cargo.lock
generated
|
@ -154,10 +154,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codeforces"
|
name = "codeforces"
|
||||||
version = "0.3.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7df54b4689d51d58162c8b76a642ba44d6128b68f29c3fbc23815e6ea4bfef15"
|
checksum = "f0167d57615475a20056a4ce224d143cf603f7159e3102ac5e6a3a1d9ea1c71a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"flume",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -74,13 +74,13 @@ async fn update_user(
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
cfu: &mut CfUser,
|
cfu: &mut CfUser,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let info = User::info(&*client.borrow().await?, &[cfu.handle.as_str()])
|
let info = User::info(&*client, &[cfu.handle.as_str()])
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.next()
|
.next()
|
||||||
.ok_or(Error::msg("Not found"))?;
|
.ok_or(Error::msg("Not found"))?;
|
||||||
|
|
||||||
let rating_changes = info.rating_changes(&*client.borrow().await?).await?;
|
let rating_changes = info.rating_changes(&*client).await?;
|
||||||
|
|
||||||
let channels_list = channels.channels_of(&http, user_id).await;
|
let channels_list = channels.channels_of(&http, user_id).await;
|
||||||
cfu.last_update = Utc::now();
|
cfu.last_update = Utc::now();
|
||||||
|
@ -119,10 +119,8 @@ async fn update_user(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let (contest, _, _) =
|
let (contest, _, _) =
|
||||||
codeforces::Contest::standings(&*client.borrow().await?, rc.contest_id, |f| {
|
codeforces::Contest::standings(&*client, rc.contest_id, |f| f.limit(1, 1))
|
||||||
f.limit(1, 1)
|
.await?;
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
channels
|
channels
|
||||||
.iter()
|
.iter()
|
||||||
.map(|channel| {
|
.map(|channel| {
|
||||||
|
|
|
@ -42,7 +42,7 @@ impl TypeMapKey for ContestCache {
|
||||||
impl ContestCache {
|
impl ContestCache {
|
||||||
/// Creates a new, empty cache.
|
/// Creates a new, empty cache.
|
||||||
pub(crate) async fn new(http: Client) -> Result<Self> {
|
pub(crate) async fn new(http: Client) -> Result<Self> {
|
||||||
let contests_list = Contest::list(&*http.borrow().await?, true).await?;
|
let contests_list = Contest::list(&*http, true).await?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
contests: HashMap::new(),
|
contests: HashMap::new(),
|
||||||
all_list: RwLock::new((contests_list, Instant::now())),
|
all_list: RwLock::new((contests_list, Instant::now())),
|
||||||
|
@ -64,17 +64,14 @@ impl ContestCache {
|
||||||
&self,
|
&self,
|
||||||
contest_id: u64,
|
contest_id: u64,
|
||||||
) -> Result<(Contest, Option<Vec<Problem>>)> {
|
) -> Result<(Contest, Option<Vec<Problem>>)> {
|
||||||
let (c, p) =
|
let (c, p) = match Contest::standings(&*self.http, contest_id, |f| f.limit(1, 1)).await {
|
||||||
match Contest::standings(&*self.http.borrow().await?, contest_id, |f| f.limit(1, 1))
|
Ok((c, p, _)) => (c, Some(p)),
|
||||||
.await
|
Err(codeforces::Error::Codeforces(s)) if s.ends_with("has not started") => {
|
||||||
{
|
let c = self.get_from_list(contest_id).await?;
|
||||||
Ok((c, p, _)) => (c, Some(p)),
|
(c, None)
|
||||||
Err(codeforces::Error::Codeforces(s)) if s.ends_with("has not started") => {
|
}
|
||||||
let c = self.get_from_list(contest_id).await?;
|
Err(v) => return Err(Error::from(v)),
|
||||||
(c, None)
|
};
|
||||||
}
|
|
||||||
Err(v) => return Err(Error::from(v)),
|
|
||||||
};
|
|
||||||
self.contests.insert(contest_id, (c, p));
|
self.contests.insert(contest_id, (c, p));
|
||||||
Ok(self.contests.get(&contest_id).unwrap().clone())
|
Ok(self.contests.get(&contest_id).unwrap().clone())
|
||||||
}
|
}
|
||||||
|
@ -83,10 +80,8 @@ impl ContestCache {
|
||||||
let last_updated = self.all_list.read().await.1.clone();
|
let last_updated = self.all_list.read().await.1.clone();
|
||||||
if Instant::now() - last_updated > std::time::Duration::from_secs(60 * 60) {
|
if Instant::now() - last_updated > std::time::Duration::from_secs(60 * 60) {
|
||||||
// We update at most once an hour.
|
// We update at most once an hour.
|
||||||
*self.all_list.write().await = (
|
*self.all_list.write().await =
|
||||||
Contest::list(&*self.http.borrow().await?, true).await?,
|
(Contest::list(&*self.http, true).await?, Instant::now());
|
||||||
Instant::now(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
self.all_list
|
self.all_list
|
||||||
.read()
|
.read()
|
||||||
|
|
|
@ -22,7 +22,7 @@ mod live;
|
||||||
struct CFClient;
|
struct CFClient;
|
||||||
|
|
||||||
impl TypeMapKey for CFClient {
|
impl TypeMapKey for CFClient {
|
||||||
type Value = Arc<ratelimit::Ratelimit<codeforces::Client>>;
|
type Value = Arc<codeforces::Client>;
|
||||||
}
|
}
|
||||||
|
|
||||||
use db::{CfSavedUsers, CfUser};
|
use db::{CfSavedUsers, CfUser};
|
||||||
|
@ -33,11 +33,7 @@ pub use hook::InfoHook;
|
||||||
pub async fn setup(path: &std::path::Path, data: &mut TypeMap, announcers: &mut AnnouncerHandler) {
|
pub async fn setup(path: &std::path::Path, data: &mut TypeMap, announcers: &mut AnnouncerHandler) {
|
||||||
CfSavedUsers::insert_into(data, path.join("cf_saved_users.yaml"))
|
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");
|
||||||
let client = Arc::new(ratelimit::Ratelimit::new(
|
let client = Arc::new(codeforces::Client::new());
|
||||||
codeforces::Client::new(),
|
|
||||||
4,
|
|
||||||
std::time::Duration::from_secs(1),
|
|
||||||
));
|
|
||||||
data.insert::<hook::ContestCache>(hook::ContestCache::new(client.clone()).await.unwrap());
|
data.insert::<hook::ContestCache>(hook::ContestCache::new(client.clone()).await.unwrap());
|
||||||
data.insert::<CFClient>(client);
|
data.insert::<CFClient>(client);
|
||||||
announcers.add("codeforces", announcer::Announcer);
|
announcers.add("codeforces", announcer::Announcer);
|
||||||
|
@ -78,7 +74,7 @@ pub async fn profile(ctx: &Context, m: &Message, mut args: Args) -> CommandResul
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let account = codeforces::User::info(&*http.borrow().await?, &[&handle[..]])
|
let account = codeforces::User::info(&*http, &[&handle[..]])
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.next();
|
.next();
|
||||||
|
@ -110,7 +106,7 @@ pub async fn save(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
|
||||||
let handle = args.single::<String>()?;
|
let handle = args.single::<String>()?;
|
||||||
let http = data.get::<CFClient>().unwrap();
|
let http = data.get::<CFClient>().unwrap();
|
||||||
|
|
||||||
let account = codeforces::User::info(&*http.borrow().await?, &[&handle[..]])
|
let account = codeforces::User::info(&*http, &[&handle[..]])
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.next();
|
.next();
|
||||||
|
@ -122,7 +118,7 @@ pub async fn save(ctx: &Context, m: &Message, mut args: Args) -> CommandResult {
|
||||||
}
|
}
|
||||||
Some(acc) => {
|
Some(acc) => {
|
||||||
// Collect rating changes data.
|
// Collect rating changes data.
|
||||||
let rating_changes = acc.rating_changes(&*http.borrow().await?).await?;
|
let rating_changes = acc.rating_changes(&*http).await?;
|
||||||
let mut db = CfSavedUsers::open(&*data);
|
let mut db = CfSavedUsers::open(&*data);
|
||||||
m.reply(
|
m.reply(
|
||||||
&ctx,
|
&ctx,
|
||||||
|
@ -272,7 +268,7 @@ pub async fn contestranks(ctx: &Context, m: &Message, mut args: Args) -> Command
|
||||||
.collect::<HashMap<_, _>>()
|
.collect::<HashMap<_, _>>()
|
||||||
.await;
|
.await;
|
||||||
let http = data.get::<CFClient>().unwrap();
|
let http = data.get::<CFClient>().unwrap();
|
||||||
let (contest, problems, ranks) = Contest::standings(&*http.borrow().await?, contest_id, |f| {
|
let (contest, problems, ranks) = Contest::standings(&*http, contest_id, |f| {
|
||||||
f.handles(members.iter().map(|(k, _)| k.clone()).collect())
|
f.handles(members.iter().map(|(k, _)| k.clone()).collect())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
|
@ -57,7 +57,7 @@ pub async fn watch_contest(
|
||||||
|
|
||||||
let http = data.get::<CFClient>().unwrap();
|
let http = data.get::<CFClient>().unwrap();
|
||||||
let (mut contest, problems, _) =
|
let (mut contest, problems, _) =
|
||||||
Contest::standings(&*http.borrow().await?, contest_id, |f| f.limit(1, 1)).await?;
|
Contest::standings(&*http, contest_id, |f| f.limit(1, 1)).await?;
|
||||||
|
|
||||||
msg.edit(&ctx, |e| {
|
msg.edit(&ctx, |e| {
|
||||||
e.content(format!(
|
e.content(format!(
|
||||||
|
@ -79,9 +79,7 @@ pub async fn watch_contest(
|
||||||
msg.pin(ctx).await.ok();
|
msg.pin(ctx).await.ok();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Ok(messages) =
|
if let Ok(messages) = scan_changes(&*http, &mut member_results, &mut contest).await {
|
||||||
scan_changes(&*http.borrow().await?, &mut member_results, &mut contest).await
|
|
||||||
{
|
|
||||||
for message in messages {
|
for message in messages {
|
||||||
channel
|
channel
|
||||||
.send_message(&ctx, |e| {
|
.send_message(&ctx, |e| {
|
||||||
|
|
Loading…
Add table
Reference in a new issue