mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-19 16:58:55 +00:00
Handle failures and record chewing
This commit is contained in:
parent
3a89c009da
commit
e2766cd782
3 changed files with 35 additions and 22 deletions
|
@ -46,29 +46,25 @@ impl youmubot_prelude::Announcer for Announcer {
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
// For each user...
|
// For each user...
|
||||||
let data = OsuSavedUsers::open(&*d.read().await).borrow()?.clone();
|
let data = OsuSavedUsers::open(&*d.read().await).borrow()?.clone();
|
||||||
|
let now = chrono::Utc::now();
|
||||||
let data = data
|
let data = data
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(user_id, osu_user)| {
|
.map(|(user_id, osu_user)| {
|
||||||
let d = d.clone();
|
|
||||||
let channels = &channels;
|
let channels = &channels;
|
||||||
let c = c.clone();
|
let ctx = Context {
|
||||||
|
c: c.clone(),
|
||||||
|
data: d.clone(),
|
||||||
|
};
|
||||||
let s = &self;
|
let s = &self;
|
||||||
async move {
|
async move {
|
||||||
let channels = channels.channels_of(c.clone(), user_id).await;
|
let channels = channels.channels_of(ctx.c.clone(), user_id).await;
|
||||||
if channels.is_empty() {
|
if channels.is_empty() {
|
||||||
return (user_id, osu_user); // We don't wanna update an user without any active server
|
return (user_id, osu_user); // We don't wanna update an user without any active server
|
||||||
}
|
}
|
||||||
let pp = match (&[Mode::Std, Mode::Taiko, Mode::Catch, Mode::Mania])
|
let pp = match (&[Mode::Std, Mode::Taiko, Mode::Catch, Mode::Mania])
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|m| {
|
.map(|m| {
|
||||||
s.handle_user_mode(
|
s.handle_user_mode(&ctx, now, &osu_user, user_id, channels.clone(), *m)
|
||||||
c.clone(),
|
|
||||||
&osu_user,
|
|
||||||
user_id,
|
|
||||||
channels.clone(),
|
|
||||||
*m,
|
|
||||||
d.clone(),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.collect::<stream::FuturesOrdered<_>>()
|
.collect::<stream::FuturesOrdered<_>>()
|
||||||
.try_collect::<Vec<_>>()
|
.try_collect::<Vec<_>>()
|
||||||
|
@ -77,15 +73,21 @@ impl youmubot_prelude::Announcer for Announcer {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("osu: Cannot update {}: {}", osu_user.id, e);
|
eprintln!("osu: Cannot update {}: {}", osu_user.id, e);
|
||||||
return (user_id, osu_user);
|
return (
|
||||||
|
user_id,
|
||||||
|
OsuUser {
|
||||||
|
failures: Some(osu_user.failures.unwrap_or(0) + 1),
|
||||||
|
..osu_user
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let last_update = chrono::Utc::now();
|
|
||||||
(
|
(
|
||||||
user_id,
|
user_id,
|
||||||
OsuUser {
|
OsuUser {
|
||||||
pp,
|
pp,
|
||||||
last_update,
|
last_update: now,
|
||||||
|
failures: None,
|
||||||
..osu_user
|
..osu_user
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -100,9 +102,17 @@ impl youmubot_prelude::Announcer for Announcer {
|
||||||
let mut db = db.borrow_mut()?;
|
let mut db = db.borrow_mut()?;
|
||||||
data.into_iter()
|
data.into_iter()
|
||||||
.for_each(|(k, v)| match db.get(&k).map(|v| v.last_update.clone()) {
|
.for_each(|(k, v)| match db.get(&k).map(|v| v.last_update.clone()) {
|
||||||
Some(d) if d > v.last_update => (),
|
Some(d) if d > now => (),
|
||||||
_ => {
|
_ => {
|
||||||
db.insert(k, v);
|
if v.failures.unwrap_or(0) > 5 {
|
||||||
|
eprintln!(
|
||||||
|
"osu: Removing user {} [{}] due to 5 consecutive failures",
|
||||||
|
k, v.id
|
||||||
|
);
|
||||||
|
db.remove(&k);
|
||||||
|
} else {
|
||||||
|
db.insert(k, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -113,14 +123,14 @@ impl Announcer {
|
||||||
/// Handles an user/mode scan, announces all possible new scores, return the new pp value.
|
/// Handles an user/mode scan, announces all possible new scores, return the new pp value.
|
||||||
async fn handle_user_mode(
|
async fn handle_user_mode(
|
||||||
&self,
|
&self,
|
||||||
c: Arc<CacheAndHttp>,
|
ctx: &Context,
|
||||||
|
now: chrono::DateTime<chrono::Utc>,
|
||||||
osu_user: &OsuUser,
|
osu_user: &OsuUser,
|
||||||
user_id: UserId,
|
user_id: UserId,
|
||||||
channels: Vec<ChannelId>,
|
channels: Vec<ChannelId>,
|
||||||
mode: Mode,
|
mode: Mode,
|
||||||
d: AppData,
|
|
||||||
) -> Result<Option<f64>, Error> {
|
) -> Result<Option<f64>, Error> {
|
||||||
let days_since_last_update = (chrono::Utc::now() - osu_user.last_update).num_days() + 1;
|
let days_since_last_update = (now - osu_user.last_update).num_days() + 1;
|
||||||
let last_update = osu_user.last_update.clone();
|
let last_update = osu_user.last_update.clone();
|
||||||
let (scores, user) = {
|
let (scores, user) = {
|
||||||
let scores = self.scan_user(osu_user, mode).await?;
|
let scores = self.scan_user(osu_user, mode).await?;
|
||||||
|
@ -136,19 +146,20 @@ impl Announcer {
|
||||||
};
|
};
|
||||||
let client = self.client.clone();
|
let client = self.client.clone();
|
||||||
let pp = user.pp;
|
let pp = user.pp;
|
||||||
|
let ctx = ctx.clone();
|
||||||
spawn_future(async move {
|
spawn_future(async move {
|
||||||
let event_scores = user
|
let event_scores = user
|
||||||
.events
|
.events
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|u| u.to_event_rank())
|
.filter_map(|u| u.to_event_rank())
|
||||||
.filter(|u| u.mode == mode && u.date > last_update)
|
.filter(|u| u.mode == mode && u.date > last_update && u.date <= now)
|
||||||
.map(|ev| CollectedScore::from_event(&*client, &user, ev, user_id, &channels[..]))
|
.map(|ev| CollectedScore::from_event(&*client, &user, ev, user_id, &channels[..]))
|
||||||
.collect::<stream::FuturesUnordered<_>>()
|
.collect::<stream::FuturesUnordered<_>>()
|
||||||
.filter_map(|u| future::ready(u.pls_ok()))
|
.filter_map(|u| future::ready(u.pls_ok()))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.await;
|
.await;
|
||||||
let top_scores = scores.into_iter().filter_map(|(rank, score)| {
|
let top_scores = scores.into_iter().filter_map(|(rank, score)| {
|
||||||
if score.date > last_update {
|
if score.date > last_update && score.date <= now {
|
||||||
Some(CollectedScore::from_top_score(
|
Some(CollectedScore::from_top_score(
|
||||||
&user,
|
&user,
|
||||||
score,
|
score,
|
||||||
|
@ -161,7 +172,6 @@ impl Announcer {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let ctx = Context { data: d, c };
|
|
||||||
event_scores
|
event_scores
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(top_scores)
|
.chain(top_scores)
|
||||||
|
|
|
@ -23,4 +23,6 @@ pub struct OsuUser {
|
||||||
pub last_update: DateTime<Utc>,
|
pub last_update: DateTime<Utc>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub pp: Vec<Option<f64>>,
|
pub pp: Vec<Option<f64>>,
|
||||||
|
/// More than 5 failures => gone
|
||||||
|
pub failures: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,6 +249,7 @@ fn add_user(target: serenity::model::id::UserId, user_id: u64, data: &TypeMap) -
|
||||||
target,
|
target,
|
||||||
OsuUser {
|
OsuUser {
|
||||||
id: user_id,
|
id: user_id,
|
||||||
|
failures: None,
|
||||||
last_update: chrono::Utc::now(),
|
last_update: chrono::Utc::now(),
|
||||||
pp: vec![],
|
pp: vec![],
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue