import TurndownService from "turndown"; import type { PayloadEvent } from "../external.ts"; import { log } from "./cli.ts"; import type { OctokitWithPlugins } from "./github.ts"; import type { RunContextData } from "./runContextData.ts"; const turndown = new TurndownService(); function hasImages(body: string | null | undefined): boolean { if (!body) return false; return body.includes(" { const body = ctx.event.body; // pass through if no images - no API call needed if (!hasImages(body)) return body ?? null; log.debug(`[resolveBody] fetching body_html for ${ctx.event.trigger}`); const bodyHtml = await fetchBodyHtml(ctx); log.debug(`[resolveBody] bodyHtml: ${bodyHtml?.substring(0, 300)}`); if (!bodyHtml) return body ?? null; const resolved = turndown.turndown(bodyHtml); log.debug(`[resolveBody] resolved: ${resolved.substring(0, 300)}`); return resolved; } async function fetchBodyHtml(ctx: ResolveBodyContext): Promise { const event = ctx.event; const headers = { accept: "application/vnd.github.full+json" }; const owner = ctx.repo.owner; const repo = ctx.repo.name; switch (event.trigger) { case "issue_comment_created": if (!event.comment_id) return; return ( await ctx.octokit.rest.issues.getComment({ owner, repo, comment_id: event.comment_id, headers, }) ).data.body_html; case "issues_opened": case "issues_assigned": case "issues_labeled": if (!event.issue_number) return; return ( await ctx.octokit.rest.issues.get({ owner, repo, issue_number: event.issue_number, headers, }) ).data.body_html; case "pull_request_opened": case "pull_request_ready_for_review": case "pull_request_synchronize": case "pull_request_review_requested": // PRs are also issues - use issues.get which returns body_html if (!event.issue_number) return; return ( await ctx.octokit.rest.issues.get({ owner, repo, issue_number: event.issue_number, headers, }) ).data.body_html; case "pull_request_review_submitted": if (!event.issue_number || !event.review_id) return; return ( await ctx.octokit.rest.pulls.getReview({ owner, repo, pull_number: event.issue_number, review_id: event.review_id, headers, }) ).data.body_html; case "pull_request_review_comment_created": if (!event.comment_id) return; return ( await ctx.octokit.rest.pulls.getReviewComment({ owner, repo, comment_id: event.comment_id, headers, }) ).data.body_html; case "check_suite_completed": // body is the PR body if (!event.issue_number) return; return ( await ctx.octokit.rest.issues.get({ owner, repo, issue_number: event.issue_number, headers, }) ).data.body_html; case "implement_plan": // body is the plan content from an issue comment if (!event.plan_comment_id) return; return ( await ctx.octokit.rest.issues.getComment({ owner, repo, comment_id: event.plan_comment_id, headers, }) ).data.body_html; // triggers without a body field that needs resolution case "workflow_dispatch": case "fix_review": case "unknown": return undefined; default: // exhaustiveness check - TypeScript will error if a trigger is missing event satisfies never; return undefined; } }