forge_notify: fix notification type strings and PR state detection (fixes #201)

This commit is contained in:
damocles 2026-05-21 22:08:56 +02:00 committed by Mara
parent ab1f8d6e33
commit 13b7a94257

View file

@ -158,8 +158,9 @@ async fn format_notification(
.unwrap_or("") .unwrap_or("")
.trim(); .trim();
// Forgejo API returns "Pull" / "Issue", never "Pull Request".
let kind = match notif_type { let kind = match notif_type {
"Pull Request" => "comment on PR", "Pull" => "comment on PR",
"Issue" => "comment on issue", "Issue" => "comment on issue",
_ => "comment", _ => "comment",
}; };
@ -174,40 +175,42 @@ async fn format_notification(
out out
} else { } else {
// Notification triggered by creation or state change of the subject. // Notification triggered by creation or state change of the subject.
let subject = fetch_json(client, subject_api_url, token).await; //
let author = subject // Classification uses notif["subject"]["state"] directly — Forgejo
.as_ref() // returns "open" / "closed" / "merged" here. We do NOT rely on
.and_then(|s| s["user"]["login"].as_str()) // fetching the PR/issue detail for `merged`:
.unwrap_or("?"); // - `subject.url` points to the *issues* endpoint, which returns
let body = subject // `pull_request.merged`, not top-level `merged`.
.as_ref() // - Forgejo API type is "Pull" / "Issue", never "Pull Request".
.and_then(|s| s["body"].as_str()) let notif_state = notif["subject"]["state"].as_str().unwrap_or("");
.unwrap_or("")
.trim();
let state = subject
.as_ref()
.and_then(|s| s["state"].as_str())
.unwrap_or("");
let merged = subject
.as_ref()
.and_then(|s| s["merged"].as_bool())
.unwrap_or(false);
let kind = match (notif_type, state, merged) { let kind = match (notif_type, notif_state) {
("Pull Request", "closed", true) => "PR merged".to_owned(), ("Pull", "merged") => "PR merged".to_owned(),
("Pull Request", "closed", false) => "PR closed".to_owned(), ("Pull", "closed") => "PR closed".to_owned(),
("Pull Request", _, _) => "new PR".to_owned(), ("Pull", _) => "new PR".to_owned(),
("Issue", "closed", _) => "issue closed".to_owned(), ("Issue", "closed") => "issue closed".to_owned(),
("Issue", _, _) => "new issue".to_owned(), ("Issue", _) => "new issue".to_owned(),
_ => format!("new {notif_type}"), _ => format!("new {notif_type}"),
}; };
// Fetch subject only for body/author on new (open) items — not
// worth an extra HTTP round-trip for already-closed/merged ones.
let is_open = notif_state == "open" || notif_state.is_empty();
let mut out = format!("[{kind}] {title}\nrepo: {repo}\nurl: {html_url}"); let mut out = format!("[{kind}] {title}\nrepo: {repo}\nurl: {html_url}");
if !body.is_empty() && !state.contains("closed") && !merged { if is_open {
out.push_str(&format!( let subject = fetch_json(client, subject_api_url, token).await;
"\n\n{author}: {}", let author = subject
truncate(body, BODY_TRUNCATE) .as_ref()
)); .and_then(|s| s["user"]["login"].as_str())
.unwrap_or("?");
let body = subject
.as_ref()
.and_then(|s| s["body"].as_str())
.unwrap_or("")
.trim();
if !body.is_empty() {
out.push_str(&format!("\n\n{author}: {}", truncate(body, BODY_TRUNCATE)));
}
} }
out out
} }