Mike Nann's distribute.users record has skip_rewrite=true (set when task #19 added the column). distribute-rmp's submit route forwards the flag in its payload (task #20). BB's receive route handles it (task #21). AV Beat's receive route was missing the branch entirely AND was writing to .schema('bb') instead of 'av' — a copy-paste bug from when this file was cloned from BB. So every Mike Nann submission to AV Beat was either landing in BB's schema (wrong) or trying to and failing. Fixed in this commit: src/app/api/submission-receive/route.ts • .schema('bb') → .schema('av') (the copy-paste bug) • Added skip_rewrite branch: when payload has skip_rewrite=true, insert straight into av.wp_imported_posts with status=published, noindex=true, and the contributor's firm/contact_name as byline. Skips the native_articles → AI-rewrite path entirely. Mirrors BB's pattern exactly. Audit row still written to original_submissions. src/lib/articles/types.ts • Article.noindex?: boolean — surfaces the DB column to the renderer. src/lib/articles/legacy-source.ts • SELECT_COLS adds noindex • ImportedPostRow gains noindex field • rowToArticle propagates !!row.noindex src/app/news/[slug]/page.tsx + src/app/articles/[slug]/page.tsx • generateMetadata: when article.noindex, set robots = no-index + no-follow + nocache + googleBot no-image-index + other meta key "googlebot-news": "noindex". Matches BB's pattern. src/app/news-sitemap.xml/route.ts • Adds .or('noindex.is.null,noindex.eq.false') so passthrough rows don't pollute the Google News sitemap. src/app/rss/route.ts • Filters out a.noindex before emitting items. Mike's existing user record is already flagged (DB verified), so the moment this deploys + he submits, the next press release publishes verbatim, gets noindex on every Google/social surface, and shows up on the AV Beat news index without going through the AI rewrite job. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import { getLegacyArticlesBySection } from "@/lib/articles/legacy-source";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
export const revalidate = 1800;
|
|
|
|
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || "https://avbeat.com";
|
|
|
|
function escapeXml(s: string): string {
|
|
return s
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """)
|
|
.replace(/'/g, "'");
|
|
}
|
|
|
|
export async function GET() {
|
|
let items = "";
|
|
try {
|
|
const articles = await getLegacyArticlesBySection("news", 50);
|
|
items = articles
|
|
.filter((a) => !a.noindex) // exclude passthrough PR submissions
|
|
.map((a) => {
|
|
const url = `${SITE_URL}/news/${a.slug}`;
|
|
const pubDate = a.date ? new Date(a.date).toUTCString() : new Date().toUTCString();
|
|
const title = escapeXml(a.title || "Untitled");
|
|
const description = escapeXml(a.excerpt || "");
|
|
return ` <item>
|
|
<title>${title}</title>
|
|
<link>${url}</link>
|
|
<guid isPermaLink="true">${url}</guid>
|
|
<pubDate>${pubDate}</pubDate>
|
|
<description>${description}</description>
|
|
</item>`;
|
|
})
|
|
.join("\n");
|
|
} catch {
|
|
// serve an empty but valid feed on failure
|
|
items = "";
|
|
}
|
|
|
|
const body = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
<channel>
|
|
<title>AV Beat</title>
|
|
<link>${SITE_URL}</link>
|
|
<atom:link href="${SITE_URL}/rss" rel="self" type="application/rss+xml" />
|
|
<description>Pro AV, Display and Live Production Tech</description>
|
|
<language>en-us</language>
|
|
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
|
|
${items}
|
|
</channel>
|
|
</rss>`;
|
|
|
|
return new Response(body, {
|
|
headers: {
|
|
"Content-Type": "application/rss+xml; charset=utf-8",
|
|
"Cache-Control": "public, max-age=1800, s-maxage=1800, stale-while-revalidate=3600",
|
|
},
|
|
});
|
|
}
|