import type { RepoEvent } from "./events";
// Events in a sentence, for lists of activity: "opened pull request #4: Fix login".
const obj = (v: unknown) => (typeof v === "object" && v !== null ? (v as Record<string, unknown>) : {});
export function describeEvent(e: RepoEvent) {
const p = e.payload;
const issue = obj(p.issue);
const pr = obj(p.pull_request);
const title = (o: Record<string, unknown>) => (o.title ? `: ${o.title}` : "");
const action = e.action?.replace(/_/g, " ") ?? "";
switch (e.kind) {
case "push": {
const ref = String(p.ref ?? "").replace(/^refs\/(heads|tags)\//, "");
if (p.deleted) return `deleted ${ref}`;
const n = Number(p.total_commits ?? 0);
return `${p.forced ? "force-pushed" : "pushed"} ${n} commit${n === 1 ? "" : "s"} to ${ref}`;
}
case "create":
return `created ${p.ref_type} ${p.ref}`;
case "delete":
return `deleted ${p.ref_type} ${p.ref}`;
case "issues":
if (e.action === "status_changed") return `moved issue ${e.subject}${title(issue)} to ${String(obj(obj(obj(p.changes).status)).to ?? "").replace(/_/g, " ")}`;
return `${action} issue ${e.subject}${title(issue)}`;
case "issue_comment":
return `commented on ${p.pull_request ? "pull request" : "issue"} ${e.subject}${title(p.pull_request ? pr : issue)}`;
case "pull_request":
return `${action === "synchronize" ? "updated" : action} pull request ${e.subject}${title(pr)}`;
case "pull_request_review":
return `reviewed pull request ${e.subject} (${String(obj(p.review).state ?? "").replace(/_/g, " ")})`;
case "pull_request_review_comment":
return `commented on the changes of pull request ${e.subject}`;
case "workflow_run":
return `${e.subject} ${obj(p.workflow_run).status ?? "finished"}`;
case "release":
return `${action} release ${e.subject}`;
case "fork":
return `forked the repository to ${e.subject}`;
default:
return `${e.kind} ${action} ${e.subject}`.trim();
}
}
/** Where an event's subject lives in the web UI, under the repository's base path. */
export function eventPath(e: RepoEvent) {
const p = e.payload;
const number = /^#(\d+)$/.exec(e.subject)?.[1];
if (number) return p.pull_request || e.kind.startsWith("pull_request") ? `/pulls/${number}` : `/issues/${number}`;
if (e.kind === "push" && typeof p.after === "string" && p.after) return `/commit/${p.after}`;
if (e.kind === "workflow_run") return `/actions/runs/${obj(p.workflow_run).number}`;
return "";
}
/** A push an agent made that can be undone: commits added to an existing branch. */
export function isRevertable(e: RepoEvent) {
const p = e.payload;
return e.kind === "push" && !!e.agent && String(p.ref ?? "").startsWith("refs/heads/") && !!p.before && !!p.after && !p.deleted && !p.reverted;
}