173 lines
5.6 KiB
TypeScript
173 lines
5.6 KiB
TypeScript
import type { APIRoute } from 'astro';
|
|
import { requireAdmin } from '../../../lib/adminAuth';
|
|
import { readCms, writeCms, type PostStatus } from '../../../lib/cms';
|
|
import { publishPost } from '../../../lib/publisher';
|
|
import { getTassFeedLinks } from '../../../lib/tassAgent';
|
|
|
|
const toList = (value: FormDataEntryValue | null) => String(value ?? '')
|
|
.split(/\r?\n|,/)
|
|
.map((item) => item.trim())
|
|
.filter(Boolean);
|
|
|
|
const toParagraphs = (value: FormDataEntryValue | null) => String(value ?? '')
|
|
.split(/\n\s*\n/)
|
|
.map((item) => item.trim())
|
|
.filter(Boolean);
|
|
|
|
export const POST: APIRoute = async (context) => {
|
|
const unauthorized = requireAdmin(context);
|
|
|
|
if (unauthorized) {
|
|
return unauthorized;
|
|
}
|
|
|
|
const formData = await context.request.formData();
|
|
const action = String(formData.get('action') ?? '');
|
|
const cms = await readCms();
|
|
const tab = String(formData.get('tab') ?? 'pending');
|
|
|
|
if (action === 'post-status') {
|
|
const slug = String(formData.get('slug') ?? '');
|
|
const status = String(formData.get('status') ?? 'pending') as PostStatus;
|
|
cms.posts = cms.posts.map((post) => (
|
|
post.slug === slug ? { ...post, status } : post
|
|
));
|
|
}
|
|
|
|
if (action === 'toggle-post-flag') {
|
|
const slug = String(formData.get('slug') ?? '');
|
|
const flag = String(formData.get('flag') ?? '');
|
|
|
|
cms.posts = cms.posts.map((post) => {
|
|
if (post.slug !== slug) {
|
|
return post;
|
|
}
|
|
|
|
if (flag === 'urgent') {
|
|
return { ...post, urgent: !post.urgent };
|
|
}
|
|
|
|
if (flag === 'sidebar') {
|
|
return { ...post, sidebar: !post.sidebar };
|
|
}
|
|
|
|
return post;
|
|
});
|
|
}
|
|
|
|
if (action === 'set-breaking-post') {
|
|
const slug = String(formData.get('slug') ?? '');
|
|
const post = cms.posts.find((item) => item.slug === slug);
|
|
|
|
if (post) {
|
|
cms.settings.breakingNews = {
|
|
...cms.settings.breakingNews,
|
|
href: `/posts/${post.slug}/`,
|
|
items: [post.title],
|
|
postSlugs: [post.slug],
|
|
};
|
|
}
|
|
}
|
|
|
|
if (action === 'set-home-featured') {
|
|
const slug = String(formData.get('slug') ?? '');
|
|
cms.settings.homeLayout.featuredSlug = slug;
|
|
}
|
|
|
|
if (action === 'clear-tass-memory') {
|
|
cms.settings.agents = {
|
|
...cms.settings.agents,
|
|
tass: { processedLinks: [] },
|
|
};
|
|
}
|
|
|
|
if (action === 'fill-tass-memory') {
|
|
const links = cms.posts
|
|
.map((post) => post.sourceUrl)
|
|
.filter(Boolean) as string[];
|
|
const feedLinks = await getTassFeedLinks(50);
|
|
cms.settings.agents = {
|
|
...cms.settings.agents,
|
|
tass: { processedLinks: Array.from(new Set([...links, ...feedLinks])) },
|
|
};
|
|
}
|
|
|
|
if (action === 'delete-post') {
|
|
const slug = String(formData.get('slug') ?? '');
|
|
const confirm = String(formData.get('confirm') ?? '');
|
|
|
|
if (confirm !== 'confirm') {
|
|
return context.redirect(`/admin/?deleteError=1&tab=${encodeURIComponent(tab)}`, 302);
|
|
}
|
|
|
|
cms.posts = cms.posts.filter((post) => post.slug !== slug);
|
|
}
|
|
|
|
if (action === 'delete-all-posts') {
|
|
const confirm = String(formData.get('confirm') ?? '');
|
|
|
|
if (confirm !== 'confirm') {
|
|
return context.redirect(`/admin/?deleteError=1&tab=${encodeURIComponent(tab)}`, 302);
|
|
}
|
|
|
|
cms.posts = [];
|
|
}
|
|
|
|
if (action === 'save-post') {
|
|
const originalSlug = String(formData.get('originalSlug') ?? '');
|
|
const title = String(formData.get('title') ?? '').trim();
|
|
const post = await publishPost({
|
|
slug: String(formData.get('slug') ?? '') || title,
|
|
title,
|
|
category: String(formData.get('category') ?? cms.categories[0] ?? 'عمومی'),
|
|
time: String(formData.get('time') ?? '').trim() || 'هماکنون',
|
|
readTime: String(formData.get('readTime') ?? '').trim() || '۳ دقیقه',
|
|
excerpt: String(formData.get('excerpt') ?? '').trim(),
|
|
status: String(formData.get('status') ?? 'pending') as PostStatus,
|
|
body: toParagraphs(formData.get('body')),
|
|
image: String(formData.get('image') ?? '').trim() || undefined,
|
|
thumbnail: String(formData.get('thumbnail') ?? '').trim() || undefined,
|
|
urgent: formData.get('urgent') === 'on',
|
|
sidebar: formData.get('sidebar') === 'on',
|
|
});
|
|
|
|
if (originalSlug && originalSlug !== post.slug) {
|
|
const updatedCms = await readCms();
|
|
updatedCms.posts = updatedCms.posts.filter((post) => post.slug !== originalSlug);
|
|
await writeCms(updatedCms);
|
|
}
|
|
|
|
return context.redirect(`/admin/?saved=1&tab=${post.status === 'approved' ? 'approved' : 'pending'}`, 302);
|
|
}
|
|
|
|
if (action === 'categories') {
|
|
cms.categories = toList(formData.get('categories'));
|
|
}
|
|
|
|
if (action === 'settings') {
|
|
cms.settings.breakingNews = {
|
|
label: String(formData.get('breakingLabel') ?? 'فوری').trim(),
|
|
href: String(formData.get('breakingHref') ?? '/').trim(),
|
|
items: toList(formData.get('breakingItems')),
|
|
postSlugs: toList(formData.get('breakingPostSlugs')),
|
|
};
|
|
cms.settings.hotTopics = toList(formData.get('hotTopics'));
|
|
cms.settings.homeLayout = {
|
|
featuredSlug: String(formData.get('featuredSlug') ?? '').trim(),
|
|
sideFeaturedSlugs: toList(formData.get('sideFeaturedSlugs')).slice(0, 2),
|
|
latestCount: Math.max(1, Number(formData.get('latestCount') ?? 4)),
|
|
showAd: formData.get('showAd') === 'on',
|
|
};
|
|
cms.settings.ad = {
|
|
enabled: formData.get('adEnabled') === 'on',
|
|
label: String(formData.get('adLabel') ?? 'آگهی').trim(),
|
|
href: String(formData.get('adHref') ?? '/advertise/').trim(),
|
|
text: String(formData.get('adText') ?? '').trim(),
|
|
};
|
|
}
|
|
|
|
await writeCms(cms);
|
|
|
|
return context.redirect(`/admin/?saved=1&tab=${encodeURIComponent(tab)}`, 302);
|
|
};
|