// これからの予定のRSSフィード(/kodaira/events/feed.xml)。
// ビルド時点の日付以降に開催される予定を、開催日の早い順に最大60件出力する。
import type { APIRoute } from 'astro';
import { items } from '@/lib/schedule-months';
import { entryDates } from '@/lib/schedule-dates';
import { SCHEDULE_BASE_PATH, SITE_URL } from '@/data/schedule/config';
const stripTags = (value: string) =>
value
.replace(/<[^>]*>/g, '')
.replace(/ /g, ' ')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, "'")
.replace(/\s+/g, ' ')
.trim();
const escapeXml = (value: string) =>
value
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
const pad = (n: number) => String(n).padStart(2, '0');
const now = new Date();
const todayKey = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
const toRfc822 = (date: string) => new Date(`${date}T00:00:00+09:00`).toUTCString();
const entries = items
.map((item) => {
const dates = entryDates(item.type, item.row.date, item.row.place);
return { item, upcoming: dates.filter((date) => date >= todayKey) };
})
.filter(({ upcoming }) => upcoming.length > 0)
.sort((a, b) => a.upcoming[0].localeCompare(b.upcoming[0]))
.slice(0, 60);
const itemXml = ({ item: { type, row }, upcoming }: (typeof entries)[number]) => {
const title = stripTags(row.title);
const description = [stripTags(row.place), stripTags(row.note)].filter(Boolean).join('/');
const datesLabel = upcoming
.map((date) => `${Number(date.slice(5, 7))}月${Number(date.slice(8, 10))}日`)
.join('、');
const link = `${SITE_URL}${SCHEDULE_BASE_PATH}`;
const guid = `${SITE_URL}${SCHEDULE_BASE_PATH}#${type}-${upcoming[0]}-${encodeURIComponent(title)}`;
return ` -
${escapeXml(title)}
${escapeXml(link)}
${escapeXml(guid)}
${type === 'meeting' ? '審議会等・市議会' : 'イベント'}
${toRfc822(upcoming[0])}
${escapeXml(`開催日:${datesLabel}${description ? `/${description}` : ''}`)}
`;
};
export const GET: APIRoute = () => {
const xml = `
小平市のイベント・行事予定(審議会・市議会の日程も掲載)
${SITE_URL}${SCHEDULE_BASE_PATH}
小平市のイベントと、審議会等・市議会の開催予定です。市報こだいら・市公式X・LoGoフォーム・市議会の行事予定表などをもとにまとめています。
ja
${now.toUTCString()}
${entries.map(itemXml).join('\n')}
`;
return new Response(xml, {
headers: { 'Content-Type': 'application/rss+xml; charset=utf-8' },
});
};