Add automatic Threads link replies and sunrise preview card

This commit is contained in:
2026-11-02 04:46:17 +09:00
parent 39374cea05
commit 586e59608e
12 changed files with 168 additions and 8 deletions
+9 -2
View File
@@ -6,6 +6,7 @@ import { THREADS } from '../../src/constants/threads.ts';
type Condition = typeof THREADS.captionConditions[number];
export interface Captions {
template: string[];
replyTemplate?: string[];
testPrefix: string;
thresholds: { fogVisibilityMeters: number; cloudyPercent: number; partlyCloudyPercent: number };
messages: Record<Condition, string[]>;
@@ -22,6 +23,7 @@ export function loadCaptions(path: string | URL = new URL('../../.threads-captio
try { config = JSON.parse(text); } catch { throw new Error('Invalid JSON in .threads-captions.json'); }
const lines = (value: unknown): value is string[] => Array.isArray(value) && value.length > 0 && value.every(line => typeof line === 'string');
if (!config || !lines(config.template) || typeof config.testPrefix !== 'string'
|| (config.replyTemplate !== undefined && !lines(config.replyTemplate))
|| !THREADS.captionConditions.every(key => lines(config.messages?.[key]))) throw new Error('Invalid caption template or weather messages');
const t = config.thresholds;
if (!t || !Number.isFinite(t.fogVisibilityMeters) || t.fogVisibilityMeters < 0
@@ -53,10 +55,15 @@ export function renderCaption(config: Captions, capture: {
dateDots: kstFields(date).date.replaceAll('-', '.'), hostname: new URL(capture.url).hostname,
time: kstClock(date).slice(0, 5), sunrise: kstClock(new Date(capture.sunrise)).slice(0, 5), url: capture.url,
};
const text = (capture.test ? config.testPrefix : '') + config.template.join('\n').replace(/\{(\w+)\}/g, (_, key: string) => {
const expand = (lines: string[]) => lines.join('\n').replace(/\{(\w+)\}/g, (_, key: string) => {
if (!(key in values)) throw new Error(`Unknown caption placeholder: ${key}`);
return values[key];
});
const text = (capture.test ? config.testPrefix : '') + expand(config.template);
const replyText = config.replyTemplate ? expand(config.replyTemplate) : undefined;
if (!text.trim() || [...text].length > THREADS.captionMaxLength) throw new Error('Caption must contain 1–500 characters');
return { text, condition };
if (replyText !== undefined && (!replyText.trim() || [...replyText].length > THREADS.captionMaxLength)) {
throw new Error('Reply must contain 1–500 characters');
}
return { text, condition, replyText };
}