Skip to content

Commit ab15521

Browse files
Copilotseqre
andcommitted
Add ranking_watcher functionality to chombot with config support
Co-authored-by: seqre <44679055+seqre@users.noreply.github.com>
1 parent 76e66dc commit ab15521

File tree

6 files changed

+80
-9
lines changed

6 files changed

+80
-9
lines changed

chombot-common/src/ranking_watcher/notifier.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use async_trait::async_trait;
2-
use crate::data_watcher::DataUpdateNotifier;
3-
use crate::discord_utils::send_with_overflow;
42
use log::error;
53
use poise::serenity_prelude::{ChannelId, Context};
64

75
use super::usma::{Ranking, RankingEntry};
6+
use crate::data_watcher::DataUpdateNotifier;
7+
use crate::discord_utils::send_with_overflow;
88
use crate::ranking_watcher::usma::PositionChangeInfo;
99

1010
pub struct ChannelMessageNotifier {

chombot-common/src/ranking_watcher/usma.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use std::convert::TryFrom;
22

33
use anyhow::{anyhow, Context, Result};
4-
use crate::data_watcher::WatchableData;
5-
use crate::scraping_utils::{create_chombot_http_client, first_nonempty_text};
6-
use crate::{select_all, select_one, unpack_children};
74
use log::info;
85
use scraper::node::{Element, Node};
96
use scraper::{CaseSensitivity, ElementRef, Html, Selector};
107

8+
use crate::data_watcher::WatchableData;
9+
use crate::scraping_utils::{create_chombot_http_client, first_nonempty_text};
10+
use crate::{select_all, select_one, unpack_children};
11+
1112
const RANKING_URL: &str = "https://ranking.cvgo.re/";
1213

1314
#[derive(Clone, Debug, Eq, PartialEq)]

chombot-kcc/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ extern crate core;
1010
use anyhow::Error;
1111
use chombot_common::chombot::ChombotBase;
1212
use chombot_common::data_watcher::DataWatcher;
13+
use chombot_common::ranking_watcher::notifier::ChannelMessageNotifier;
14+
use chombot_common::ranking_watcher::usma::get_ranking;
1315
use chombot_common::slash_commands::hand::hand;
1416
use chombot_common::slash_commands::score::score;
1517
use chombot_common::{start_tournaments_watcher, ChombotPoiseUserData};
@@ -23,8 +25,6 @@ use poise::{BoxFuture, Command, Context, Framework, FrameworkContext, FrameworkO
2325
use crate::args::Arguments;
2426
use crate::chombot::Chombot;
2527
use crate::kcc3::Kcc3ClientResult;
26-
use chombot_common::ranking_watcher::notifier::ChannelMessageNotifier;
27-
use chombot_common::ranking_watcher::usma::get_ranking;
2828
use crate::slash_commands::chombo::chombo;
2929
use crate::slash_commands::pasta::pasta;
3030

chombot/src/args.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,8 @@ pub struct Arguments {
77
/// Discord API token
88
#[arg(long, env)]
99
pub discord_token: String,
10+
11+
/// Enable ranking watcher
12+
#[arg(long, env, default_value_t = false)]
13+
pub feature_ranking_watcher: bool,
1014
}

chombot/src/config.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ use std::collections::HashMap;
44
use std::fs;
55
use std::ops::{Deref, DerefMut};
66
use std::path::PathBuf;
7+
use std::sync::Arc;
78

89
use async_trait::async_trait;
910
use chombot_common::tournaments_watcher::notifier::TournamentWatcherChannelListProvider;
1011
use log::info;
1112
use poise::serenity_prelude::{ChannelId, GuildId};
1213
use serde::{Deserialize, Serialize};
14+
use tokio::sync::RwLock;
1315

1416
#[derive(Clone, Default, Debug, Eq, PartialEq, Serialize, Deserialize)]
1517
pub struct Config {
@@ -22,6 +24,8 @@ pub struct Config {
2224
pub struct GuildConfig {
2325
/// Tournaments watcher channel ID
2426
pub tournaments_watcher_channel_id: Option<ChannelId>,
27+
/// Ranking watcher channel ID
28+
pub ranking_watcher_channel_id: Option<ChannelId>,
2529
}
2630

2731
#[async_trait]
@@ -39,6 +43,37 @@ impl TournamentWatcherChannelListProvider for ChombotConfig {
3943
}
4044
}
4145

46+
#[async_trait]
47+
pub trait RankingWatcherChannelListProvider: Send + Sync {
48+
type RankingWatcherChannelList: IntoIterator<Item = ChannelId> + Send;
49+
50+
async fn ranking_watcher_channels(&self) -> Self::RankingWatcherChannelList;
51+
}
52+
53+
#[async_trait]
54+
impl RankingWatcherChannelListProvider for ChombotConfig {
55+
type RankingWatcherChannelList = Vec<ChannelId>;
56+
57+
async fn ranking_watcher_channels(&self) -> Self::RankingWatcherChannelList {
58+
let channel_ids = self
59+
.config
60+
.guilds
61+
.iter()
62+
.filter_map(|(_, config)| config.ranking_watcher_channel_id);
63+
64+
channel_ids.collect()
65+
}
66+
}
67+
68+
#[async_trait]
69+
impl<T: RankingWatcherChannelListProvider> RankingWatcherChannelListProvider for Arc<RwLock<T>> {
70+
type RankingWatcherChannelList = T::RankingWatcherChannelList;
71+
72+
async fn ranking_watcher_channels(&self) -> Self::RankingWatcherChannelList {
73+
self.read().await.ranking_watcher_channels().await
74+
}
75+
}
76+
4277
#[derive(Debug)]
4378
pub struct ChombotConfig {
4479
path: PathBuf,
@@ -136,12 +171,14 @@ mod tests {
136171
GuildId::new(69),
137172
GuildConfig {
138173
tournaments_watcher_channel_id: Some(ChannelId::new(2137)),
174+
ranking_watcher_channel_id: None,
139175
},
140176
),
141177
(
142178
GuildId::new(420),
143179
GuildConfig {
144180
tournaments_watcher_channel_id: Some(ChannelId::new(69)),
181+
ranking_watcher_channel_id: None,
145182
},
146183
),
147184
]),
@@ -171,12 +208,14 @@ mod tests {
171208
GuildId::new(69),
172209
GuildConfig {
173210
tournaments_watcher_channel_id: Some(ChannelId::new(2137)),
211+
ranking_watcher_channel_id: None,
174212
},
175213
),
176214
(
177215
GuildId::new(420),
178216
GuildConfig {
179217
tournaments_watcher_channel_id: Some(ChannelId::new(69)),
218+
ranking_watcher_channel_id: None,
180219
},
181220
),
182221
]),

