3 Commits

Author SHA1 Message Date
Lukas Wölfer
eb88c041f6 Depedency on release CI
All checks were successful
Rust / build_and_test (push) Successful in 1m14s
Release / build_release (push) Successful in 2m26s
2026-01-17 23:40:49 +01:00
Lukas Wölfer
596f1b3a6b Version bump
Some checks failed
Release / build_release (push) Has been cancelled
Rust / build_and_test (push) Has been cancelled
2026-01-17 23:39:18 +01:00
Lukas Wölfer
6f332b314d Added subcommands 2026-01-17 23:34:24 +01:00
5 changed files with 57 additions and 27 deletions

View File

@@ -11,6 +11,7 @@ env:
jobs:
build_release:
runs-on: ubuntu-latest
needs: build_and_test
env:
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
GITEA_SERVER: ${{ secrets.GITEA_SERVER }}

2
Cargo.lock generated
View File

@@ -3201,7 +3201,7 @@ dependencies = [
[[package]]
name = "teachertracker-rs"
version = "0.1.5"
version = "0.1.6"
dependencies = [
"async-trait",
"chrono",

View File

@@ -1,6 +1,6 @@
[package]
name = "teachertracker-rs"
version = "0.1.5"
version = "0.1.6"
edition = "2024"
authors = ["Lukas Wölfer <coding@thasky.one>"]
description = "A MediaWiki bot that updates score information of teachers"
@@ -14,8 +14,7 @@ categories = ["web-programming", "api-bindings", "automation"]
chrono = "0.4.41"
clap = { version = "4.5.54", features = ["derive"] }
futures = "0.3.31"
# mwbot = { git = "https://gitlab.wikimedia.org/repos/mwbot-rs/mwbot.git", rev = "05cbb12188f18e2da710de158d89a9a4f1b42689", default-features = false, features = ["generators", "mwbot_derive"] }
mwbot = { version = "0.7.0", default-features = false, features = ["generators", "mwbot_derive"] }
mwbot = { version = "0.7.1", default-features = false, features = ["generators", "mwbot_derive"] }
rand = "0.9.2"
reqwest = "0.12.22"
scraper = "0.24.0"

View File

@@ -26,8 +26,8 @@ use std::path::Path;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::{Layer, layer::SubscriberExt, util::SubscriberInitExt};
use crate::fetching::{DynWsdcFetcher, ScoringDanceFetcher, WorldsdcFetcher};
use crate::watchdog::{update_wanted_ids, watch_wanted};
use crate::fetching::{DynWsdcFetcher, WorldsdcFetcher, ScoringDanceFetcher};
mod dance_info;
mod fetching;
@@ -128,8 +128,19 @@ enum WsdcPointsBackend {
#[derive(Subcommand)]
enum Commands {
/// Continuously watch for missing or outdated teachers and update them
Watch,
/// Build pages for all missing teachers
Missing,
FixMissing,
/// List all missing teachers
ListMissing,
/// Update info for all teachers
FetchInfo(FetchInfoArgs),
}
#[derive(Parser)]
struct FetchInfoArgs {
id: u32,
}
fn main() -> Result<(), AppError> {
@@ -149,9 +160,10 @@ fn main() -> Result<(), AppError> {
WsdcPointsBackend::ScoringDance => std::sync::Arc::new(ScoringDanceFetcher {}),
WsdcPointsBackend::WorldSDC => std::sync::Arc::new(WorldsdcFetcher {}),
};
let command = cli.command.as_ref().map_or(&Commands::Watch, |cmd| cmd);
match &cli.command {
Some(Commands::Missing) => {
match command {
Commands::ListMissing => {
rt.block_on(async {
let wanted = wikiinfo::wanted_ids(bot.clone(), fetcher.clone()).await;
tracing::info!(
@@ -165,18 +177,48 @@ fn main() -> Result<(), AppError> {
);
update_wanted_ids(&wanted, &[], fetcher.clone()).await;
});
return Ok(());
}
None => {
Commands::FetchInfo(args) => {
rt.block_on(async {
let info = fetcher.fetch(args.id).await;
#[allow(
clippy::print_stdout,
clippy::print_stderr,
reason = "We want to print here"
)]
match info {
Ok(info) => println!("Fetched info: {info:?}"),
Err(err) => eprintln!("Error fetching info: {err}"),
}
});
}
Commands::FixMissing => {
rt.block_on(async {
let wanted = wikiinfo::wanted_ids(bot.clone(), fetcher.clone()).await;
tracing::info!(
"Missing ids: {}",
wanted
.iter()
.map(|(v, _)| v)
.map(u32::to_string)
.collect::<Vec<_>>()
.join("\n")
);
update_wanted_ids(&wanted, &[], fetcher.clone()).await;
});
}
Commands::Watch => {
#[allow(
unreachable_code,
reason = "This is a false positive I think, I just want to loop infinitely on two futures"
)]
rt.block_on(async {
futures::join!(watch_wanted(bot.clone(), fetcher.clone()), updater::update_wsdc(bot, fetcher.clone()))
futures::join!(
watch_wanted(bot.clone(), fetcher.clone()),
updater::update_wsdc(bot, fetcher.clone())
)
});
}
}
unreachable!();
Ok(())
}

View File

@@ -4,8 +4,8 @@ use mwbot::{
};
use crate::fetching::DynWsdcFetcher;
pub async fn wanted_ids(_bot: Bot, _fetcher: DynWsdcFetcher) -> Vec<(u32, Page)> {
let mut gene = QueryPage::new("Wantedpages").generate(&_bot);
pub async fn wanted_ids(bot: Bot, _fetcher: DynWsdcFetcher) -> Vec<(u32, Page)> {
let mut gene = QueryPage::new("Wantedpages").generate(&bot);
let mut result = vec![];
while let Some(x) = gene.recv().await {
let p = match x {
@@ -51,18 +51,6 @@ fn parse_wsdc_page_name(name: &str) -> Result<u32, TitleParseError> {
}
}
// fn get_wsdc_page_date(bot: &Bot, page: &Page) -> Option<SystemTime> {
// todo!();
// let prefix = "Updated-On: ";
// page.filter_comments()
// .iter()
// .filter_map(|x| {
// let c = x.text_contents();
// if c.starts_with(prefix) { Some(c) } else { None }
// })
// .map(|x| x.trim_start_matches(prefix).parse::<u64>());
// }
#[allow(dead_code)]
pub async fn index_wsdc_ids(bot: &Bot, _fetcher: DynWsdcFetcher) -> Vec<(u32, Page)> {
let mut gene = Search::new("WSDC/").generate(bot);