Newsletter audit: unique auto-slug so recurring titles can't clobber prior issues (1.2.41)
The composer derived the kind 30023 addressable `d` identifier straight from
slugify(title). Because 30023 is addressable, two issues sharing a slug —
a recurring "Weekly Roundup", or "Update!" vs "Update?" — would share a
coordinate and the newer publish would silently overwrite the older issue.
Blank slug now auto-generates a unique coordinate (title-slug + UTC date +
short base36 time suffix). An explicit manual slug is still honored verbatim,
so intentionally editing/replacing a specific issue keeps working.
Verified clean (no changes): backfill panel is idempotent (skips slugs already
on-relay, deterministic issue-{n} identifiers) and the subscriber-count hook
uses the standard newest-marker-per-author tally with no double-counting.
Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
6ad112dea3
commit
c376f37164
2 changed files with 15 additions and 3 deletions
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "skate-spots",
|
||||
"private": true,
|
||||
"version": "1.2.40",
|
||||
"version": "1.2.41",
|
||||
"type": "module",
|
||||
"homepage": "https://skate-spots.com",
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -48,12 +48,24 @@ export function NewsletterComposer() {
|
|||
|
||||
if (!isAdminPubkey(user?.pubkey)) return null;
|
||||
|
||||
const effectiveSlug = slug.trim() || slugify(title);
|
||||
const canPublish = title.trim().length >= 2 && body.trim().length >= 10 && !!effectiveSlug;
|
||||
// A manual slug is used verbatim (lets an admin intentionally EDIT/replace a
|
||||
// specific existing issue). When left blank we must NOT use the bare
|
||||
// title-slug: kind 30023 is addressable, so two issues that slugify the same
|
||||
// (e.g. a recurring "Weekly Roundup", or "Update!" vs "Update?") would share a
|
||||
// `d` and the newer one would silently OVERWRITE the older. So an auto-slug
|
||||
// gets a short date suffix to make each published issue its own coordinate.
|
||||
const manualSlug = slug.trim();
|
||||
const canPublish = title.trim().length >= 2 && body.trim().length >= 10 && (!!manualSlug || title.trim().length >= 2);
|
||||
|
||||
const handlePublish = async () => {
|
||||
if (!canPublish) return;
|
||||
const now = Math.floor(Date.now() / 1000);
|
||||
// YYYYMMDD suffix (UTC) keeps auto-slugs readable and unique per day; a
|
||||
// second same-title issue on the same day also gets a time component.
|
||||
const d = new Date(now * 1000);
|
||||
const dateSuffix = `${d.getUTCFullYear()}${String(d.getUTCMonth() + 1).padStart(2, '0')}${String(d.getUTCDate()).padStart(2, '0')}`;
|
||||
const autoSlug = `${slugify(title) || 'issue'}-${dateSuffix}-${now.toString(36).slice(-4)}`;
|
||||
const effectiveSlug = manualSlug || autoSlug;
|
||||
try {
|
||||
await publish({
|
||||
kind: NEWSLETTER_KIND,
|
||||
|
|
|
|||
Loading…
Reference in a new issue