diff --git a/Cargo.lock b/Cargo.lock index 73f1cc3cf..39fbf9c7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -971,7 +971,6 @@ checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ "autocfg", "hashbrown 0.11.2", - "serde", ] [[package]] @@ -982,6 +981,7 @@ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -1826,9 +1826,9 @@ checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" [[package]] name = "rust_team_data" version = "1.0.0" -source = "git+https://github.com/rust-lang/team#49683ec8af9ca6b546b3af516ea4654424e302eb" +source = "git+https://github.com/rust-lang/team#1ff0fa95e5ead9fbbb4be3975cac8ede35b9d3d5" dependencies = [ - "indexmap 1.8.1", + "indexmap 2.1.0", "serde", ] diff --git a/src/db/notifications.rs b/src/db/notifications.rs index 5b1857933..57c919943 100644 --- a/src/db/notifications.rs +++ b/src/db/notifications.rs @@ -4,7 +4,7 @@ use tokio_postgres::Client as DbClient; use tracing as log; pub struct Notification { - pub user_id: i64, + pub user_id: u64, pub origin_url: String, pub origin_html: String, pub short_description: Option, @@ -15,10 +15,10 @@ pub struct Notification { pub team_name: Option, } -pub async fn record_username(db: &DbClient, user_id: i64, username: String) -> anyhow::Result<()> { +pub async fn record_username(db: &DbClient, user_id: u64, username: String) -> anyhow::Result<()> { db.execute( "INSERT INTO users (user_id, username) VALUES ($1, $2) ON CONFLICT DO NOTHING", - &[&user_id, &username], + &[&(user_id as i64), &username], ) .await .context("inserting user id / username")?; @@ -31,7 +31,7 @@ pub async fn record_ping(db: &DbClient, notification: &Notification) -> anyhow:: $1, $2, $3, $4, $5, $6, (SELECT max(notifications.idx) + 1 from notifications where notifications.user_id = $1) )", - &[¬ification.user_id, ¬ification.origin_url, ¬ification.origin_html, ¬ification.time, ¬ification.short_description, ¬ification.team_name], + &[&(notification.user_id as i64), ¬ification.origin_url, ¬ification.origin_html, ¬ification.time, ¬ification.short_description, ¬ification.team_name], ).await.context("inserting notification")?; Ok(()) @@ -40,14 +40,14 @@ pub async fn record_ping(db: &DbClient, notification: &Notification) -> anyhow:: #[derive(Copy, Clone)] pub enum Identifier<'a> { Url(&'a str), - Index(std::num::NonZeroUsize), + Index(std::num::NonZeroU32), /// Glob identifier (`all` or `*`). All, } pub async fn delete_ping( db: &mut DbClient, - user_id: i64, + user_id: u64, identifier: Identifier<'_>, ) -> anyhow::Result> { match identifier { @@ -56,7 +56,7 @@ pub async fn delete_ping( .query( "DELETE FROM notifications WHERE user_id = $1 and origin_url = $2 RETURNING origin_html, time, short_description, metadata", - &[&user_id, &origin_url], + &[&(user_id as i64), &origin_url], ) .await .context("delete notification query")?; @@ -91,13 +91,13 @@ pub async fn delete_ping( from notifications where user_id = $1 order by idx asc nulls last;", - &[&user_id], + &[&(user_id as i64)], ) .await .context("failed to get ordering")?; let notification_id: i64 = notifications - .get(idx.get() - 1) + .get((idx.get() - 1) as usize) .ok_or_else(|| anyhow::anyhow!("No such notification with index {}", idx.get()))? .get(0); @@ -144,7 +144,7 @@ pub async fn delete_ping( .query( "DELETE FROM notifications WHERE user_id = $1 RETURNING origin_url, origin_html, time, short_description, metadata", - &[&user_id], + &[&(user_id as i64)], ) .await .context("delete all notifications query")?; @@ -180,10 +180,12 @@ pub struct NotificationData { pub async fn move_indices( db: &mut DbClient, - user_id: i64, - from: usize, - to: usize, + user_id: u64, + from: u32, + to: u32, ) -> anyhow::Result<()> { + let from = usize::try_from(from)?; + let to = usize::try_from(to)?; loop { let t = db .build_transaction() @@ -198,7 +200,7 @@ pub async fn move_indices( from notifications where user_id = $1 order by idx asc nulls last;", - &[&user_id], + &[&(user_id as i64)], ) .await .context("failed to get initial ordering")?; @@ -257,10 +259,11 @@ pub async fn move_indices( pub async fn add_metadata( db: &mut DbClient, - user_id: i64, - idx: usize, + user_id: u64, + idx: u32, metadata: Option<&str>, ) -> anyhow::Result<()> { + let idx = usize::try_from(idx)?; loop { let t = db .build_transaction() @@ -275,7 +278,7 @@ pub async fn add_metadata( from notifications where user_id = $1 order by idx asc nulls last;", - &[&user_id], + &[&(user_id as i64)], ) .await .context("failed to get initial ordering")?; diff --git a/src/github.rs b/src/github.rs index b987599b5..4a1556a22 100644 --- a/src/github.rs +++ b/src/github.rs @@ -19,12 +19,12 @@ use tracing as log; #[derive(Debug, PartialEq, Eq, serde::Deserialize)] pub struct User { pub login: String, - pub id: Option, + pub id: Option, } impl GithubClient { async fn send_req(&self, req: RequestBuilder) -> anyhow::Result<(Bytes, String)> { - const MAX_ATTEMPTS: usize = 2; + const MAX_ATTEMPTS: u32 = 2; log::debug!("send_req with {:?}", req); let req_dbg = format!("{:?}", req); let req = req @@ -80,7 +80,7 @@ impl GithubClient { &self, req: Request, sleep: Duration, - remaining_attempts: usize, + remaining_attempts: u32, ) -> BoxFuture> { #[derive(Debug, serde::Deserialize)] struct RateLimit { @@ -203,7 +203,7 @@ impl User { } // Returns the ID of the given user, if the user is in the `all` team. - pub async fn get_id<'a>(&'a self, client: &'a GithubClient) -> anyhow::Result> { + pub async fn get_id<'a>(&'a self, client: &'a GithubClient) -> anyhow::Result> { let permission = crate::team_data::teams(client).await?; let map = permission.teams; Ok(map["all"] @@ -504,7 +504,7 @@ impl Issue { self.state == IssueState::Open } - pub async fn get_comment(&self, client: &GithubClient, id: usize) -> anyhow::Result { + pub async fn get_comment(&self, client: &GithubClient, id: u64) -> anyhow::Result { let comment_url = format!("{}/issues/comments/{}", self.repository().url(client), id); let comment = client.json(client.get(&comment_url)).await?; Ok(comment) @@ -540,7 +540,7 @@ impl Issue { pub async fn edit_comment( &self, client: &GithubClient, - id: usize, + id: u64, new_body: &str, ) -> anyhow::Result<()> { let comment_url = format!("{}/issues/comments/{}", self.repository().url(client), id); @@ -1030,7 +1030,7 @@ pub fn parse_diff(diff: &str) -> Vec { #[derive(Debug, serde::Deserialize)] pub struct IssueSearchResult { - pub total_count: usize, + pub total_count: u64, pub incomplete_results: bool, pub items: Vec, } @@ -1049,7 +1049,7 @@ struct Ordering<'a> { pub sort: &'a str, pub direction: &'a str, pub per_page: &'a str, - pub page: usize, + pub page: u64, } impl Repository { @@ -1136,7 +1136,7 @@ impl Repository { .await .with_context(|| format!("failed to list issues from {}", url))?; issues.extend(result.items); - if issues.len() < result.total_count { + if (issues.len() as u64) < result.total_count { ordering.page += 1; continue; } diff --git a/src/handlers/assign/tests/tests_candidates.rs b/src/handlers/assign/tests/tests_candidates.rs index 861ca7aaf..3febb1033 100644 --- a/src/handlers/assign/tests/tests_candidates.rs +++ b/src/handlers/assign/tests/tests_candidates.rs @@ -53,6 +53,7 @@ fn convert_simplified( "members": serde_json::Value::Array(members), "alumni": [], "discord": [], + "roles": [], }); } let teams = serde_json::value::from_value(teams_config).unwrap(); diff --git a/src/handlers/notification.rs b/src/handlers/notification.rs index 718b2b24b..54a89dbbb 100644 --- a/src/handlers/notification.rs +++ b/src/handlers/notification.rs @@ -11,7 +11,7 @@ use crate::{ }; use anyhow::Context as _; use std::collections::HashSet; -use std::convert::{TryFrom, TryInto}; +use std::convert::TryInto; use tracing as log; pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { @@ -58,7 +58,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { let mut users_notified = HashSet::new(); if let Some(from) = event.comment_from() { for login in parser::get_mentions(from).into_iter() { - if let Some((Ok(users), _)) = id_from_user(ctx, login).await? { + if let Some((users, _)) = id_from_user(ctx, login).await? { users_notified.extend(users.into_iter().map(|user| user.id.unwrap())); } } @@ -85,14 +85,6 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { None => continue, }; - let users = match users { - Ok(users) => users, - Err(err) => { - log::error!("getting users failed: {:?}", err); - continue; - } - }; - let client = ctx.db.get().await; for user in users { if !users_notified.insert(user.id.unwrap()) { @@ -132,7 +124,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { async fn id_from_user( ctx: &Context, login: &str, -) -> anyhow::Result>, Option)>> { +) -> anyhow::Result, Option)>> { if login.contains('/') { // This is a team ping. For now, just add it to everyone's agenda on // that team, but also mark it as such (i.e., a team ping) for @@ -174,15 +166,11 @@ async fn id_from_user( Ok(Some(( team.members .into_iter() - .map(|member| { - let id = i64::try_from(member.github_id) - .with_context(|| format!("user id {} out of bounds", member.github_id))?; - Ok(github::User { - id: Some(id), - login: member.github, - }) + .map(|member| github::User { + id: Some(member.github_id), + login: member.github, }) - .collect::>>(), + .collect::>(), Some(team.name), ))) } else { @@ -194,22 +182,16 @@ async fn id_from_user( .get_id(&ctx.github) .await .with_context(|| format!("failed to get user {} ID", user.login))?; - let id = match id { - Some(id) => id, + let Some(id) = id else { // If the user was not in the team(s) then just don't record it. - None => { - log::trace!("Skipping {} because no id found", user.login); - return Ok(None); - } + log::trace!("Skipping {} because no id found", user.login); + return Ok(None); }; - let id = i64::try_from(id).with_context(|| format!("user id {} out of bounds", id)); Ok(Some(( - id.map(|id| { - vec![github::User { - login: user.login.clone(), - id: Some(id), - }] - }), + vec![github::User { + login: user.login.clone(), + id: Some(id), + }], None, ))) } diff --git a/src/handlers/rustc_commits.rs b/src/handlers/rustc_commits.rs index d5dc30a94..8af282345 100644 --- a/src/handlers/rustc_commits.rs +++ b/src/handlers/rustc_commits.rs @@ -10,7 +10,7 @@ use std::collections::VecDeque; use std::convert::TryInto; use tracing as log; -const BORS_GH_ID: i64 = 3372342; +const BORS_GH_ID: u64 = 3372342; pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> { let body = match event.comment_body() { diff --git a/src/zulip.rs b/src/zulip.rs index a158db506..66e79cf9a 100644 --- a/src/zulip.rs +++ b/src/zulip.rs @@ -71,17 +71,17 @@ struct Response { pub const BOT_EMAIL: &str = "triage-rust-lang-bot@zulipchat.com"; -pub async fn to_github_id(client: &GithubClient, zulip_id: usize) -> anyhow::Result> { +pub async fn to_github_id(client: &GithubClient, zulip_id: u64) -> anyhow::Result> { let map = crate::team_data::zulip_map(client).await?; - Ok(map.users.get(&zulip_id).map(|v| *v as i64)) + Ok(map.users.get(&zulip_id).copied()) } -pub async fn to_zulip_id(client: &GithubClient, github_id: i64) -> anyhow::Result> { +pub async fn to_zulip_id(client: &GithubClient, github_id: u64) -> anyhow::Result> { let map = crate::team_data::zulip_map(client).await?; Ok(map .users .iter() - .find(|(_, github)| **github == github_id as usize) + .find(|&(_, &github)| github == github_id) .map(|v| *v.0)) } @@ -113,7 +113,7 @@ async fn process_zulip_request(ctx: &Context, req: Request) -> anyhow::Result Ok(gh_id), Ok(None) => Err(format_err!( "Unknown Zulip user. Please add `zulip-id = {}` to your file in \ @@ -128,7 +128,7 @@ async fn process_zulip_request(ctx: &Context, req: Request) -> anyhow::Result( ctx: &'a Context, - gh_id: anyhow::Result, + gh_id: anyhow::Result, words: &'a str, message_data: &'a Message, ) -> std::pin::Pin>> + Send + 'a>> @@ -263,7 +263,7 @@ async fn execute_for_other_user( .find(|m| m.user_id == zulip_user_id) .ok_or_else(|| format_err!("Could not find Zulip user email."))?; - let output = handle_command(ctx, Ok(user_id as i64), &command, message_data) + let output = handle_command(ctx, Ok(user_id), &command, message_data) .await? .unwrap_or_default(); @@ -479,7 +479,7 @@ impl<'a> UpdateMessageApiRequest<'a> { async fn acknowledge( ctx: &Context, - gh_id: i64, + gh_id: u64, mut words: impl Iterator, ) -> anyhow::Result> { let filter = match words.next() { @@ -491,9 +491,9 @@ async fn acknowledge( } None => anyhow::bail!("not enough words"), }; - let ident = if let Ok(number) = filter.parse::() { + let ident = if let Ok(number) = filter.parse::() { Identifier::Index( - std::num::NonZeroUsize::new(number) + std::num::NonZeroU32::new(number) .ok_or_else(|| anyhow::anyhow!("index must be at least 1"))?, ) } else if filter == "all" || filter == "*" { @@ -534,7 +534,7 @@ async fn acknowledge( async fn add_notification( ctx: &Context, - gh_id: i64, + gh_id: u64, mut words: impl Iterator, ) -> anyhow::Result> { let url = match words.next() { @@ -572,7 +572,7 @@ async fn add_notification( async fn add_meta_notification( ctx: &Context, - gh_id: i64, + gh_id: u64, mut words: impl Iterator, ) -> anyhow::Result> { let idx = match words.next() { @@ -580,7 +580,7 @@ async fn add_meta_notification( None => anyhow::bail!("idx not present"), }; let idx = idx - .parse::() + .parse::() .context("index")? .checked_sub(1) .ok_or_else(|| anyhow::anyhow!("1-based indexes"))?; @@ -604,7 +604,7 @@ async fn add_meta_notification( async fn move_notification( ctx: &Context, - gh_id: i64, + gh_id: u64, mut words: impl Iterator, ) -> anyhow::Result> { let from = match words.next() { @@ -616,12 +616,12 @@ async fn move_notification( None => anyhow::bail!("from idx not present"), }; let from = from - .parse::() + .parse::() .context("from index")? .checked_sub(1) .ok_or_else(|| anyhow::anyhow!("1-based indexes"))?; let to = to - .parse::() + .parse::() .context("to index")? .checked_sub(1) .ok_or_else(|| anyhow::anyhow!("1-based indexes"))?;