chombot/src/main.rs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@ use std::sync::Arc;
99

1010
use anyhow::Error;
1111
use chombot_common::chombot::ChombotBase;
12+
use chombot_common::data_watcher::DataWatcher;
13+
use chombot_common::ranking_watcher::notifier::ChannelMessageNotifier;
14+
use chombot_common::ranking_watcher::usma::get_ranking;
1215
use chombot_common::slash_commands::hand::hand;
1316
use chombot_common::slash_commands::score::score;
1417
use chombot_common::{start_tournaments_watcher, ChombotPoiseUserData};
1518
use clap::Parser;
1619
use log::{error, info, LevelFilter};
17-
use poise::serenity_prelude::{ClientBuilder, GatewayIntents};
20+
use poise::serenity_prelude::{ClientBuilder, Context as SerenityContext, GatewayIntents};
1821
use poise::{Command, Context, Framework, FrameworkOptions};
1922
use tokio::sync::RwLock;
2023

2124
use crate::args::Arguments;
22-
use crate::config::ChombotConfig;
25+
use crate::config::{ChombotConfig, RankingWatcherChannelListProvider};
2326
use crate::tournament_watcher::tournament_watcher;
2427

2528
mod args;
@@ -39,6 +42,27 @@ impl ChombotPoiseUserData for PoiseUserData {
3942

4043
pub type PoiseContext<'a> = Context<'a, PoiseUserData, anyhow::Error>;
4144

45+
fn start_ranking_watcher<T: RankingWatcherChannelListProvider + 'static>(
46+
channel_list_provider: T,
47+
ctx: SerenityContext,
48+
) {
49+
tokio::spawn(async move {
50+
let channels = channel_list_provider.ranking_watcher_channels().await;
51+
for channel_id in channels {
52+
let notifier = ChannelMessageNotifier::new(
53+
channel_id,
54+
String::from("https://ranking.cvgo.re/ ranking update"),
55+
);
56+
let ctx_clone = ctx.clone();
57+
tokio::spawn(async move {
58+
DataWatcher::new(notifier, get_ranking)
59+
.run(&ctx_clone)
60+
.await;
61+
});
62+
}
63+
});
64+
}
65+
4266
fn get_command_list() -> Vec<Command<PoiseUserData, Error>> {
4367
vec![hand(), score(), tournament_watcher()]
4468
}
@@ -63,6 +87,9 @@ async fn main() {
6387
})
6488
.setup(move |ctx, ready, framework| {
6589
Box::pin(async move {
90+
if args.feature_ranking_watcher {
91+
start_ranking_watcher(config_ref.clone(), ctx.clone());
92+
}
6693
start_tournaments_watcher(config_ref.clone(), ctx.clone());
6794
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
6895
info!("{} is connected!", ready.user.name);

0 commit comments

Comments
 (0)