Skip to content

Commit 1bb3966

Browse files
committed
Move several functions to TeamApiClient method
1 parent 3bd87f4 commit 1bb3966

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
@@ -263,49 +263,6 @@ impl User {
263263
}
264264
}
265265

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

66-
let team = match github::get_team(team_api_client, GOALS_TEAM).await {
65+
let team = match team_api_client.get_team(GOALS_TEAM).await {
6766
Ok(Some(team)) => team,
6867
Ok(None) => {
6968
log::info!("team ({}) failed to resolve to a known team", GOALS_TEAM);
@@ -245,8 +244,8 @@ async fn zulip_owners(
245244
})
246245
}
247246

248-
async fn owner_string(team_api_client: &TeamApiClient, assignee: &User) -> anyhow::Result<String> {
249-
if let Some(zulip_id) = to_zulip_id(team_api_client, assignee.id).await? {
247+
async fn owner_string(team_api: &TeamApiClient, assignee: &User) -> anyhow::Result<String> {
248+
if let Some(zulip_id) = team_api.github_to_zulip_id(assignee.id).await? {
250249
Ok(format!("@**|{zulip_id}**"))
251250
} else {
252251
// 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.team_api, 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
{
@@ -233,7 +207,9 @@ async fn handle_command<'a>(
233207

234208
// Let the impersonated person know about the impersonation if the command was sensitive
235209
if impersonated && is_sensitive_command(&cmd) {
236-
let impersonated_zulip_id = to_zulip_id(&ctx.team_api, gh_id)
210+
let impersonated_zulip_id = ctx
211+
.team_api
212+
.github_to_zulip_id(gh_id)
237213
.await?
238214
.ok_or_else(|| anyhow::anyhow!("Zulip user for GitHub ID {gh_id} was not found"))?;
239215
let users = ctx.zulip.get_zulip_users().await?;
@@ -342,7 +318,9 @@ async fn workqueue_commands(
342318
) -> anyhow::Result<Option<String>> {
343319
let db_client = ctx.db.get().await;
344320

345-
let gh_username = username_from_gh_id(&ctx.team_api, gh_id)
321+
let gh_username = ctx
322+
.team_api
323+
.username_from_gh_id(gh_id)
346324
.await?
347325
.ok_or_else(|| anyhow::anyhow!("Cannot find your GitHub username in the team database"))?;
348326
let user = User {
@@ -450,7 +428,9 @@ async fn workqueue_commands(
450428

451429
/// The `whoami` command displays the user's membership in Rust teams.
452430
async fn whoami_cmd(ctx: &Context, gh_id: u64) -> anyhow::Result<Option<String>> {
453-
let gh_username = username_from_gh_id(&ctx.team_api, gh_id)
431+
let gh_username = ctx
432+
.team_api
433+
.username_from_gh_id(gh_id)
454434
.await?
455435
.ok_or_else(|| anyhow::anyhow!("Cannot find your GitHub username in the team database"))?;
456436
let teams = ctx
@@ -541,10 +521,10 @@ async fn lookup_github_username(ctx: &Context, zulip_username: &str) -> anyhow::
541521
Some(name) => name.to_string(),
542522
None => {
543523
let zulip_id = zulip_user.user_id;
544-
let Some(gh_id) = to_github_id(&ctx.team_api, zulip_id).await? else {
524+
let Some(gh_id) = ctx.team_api.zulip_to_github_id(zulip_id).await? else {
545525
return Ok(format!("Zulip user {zulip_username} was not found in team Zulip mapping. Maybe they do not have zulip-id configured in team."));
546526
};
547-
let Some(username) = username_from_gh_id(&ctx.team_api, gh_id).await? else {
527+
let Some(username) = ctx.team_api.username_from_gh_id(gh_id).await? else {
548528
return Ok(format!(
549529
"Zulip user {zulip_username} was not found in the team database."
550530
));
@@ -603,7 +583,7 @@ async fn lookup_zulip_username(ctx: &Context, gh_username: &str) -> anyhow::Resu
603583
return Ok(None);
604584
};
605585

606-
let Some(zulip_id) = to_zulip_id(&ctx.team_api, person.github_id).await? else {
586+
let Some(zulip_id) = ctx.team_api.github_to_zulip_id(person.github_id).await? else {
607587
return Ok(None);
608588
};
609589
Ok(Some(zulip_id))

0 commit comments

Comments
 (0)