fix(scheduler): 봇 JSON 컬럼 파싱에 safeParse 가드 추가
깨진 JSON 값 하나가 getAllBots 전체를 throw시켜 startAll(전체 봇 기동)을 막던 위험 제거. weekly_schedule_config/title_filters/default_member_ids/ auto_schedule_config/text_filters를 safeParse(fallback)로 처리. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e16d3f1230
commit
6e559a52b7
1 changed files with 18 additions and 25 deletions
|
|
@ -20,6 +20,19 @@ function isActiveMonth(bot) {
|
|||
return months.includes(monthKST());
|
||||
}
|
||||
|
||||
/**
|
||||
* DB JSON 컬럼 안전 파싱. 깨진 값 하나가 getAllBots 전체를 막지 않도록 fallback 반환.
|
||||
*/
|
||||
function safeParse(value, fallback = null) {
|
||||
if (value == null) return fallback;
|
||||
if (typeof value !== 'string') return value;
|
||||
try {
|
||||
return JSON.parse(value);
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 에러 객체에서 활동 로그용 details 구성
|
||||
* - err.cause(Node fetch failed의 진짜 원인 등), err.code를 함께 포함
|
||||
|
|
@ -47,11 +60,7 @@ async function schedulerPlugin(fastify, opts) {
|
|||
'SELECT * FROM bot_youtube'
|
||||
);
|
||||
return rows.map(row => {
|
||||
const weekly = row.weekly_schedule_config
|
||||
? (typeof row.weekly_schedule_config === 'string'
|
||||
? JSON.parse(row.weekly_schedule_config)
|
||||
: row.weekly_schedule_config)
|
||||
: null;
|
||||
const weekly = safeParse(row.weekly_schedule_config, null);
|
||||
|
||||
// weekly 모드면 시작 시각에만 트리거, 아니면 cron_interval 분 주기
|
||||
let cronExpr;
|
||||
|
|
@ -72,23 +81,11 @@ async function schedulerPlugin(fastify, opts) {
|
|||
bannerUrl: row.banner_url,
|
||||
cron: cronExpr,
|
||||
enabled: row.enabled === 1,
|
||||
titleFilters: row.title_filters
|
||||
? (typeof row.title_filters === 'string'
|
||||
? JSON.parse(row.title_filters)
|
||||
: row.title_filters)
|
||||
: [],
|
||||
defaultMemberIds: row.default_member_ids
|
||||
? (typeof row.default_member_ids === 'string'
|
||||
? JSON.parse(row.default_member_ids)
|
||||
: row.default_member_ids)
|
||||
: [],
|
||||
titleFilters: safeParse(row.title_filters, []),
|
||||
defaultMemberIds: safeParse(row.default_member_ids, []),
|
||||
extractMembersFromDesc: row.extract_members_from_desc === 1,
|
||||
extractMembersFromTitle: row.extract_members_from_title === 1,
|
||||
autoScheduleNext: row.auto_schedule_config
|
||||
? (typeof row.auto_schedule_config === 'string'
|
||||
? JSON.parse(row.auto_schedule_config)
|
||||
: row.auto_schedule_config)
|
||||
: null,
|
||||
autoScheduleNext: safeParse(row.auto_schedule_config, null),
|
||||
weeklySchedule: weekly,
|
||||
};
|
||||
});
|
||||
|
|
@ -111,11 +108,7 @@ async function schedulerPlugin(fastify, opts) {
|
|||
nitterUrl: process.env.NITTER_URL || 'http://nitter:8080',
|
||||
cron: `*/${row.cron_interval} * * * *`,
|
||||
enabled: row.enabled === 1,
|
||||
textFilters: row.text_filters
|
||||
? (typeof row.text_filters === 'string'
|
||||
? JSON.parse(row.text_filters)
|
||||
: row.text_filters)
|
||||
: [],
|
||||
textFilters: safeParse(row.text_filters, []),
|
||||
includeRetweets: row.include_retweets === 1,
|
||||
extractYoutube: row.extract_youtube === 1,
|
||||
excludeManagedChannels: row.exclude_managed_channels === 1,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue