summaryrefslogtreecommitdiff
path: root/app/lib/markdown-writer.server.ts
diff options
context:
space:
mode:
Diffstat (limited to 'app/lib/markdown-writer.server.ts')
-rw-r--r--app/lib/markdown-writer.server.ts80
1 files changed, 80 insertions, 0 deletions
diff --git a/app/lib/markdown-writer.server.ts b/app/lib/markdown-writer.server.ts
new file mode 100644
index 0000000..cfef315
--- /dev/null
+++ b/app/lib/markdown-writer.server.ts
@@ -0,0 +1,80 @@
+/**
+ * Generates a Markdown summary file per venue after scraping.
+ * Files are written to events/<venue-id>.md in the project root.
+ */
+import fs from "fs";
+import path from "path";
+import { fileURLToPath } from "url";
+import { queryEvents } from "./db.server";
+import type { Event } from "./db.server";
+
+const ROOT = path.join(path.dirname(fileURLToPath(import.meta.url)), "../../");
+const EVENTS_DIR = path.join(ROOT, "events");
+
+export function generateVenueMarkdown(venueId: string): void {
+ const events = queryEvents({ venue_id: venueId, limit: 200 });
+ if (events.length === 0) return;
+
+ fs.mkdirSync(EVENTS_DIR, { recursive: true });
+
+ const venueName = events[0].venue_name;
+ const venueArea = events[0].venue_area ?? "";
+ const now = new Date().toISOString().slice(0, 10);
+
+ const lines: string[] = [
+ `# ${venueName}(${venueArea})イベント情報`,
+ ``,
+ `> 最終更新: ${now} `,
+ `> データソース: スクレイパー自動取得`,
+ ``,
+ `| 日付 | 出演者 | タイトル | 時間 | 料金 | URL |`,
+ `| ---- | ------ | -------- | ---- | ---- | --- |`,
+ ];
+
+ for (const ev of events) {
+ const date = formatDate(ev.date);
+ const artist = escape(ev.artist ?? "未定");
+ const title = escape(ev.title);
+ const time = buildTime(ev.open_time, ev.start_time);
+ const fee = escape(ev.price ?? "");
+ const url = ev.ticket_url
+ ? `[チケット](${ev.ticket_url})`
+ : ev.source_url
+ ? `[詳細](${ev.source_url})`
+ : "";
+
+ lines.push(`| ${date} | ${artist} | ${title} | ${time} | ${fee} | ${url} |`);
+ }
+
+ lines.push(``);
+ lines.push(`---`);
+ lines.push(`*このファイルは自動生成されます。手動編集は次回更新時に上書きされます。*`);
+ lines.push(``);
+
+ const filePath = path.join(EVENTS_DIR, `${venueId}.md`);
+ fs.writeFileSync(filePath, lines.join("\n"), "utf-8");
+}
+
+export function generateAllVenueMarkdown(venueIds: string[]): void {
+ for (const id of venueIds) {
+ generateVenueMarkdown(id);
+ }
+}
+
+function formatDate(iso: string): string {
+ const [y, m, d] = iso.split("-");
+ const days = ["日", "月", "火", "水", "木", "金", "土"];
+ const dayIdx = new Date(`${iso}T00:00:00`).getDay();
+ return `${y}/${m}/${d}(${days[dayIdx]})`;
+}
+
+function buildTime(open: string | null, start: string | null): string {
+ const parts: string[] = [];
+ if (open) parts.push(`OPEN ${open}`);
+ if (start) parts.push(`START ${start}`);
+ return parts.join(" / ") || "";
+}
+
+function escape(s: string): string {
+ return s.replace(/\|/g, "\\|").replace(/\n/g, " ");
+}