Skip to content

Commit be9366f

Browse files
authored
Merge pull request #2044 from Kobzol/zulip-client
Add a Zulip client API
2 parents 753cc10 + e7fce99 commit be9366f

File tree

11 files changed

+405
-330
lines changed

11 files changed

+405
-330
lines changed

src/bin/project_goals.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use structopt::StructOpt;
2+
use triagebot::zulip::client::ZulipClient;
23
use triagebot::{github::GithubClient, handlers::project_goals};
34

45
/// A basic example
@@ -22,8 +23,10 @@ async fn main() -> anyhow::Result<()> {
2223

2324
let opt = Opt::from_args();
2425
let gh = GithubClient::new_from_env();
26+
let zulip = ZulipClient::new_from_env();
2527
project_goals::ping_project_goals_owners(
2628
&gh,
29+
&zulip,
2730
opt.dry_run,
2831
opt.days_threshold,
2932
&opt.next_meeting_date,

src/handlers.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::config::{self, Config, ConfigurationError};
22
use crate::github::{Event, GithubClient, IssueCommentAction, IssuesAction, IssuesEvent};
33
use crate::handlers::pr_tracking::ReviewerWorkqueue;
4+
use crate::zulip::client::ZulipClient;
45
use octocrab::Octocrab;
56
use parser::command::{assign::AssignCommand, Command, Input};
67
use std::fmt;
@@ -372,6 +373,7 @@ command_handlers! {
372373

373374
pub struct Context {
374375
pub github: GithubClient,
376+
pub zulip: ZulipClient,
375377
pub db: crate::db::ClientPool,
376378
pub username: String,
377379
pub octocrab: Octocrab,

src/handlers/major_change.rs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::zulip::api::Recipient;
12
use crate::{
23
config::MajorChangeConfig,
34
github::{Event, Issue, IssuesAction, IssuesEvent, Label, ZulipGitHubReference},
@@ -119,14 +120,14 @@ pub(super) async fn handle_input(
119120
let new_topic = zulip_topic_from_issue(&partial_issue);
120121

121122
let zulip_send_req = crate::zulip::MessageApiRequest {
122-
recipient: crate::zulip::Recipient::Stream {
123+
recipient: Recipient::Stream {
123124
id: config.zulip_stream,
124125
topic: &prev_topic,
125126
},
126127
content: "The associated GitHub issue has been renamed. Renaming this Zulip topic.",
127128
};
128129
let zulip_send_res = zulip_send_req
129-
.send(&ctx.github.raw())
130+
.send(&ctx.zulip)
130131
.await
131132
.context("zulip post failed")?;
132133

@@ -137,30 +138,30 @@ pub(super) async fn handle_input(
137138
content: None,
138139
};
139140
zulip_update_req
140-
.send(&ctx.github.raw())
141+
.send(&ctx.zulip)
141142
.await
142143
.context("zulip message update failed")?;
143144

144145
// after renaming the zulip topic, post an additional comment under the old topic with a url to the new, renamed topic
145146
// this is necessary due to the lack of topic permalinks, see https://github.com/zulip/zulip/issues/15290
146-
let new_topic_url = crate::zulip::Recipient::Stream {
147+
let new_topic_url = Recipient::Stream {
147148
id: config.zulip_stream,
148149
topic: &new_topic,
149150
}
150-
.url();
151+
.url(&ctx.zulip);
151152
let breadcrumb_comment = format!(
152153
"The associated GitHub issue has been renamed. Please see the [renamed Zulip topic]({}).",
153154
new_topic_url
154155
);
155156
let zulip_send_breadcrumb_req = crate::zulip::MessageApiRequest {
156-
recipient: crate::zulip::Recipient::Stream {
157+
recipient: Recipient::Stream {
157158
id: config.zulip_stream,
158159
topic: &prev_topic,
159160
},
160161
content: &breadcrumb_comment,
161162
};
162163
zulip_send_breadcrumb_req
163-
.send(&ctx.github.raw())
164+
.send(&ctx.zulip)
164165
.await
165166
.context("zulip post failed")?;
166167

@@ -247,15 +248,15 @@ async fn handle(
247248
let zulip_topic = zulip_topic_from_issue(&partial_issue);
248249

249250
let zulip_req = crate::zulip::MessageApiRequest {
250-
recipient: crate::zulip::Recipient::Stream {
251+
recipient: Recipient::Stream {
251252
id: config.zulip_stream,
252253
topic: &zulip_topic,
253254
},
254255
content: &zulip_msg,
255256
};
256257

257258
if new_proposal {
258-
let topic_url = zulip_req.url();
259+
let topic_url = zulip_req.url(&ctx.zulip);
259260
let comment = format!(
260261
r#"> [!IMPORTANT]
261262
> This issue is *not meant to be used for technical discussion*. There is a **Zulip [stream]** for that.
@@ -289,7 +290,7 @@ See documentation at [https://forge.rust-lang.org](https://forge.rust-lang.org/c
289290
.context("post major change comment")?;
290291
}
291292

292-
let zulip_req = zulip_req.send(&ctx.github.raw());
293+
let zulip_req = zulip_req.send(&ctx.zulip);
293294

294295
let (gh_res, zulip_res) = futures::join!(github_req, zulip_req);
295296
zulip_res.context("zulip post failed")?;

src/handlers/notify_zulip.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::zulip::api::Recipient;
12
use crate::{
23
config::{NotifyZulipConfig, NotifyZulipLabelConfig, NotifyZulipTablesConfig},
34
github::{Issue, IssuesAction, IssuesEvent, Label},
@@ -208,7 +209,7 @@ pub(super) async fn handle_input<'a>(
208209
NotificationType::Reopened => &config.messages_on_reopen,
209210
};
210211

211-
let recipient = crate::zulip::Recipient::Stream {
212+
let recipient = Recipient::Stream {
212213
id: config.zulip_stream,
213214
topic: &topic,
214215
};
@@ -222,7 +223,7 @@ pub(super) async fn handle_input<'a>(
222223
recipient,
223224
content: &msg,
224225
}
225-
.send(&ctx.github.raw())
226+
.send(&ctx.zulip)
226227
.await;
227228

228229
if let Err(err) = req {

src/handlers/project_goals.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
use super::Context;
12
use crate::github::{
23
self, GithubClient, IssueCommentAction, IssueCommentEvent, IssuesAction, IssuesEvent, User,
34
};
45
use crate::github::{Event, Issue};
56
use crate::jobs::Job;
7+
use crate::zulip::api::Recipient;
8+
use crate::zulip::client::ZulipClient;
69
use crate::zulip::to_zulip_id;
710
use anyhow::Context as _;
811
use async_trait::async_trait;
912
use chrono::{Datelike, NaiveDate, Utc};
1013
use tracing::{self as log};
1114

12-
use super::Context;
13-
1415
const MAX_ZULIP_TOPIC: usize = 60;
1516
const RUST_PROJECT_GOALS_REPO: &'static str = "rust-lang/rust-project-goals";
1617
const GOALS_STREAM: u64 = 435869; // #project-goals
@@ -39,7 +40,7 @@ impl Job for ProjectGoalsUpdateJob {
3940
}
4041

4142
async fn run(&self, ctx: &super::Context, _metadata: &serde_json::Value) -> anyhow::Result<()> {
42-
ping_project_goals_owners_automatically(&ctx.github).await
43+
ping_project_goals_owners_automatically(&ctx.github, &ctx.zulip).await
4344
}
4445
}
4546

@@ -71,7 +72,10 @@ pub async fn check_project_goal_acl(gh: &GithubClient, gh_id: u64) -> anyhow::Re
7172
.is_some())
7273
}
7374

74-
async fn ping_project_goals_owners_automatically(gh: &GithubClient) -> anyhow::Result<()> {
75+
async fn ping_project_goals_owners_automatically(
76+
gh: &GithubClient,
77+
zulip: &ZulipClient,
78+
) -> anyhow::Result<()> {
7579
// Predicted schedule is to author a blog post on the 3rd week of the month.
7680
// We start pinging when the month starts until we see an update in this month
7781
// or the last 7 days of previous month.
@@ -91,7 +95,7 @@ async fn ping_project_goals_owners_automatically(gh: &GithubClient) -> anyhow::R
9195
.format("on %b-%d")
9296
.to_string();
9397

94-
ping_project_goals_owners(gh, false, days_threshold as i64, &third_monday).await
98+
ping_project_goals_owners(gh, zulip, false, days_threshold as i64, &third_monday).await
9599
}
96100

97101
/// Sends a ping message to all project goal owners if
@@ -101,6 +105,7 @@ async fn ping_project_goals_owners_automatically(gh: &GithubClient) -> anyhow::R
101105
/// will be drafted (e.g., `"on Sep 5"`).
102106
pub async fn ping_project_goals_owners(
103107
gh: &GithubClient,
108+
zulip: &ZulipClient,
104109
dry_run: bool,
105110
days_threshold: i64,
106111
next_update: &str,
@@ -156,7 +161,7 @@ pub async fn ping_project_goals_owners(
156161
.replace("$NEXT_UPDATE", next_update);
157162

158163
let zulip_req = crate::zulip::MessageApiRequest {
159-
recipient: crate::zulip::Recipient::Stream {
164+
recipient: Recipient::Stream {
160165
id: GOALS_STREAM,
161166
topic: &zulip_topic_name,
162167
},
@@ -167,7 +172,7 @@ pub async fn ping_project_goals_owners(
167172
log::debug!("message = {message:#?}");
168173

169174
if !dry_run {
170-
zulip_req.send(&gh.raw()).await?;
175+
zulip_req.send(&zulip).await?;
171176
} else {
172177
eprintln!();
173178
eprintln!("-- Dry Run ------------------------------------");
@@ -253,15 +258,15 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
253258
let title = &issue.title;
254259
let goalnum = issue.number;
255260
let zulip_req = crate::zulip::MessageApiRequest {
256-
recipient: crate::zulip::Recipient::Stream {
261+
recipient: Recipient::Stream {
257262
id: GOALS_STREAM,
258263
topic: &zulip_topic_name,
259264
},
260265
content: &format!(
261266
r#"New tracking issue goals#{goalnum}.\n* Goal title: {title}\n* Goal owners: {zulip_owners}"#
262267
),
263268
};
264-
zulip_req.send(&gh.raw()).await?;
269+
zulip_req.send(&ctx.zulip).await?;
265270
Ok(())
266271
}
267272

@@ -297,7 +302,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
297302
match action {
298303
IssueCommentAction::Created | IssueCommentAction::Edited => {
299304
let zulip_req = crate::zulip::MessageApiRequest {
300-
recipient: crate::zulip::Recipient::Stream {
305+
recipient: Recipient::Stream {
301306
id: GOALS_STREAM,
302307
topic: &zulip_topic_name,
303308
},
@@ -308,7 +313,7 @@ pub async fn handle(ctx: &Context, event: &Event) -> anyhow::Result<()> {
308313
{ticks}"
309314
),
310315
};
311-
zulip_req.send(&gh.raw()).await?;
316+
zulip_req.send(&ctx.zulip).await?;
312317
}
313318

314319
IssueCommentAction::Deleted => {

src/handlers/types_planning_updates.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::db::schedule_job;
22
use crate::github;
33
use crate::jobs::Job;
4+
use crate::zulip::api::Recipient;
45
use anyhow::Context as _;
56
use async_trait::async_trait;
67
use chrono::{Datelike, Duration, NaiveTime, TimeZone, Utc};
@@ -32,13 +33,13 @@ impl Job for TypesPlanningMeetingThreadOpenJob {
3233
This is a reminder to update the current [roadmap tracking issues](https://github.com/rust-lang/types-team/issues?q=is%3Aissue+is%3Aopen+label%3Aroadmap-tracking-issue).\n\
3334
Extra reminders will be sent later this week.");
3435
let zulip_req = crate::zulip::MessageApiRequest {
35-
recipient: crate::zulip::Recipient::Stream {
36+
recipient: Recipient::Stream {
3637
id: TYPES_MEETINGS_STREAM,
3738
topic: &format!("{meeting_date_string} planning meeting"),
3839
},
3940
content: &message,
4041
};
41-
zulip_req.send(&ctx.github.raw()).await?;
42+
zulip_req.send(&ctx.zulip).await?;
4243

4344
// Then, we want to schedule the next Thursday after this
4445
let mut thursday = today;
@@ -158,13 +159,13 @@ pub async fn request_updates(
158159

159160
let meeting_date_string = metadata.date_string;
160161
let zulip_req = crate::zulip::MessageApiRequest {
161-
recipient: crate::zulip::Recipient::Stream {
162+
recipient: Recipient::Stream {
162163
id: TYPES_MEETINGS_STREAM,
163164
topic: &format!("{meeting_date_string} planning meeting"),
164165
},
165166
content: &message,
166167
};
167-
zulip_req.send(&ctx.github.raw()).await?;
168+
zulip_req.send(&ctx.zulip).await?;
168169

169170
Ok(())
170171
}

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use triagebot::handlers::pr_tracking::ReviewerWorkqueue;
1717
use triagebot::jobs::{
1818
default_jobs, JOB_PROCESSING_CADENCE_IN_SECS, JOB_SCHEDULING_CADENCE_IN_SECS,
1919
};
20+
use triagebot::zulip::client::ZulipClient;
2021
use triagebot::{db, github, handlers::Context, notification_listing, payload, EventName};
2122

2223
async fn handle_agenda_request(req: String) -> anyhow::Result<String> {
@@ -248,6 +249,7 @@ async fn serve_req(
248249

249250
async fn run_server(addr: SocketAddr) -> anyhow::Result<()> {
250251
let gh = github::GithubClient::new_from_env();
252+
let zulip = ZulipClient::new_from_env();
251253
let oc = octocrab::OctocrabBuilder::new()
252254
.personal_token(github::default_token_from_env())
253255
.build()
@@ -291,6 +293,7 @@ async fn run_server(addr: SocketAddr) -> anyhow::Result<()> {
291293
github: gh,
292294
octocrab: oc,
293295
workqueue: Arc::new(RwLock::new(workqueue)),
296+
zulip,
294297
});
295298

296299
// Run all jobs that have a schedule (recurring jobs)

src/tests/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::db::users::record_username;
33
use crate::db::{make_client, ClientPool, PooledClient};
44
use crate::github::GithubClient;
55
use crate::handlers::Context;
6+
use crate::zulip::client::ZulipClient;
67
use octocrab::Octocrab;
78
use std::future::Future;
89
use std::sync::Arc;
@@ -67,8 +68,13 @@ impl TestContext {
6768
"https://api.github.com/graphql".to_string(),
6869
"https://raw.githubusercontent.com".to_string(),
6970
);
71+
let zulip = ZulipClient::new(
72+
"https://rust-fake.zulipchat.com".to_string(),
73+
"[email protected]".to_string(),
74+
);
7075
let ctx = Context {
7176
github,
77+
zulip,
7278
db: pool,
7379
username: "triagebot-test".to_string(),
7480
octocrab,

0 commit comments

Comments
 (0)