Skip to content

Commit 5885b1d

Browse files
committed
Move several functions to TeamApiClient method
1 parent c0a83ce commit 5885b1d

File tree

6 files changed

+91
-89
lines changed

6 files changed

+91
-89
lines changed

src/github.rs

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -267,49 +267,6 @@ impl User {
267267
}
268268
}
269269

270-
// Returns the ID of the given user, if the user is in the `all` team.
271-
pub async fn get_id_for_username(
272-
client: &TeamApiClient,
273-
login: &str,
274-
) -> anyhow::Result<Option<u64>> {
275-
let permission = client.teams().await?;
276-
let map = permission.teams;
277-
let login = login.to_lowercase();
278-
Ok(map["all"]
279-
.members
280-
.iter()
281-
.find(|g| g.github.to_lowercase() == login)
282-
.map(|u| u.github_id))
283-
}
284-
285-
pub async fn get_team(
286-
client: &TeamApiClient,
287-
team: &str,
288-
) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
289-
let permission = client.teams().await?;
290-
let mut map = permission.teams;
291-
Ok(map.swap_remove(team))
292-
}
293-
294-
/// Fetches a Rust team via its GitHub team name.
295-
pub async fn get_team_by_github_name(
296-
client: &TeamApiClient,
297-
org: &str,
298-
team: &str,
299-
) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
300-
let teams = client.teams().await?;
301-
for rust_team in teams.teams.into_values() {
302-
if let Some(github) = &rust_team.github {
303-
for gh_team in &github.teams {
304-
if gh_team.org == org && gh_team.name == team {
305-
return Ok(Some(rust_team));
306-
}
307-
}
308-
}
309-
}
310-
Ok(None)
311-
}
312-
313270
#[derive(PartialEq, Eq, Debug, Clone, serde::Deserialize)]
314271
pub struct Label {
315272
pub name: String,

src/handlers/notification.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
//! Parsing is done in the `parser::command::ping` module.
66
77
use crate::db::{notifications, users};
8-
use crate::github::get_id_for_username;
98
use crate::{
109
github::{self, Event},
1110
handlers::Context,
@@ -69,7 +68,11 @@ pub(super) async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
6968
//
7069
// If the user intended to ping themselves, they can add the GitHub comment
7170
// via the Zulip interface.
72-
match get_id_for_username(&ctx.team_api, &event.user().login).await {
71+
match ctx
72+
.team_api
73+
.get_gh_id_from_username(&event.user().login)
74+
.await
75+
{
7376
Ok(Some(id)) => {
7477
users_notified.insert(id.try_into().unwrap());
7578
}
@@ -136,7 +139,7 @@ async fn id_from_user(
136139
//
137140
// We may also want to be able to categorize into these buckets
138141
// *after* the ping occurs and is initially processed.
139-
let team = match github::get_team_by_github_name(&ctx.team_api, org, team).await {
142+
let team = match ctx.team_api.get_team_by_github_name(org, team).await {
140143
Ok(Some(team)) => team,
141144
Ok(None) => {
142145
// If the team is in rust-lang*, then this is probably an error (potentially user
@@ -170,7 +173,9 @@ async fn id_from_user(
170173
Some(team.name),
171174
)))
172175
} else {
173-
let id = get_id_for_username(&ctx.team_api, login)
176+
let id = ctx
177+
.team_api
178+
.get_gh_id_from_username(login)
174179
.await
175180
.with_context(|| format!("failed to get user {} ID", login))?;
176181
let Some(id) = id else {

src/handlers/ping.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub(super) async fn handle_command(
4949
return Ok(());
5050
}
5151
};
52-
let team = github::get_team(&ctx.team_api, &gh_team).await?;
52+
let team = ctx.team_api.get_team(&gh_team).await?;
5353
let team = match team {
5454
Some(team) => team,
5555
None => {

src/handlers/project_goals.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use crate::jobs::Job;
77
use crate::team_data::TeamApiClient;
88
use crate::zulip::api::Recipient;
99
use crate::zulip::client::ZulipClient;
10-
use crate::zulip::to_zulip_id;
1110
use anyhow::Context as _;
1211
use async_trait::async_trait;
1312
use chrono::{Datelike, NaiveDate, Utc};
@@ -53,7 +52,7 @@ pub async fn check_project_goal_acl(
5352
) -> anyhow::Result<bool> {
5453
const GOALS_TEAM: &str = "goals";
5554

56-
let team = match github::get_team(team_api_client, GOALS_TEAM).await {
55+
let team = match team_api_client.get_team(GOALS_TEAM).await {
5756
Ok(Some(team)) => team,
5857
Ok(None) => {
5958
log::info!("team ({}) failed to resolve to a known team", GOALS_TEAM);
@@ -237,8 +236,8 @@ async fn zulip_owners(
237236
})
238237
}
239238

240-
async fn owner_string(team_api_client: &TeamApiClient, assignee: &User) -> anyhow::Result<String> {
241-
if let Some(zulip_id) = to_zulip_id(team_api_client, assignee.id).await? {
239+
async fn owner_string(team_api: &TeamApiClient, assignee: &User) -> anyhow::Result<String> {
240+
if let Some(zulip_id) = team_api.github_to_zulip_id(assignee.id).await? {
242241
Ok(format!("@**|{zulip_id}**"))
243242
} else {
244243
// No zulip-id? Fallback to github user name.

src/team_data.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,67 @@ impl TeamApiClient {
2222
}
2323
}
2424

25+
pub async fn zulip_to_github_id(&self, zulip_id: u64) -> anyhow::Result<Option<u64>> {
26+
let map = self.zulip_map().await?;
27+
Ok(map.users.get(&zulip_id).copied())
28+
}
29+
30+
pub async fn username_from_gh_id(&self, github_id: u64) -> anyhow::Result<Option<String>> {
31+
let people_map = self.people().await?;
32+
Ok(people_map
33+
.people
34+
.into_iter()
35+
.filter(|(_, p)| p.github_id == github_id)
36+
.map(|p| p.0)
37+
.next())
38+
}
39+
40+
// Returns the ID of the given user, if the user is in the `all` team.
41+
pub async fn get_gh_id_from_username(&self, login: &str) -> anyhow::Result<Option<u64>> {
42+
let permission = self.teams().await?;
43+
let map = permission.teams;
44+
let login = login.to_lowercase();
45+
Ok(map["all"]
46+
.members
47+
.iter()
48+
.find(|g| g.github.to_lowercase() == login)
49+
.map(|u| u.github_id))
50+
}
51+
52+
pub async fn github_to_zulip_id(&self, github_id: u64) -> anyhow::Result<Option<u64>> {
53+
let map = self.zulip_map().await?;
54+
Ok(map
55+
.users
56+
.iter()
57+
.find(|&(_, &github)| github == github_id)
58+
.map(|v| *v.0))
59+
}
60+
61+
pub async fn get_team(&self, team: &str) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
62+
let permission = self.teams().await?;
63+
let mut map = permission.teams;
64+
Ok(map.swap_remove(team))
65+
}
66+
67+
/// Fetches a Rust team via its GitHub team name.
68+
pub async fn get_team_by_github_name(
69+
&self,
70+
org: &str,
71+
team: &str,
72+
) -> anyhow::Result<Option<rust_team_data::v1::Team>> {
73+
let teams = self.teams().await?;
74+
for rust_team in teams.teams.into_values() {
75+
if let Some(github) = &rust_team.github {
76+
for gh_team in &github.teams {
77+
if gh_team.org == org && gh_team.name == team {
78+
return Ok(Some(rust_team));
79+
}
80+
}
81+
}
82+
}
83+
Ok(None)
84+
}
85+
2586
pub async fn zulip_map(&self) -> anyhow::Result<ZulipMapping> {
2687
download(&self.client, &self.base_url, "/zulip-map.json")
2788
.await

src/zulip.rs

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ mod commands;
55
use crate::db::notifications::add_metadata;
66
use crate::db::notifications::{self, delete_ping, move_indices, record_ping, Identifier};
77
use crate::db::review_prefs::{get_review_prefs, upsert_review_prefs, RotationMode};
8-
use crate::github::{get_id_for_username, User};
8+
use crate::github::User;
99
use crate::handlers::docs_update::docs_update;
1010
use crate::handlers::pr_tracking::get_assigned_prs;
1111
use crate::handlers::project_goals::{self, ping_project_goals_owners};
1212
use crate::handlers::Context;
13-
use crate::team_data::TeamApiClient;
1413
use crate::utils::pluralize;
1514
use crate::zulip::api::{MessageApiResponse, Recipient};
1615
use crate::zulip::client::ZulipClient;
@@ -83,33 +82,6 @@ struct Response {
8382
content: String,
8483
}
8584

86-
pub async fn to_github_id(client: &TeamApiClient, zulip_id: u64) -> anyhow::Result<Option<u64>> {
87-
let map = client.zulip_map().await?;
88-
Ok(map.users.get(&zulip_id).copied())
89-
}
90-
91-
pub async fn username_from_gh_id(
92-
client: &TeamApiClient,
93-
gh_id: u64,
94-
) -> anyhow::Result<Option<String>> {
95-
let people_map = client.people().await?;
96-
Ok(people_map
97-
.people
98-
.into_iter()
99-
.filter(|(_, p)| p.github_id == gh_id)
100-
.map(|p| p.0)
101-
.next())
102-
}
103-
104-
pub async fn to_zulip_id(client: &TeamApiClient, github_id: u64) -> anyhow::Result<Option<u64>> {
105-
let map = client.zulip_map().await?;
106-
Ok(map
107-
.users
108-
.iter()
109-
.find(|&(_, &github)| github == github_id)
110-
.map(|v| *v.0))
111-
}
112-
11385
/// Top-level handler for Zulip webhooks.
11486
///
11587
/// Returns a JSON response.
@@ -157,7 +129,7 @@ async fn process_zulip_request(ctx: &Context, req: Request) -> anyhow::Result<Op
157129
log::trace!("zulip hook: {req:?}");
158130

159131
// Zulip commands are only available to users in the team database
160-
let gh_id = match to_github_id(&ctx.team_api, req.message.sender_id).await {
132+
let gh_id = match ctx.team_api.zulip_to_github_id(req.message.sender_id).await {
161133
Ok(Some(gh_id)) => gh_id,
162134
Ok(None) => {
163135
return Err(anyhow::anyhow!(
@@ -187,7 +159,9 @@ async fn handle_command<'a>(
187159
let mut impersonated = false;
188160
if let Some(&"as") = words.get(0) {
189161
if let Some(username) = words.get(1) {
190-
let impersonated_gh_id = match get_id_for_username(&ctx.github, username)
162+
let impersonated_gh_id = match ctx
163+
.team_api
164+
.get_gh_id_from_username(username)
191165
.await
192166
.context("getting ID of github user")?
193167
{
@@ -228,7 +202,9 @@ async fn handle_command<'a>(
228202

229203
// Let the impersonated person know about the impersonation if the command was sensitive
230204
if impersonated && is_sensitive_command(&cmd) {
231-
let impersonated_zulip_id = to_zulip_id(&ctx.github, gh_id)
205+
let impersonated_zulip_id = ctx
206+
.team_api
207+
.github_to_zulip_id(gh_id)
232208
.await?
233209
.ok_or_else(|| anyhow::anyhow!("Zulip user for GitHub ID {gh_id} was not found"))?;
234210
let users = ctx.zulip.get_zulip_users().await?;
@@ -332,7 +308,9 @@ async fn workqueue_commands(
332308
) -> anyhow::Result<Option<String>> {
333309
let db_client = ctx.db.get().await;
334310

335-
let gh_username = username_from_gh_id(&ctx.team_api, gh_id)
311+
let gh_username = ctx
312+
.team_api
313+
.username_from_gh_id(gh_id)
336314
.await?
337315
.ok_or_else(|| anyhow::anyhow!("Cannot find your GitHub username in the team database"))?;
338316
let user = User {
@@ -440,7 +418,9 @@ async fn workqueue_commands(
440418

441419
/// The `whoami` command displays the user's membership in Rust teams.
442420
async fn whoami_cmd(ctx: &Context, gh_id: u64) -> anyhow::Result<Option<String>> {
443-
let gh_username = username_from_gh_id(&ctx.team_api, gh_id)
421+
let gh_username = ctx
422+
.team_api
423+
.username_from_gh_id(gh_id)
444424
.await?
445425
.ok_or_else(|| anyhow::anyhow!("Cannot find your GitHub username in the team database"))?;
446426
let teams = ctx
@@ -531,10 +511,10 @@ async fn lookup_github_username(ctx: &Context, zulip_username: &str) -> anyhow::
531511
Some(name) => name.to_string(),
532512
None => {
533513
let zulip_id = zulip_user.user_id;
534-
let Some(gh_id) = to_github_id(&ctx.team_api, zulip_id).await? else {
514+
let Some(gh_id) = ctx.team_api.zulip_to_github_id(zulip_id).await? else {
535515
return Ok(format!("Zulip user {zulip_username} was not found in team Zulip mapping. Maybe they do not have zulip-id configured in team."));
536516
};
537-
let Some(username) = username_from_gh_id(&ctx.team_api, gh_id).await? else {
517+
let Some(username) = ctx.team_api.username_from_gh_id(gh_id).await? else {
538518
return Ok(format!(
539519
"Zulip user {zulip_username} was not found in the team database."
540520
));
@@ -593,7 +573,7 @@ async fn lookup_zulip_username(ctx: &Context, gh_username: &str) -> anyhow::Resu
593573
return Ok(None);
594574
};
595575

596-
let Some(zulip_id) = to_zulip_id(&ctx.team_api, person.github_id).await? else {
576+
let Some(zulip_id) = ctx.team_api.github_to_zulip_id(person.github_id).await? else {
597577
return Ok(None);
598578
};
599579
Ok(Some(zulip_id))

0 commit comments

Comments
 (0)