/***** 설정 *****/
const CAL_NAME = 'EXAM NAME💻'; // 전용 캘린더 이름
const EVENT_TITLE = '✅Todo List'; // 매일 생성할 종일 이벤트 제목
const LOG_SHEET_NAME = 'List Script Log'; // 실행 로그를 쓸 구글 스프레드시트 이름
/***** 공통: 주말 유틸 *****/
function isWeekend_(date = todayDate_()) {
const d = date.getDay(); // 0=Sun, 6=Sat
return d === 0 || d === 6;
}
function getOrCreateLogSheet_() {
const files = DriveApp.getFilesByName(LOG_SHEET_NAME);
let ss;
if (files.hasNext()) {
ss = SpreadsheetApp.open(files.next());
} else {
ss = SpreadsheetApp.create(LOG_SHEET_NAME);
}
const sheet = ss.getActiveSheet();
const first = sheet.getRange(1, 1).getValue();
if (!first) {
sheet.appendRow(['Timestamp', 'Function', 'Status', 'Message']);
}
return sheet;
}
function log_(fn, status, message) {
const tz = Session.getScriptTimeZone();
const ts = Utilities.formatDate(new Date(), tz, 'yyyy-MM-dd HH:mm:ss');
try {
const sheet = getOrCreateLogSheet_();
sheet.appendRow([ts, fn, status, message || '']);
} catch (e) {
console.warn('Log write failed:', e);
}
}
/***** 캘린더/날짜 유틸 (기존 동일) *****/
function getCal_() {
const cals = CalendarApp.getCalendarsByName(CAL_NAME);
return cals[0] || CalendarApp.getDefaultCalendar();
}
function todayDate_(tz = Session.getScriptTimeZone()) {
const now = new Date();
return new Date(
Utilities.formatDate(now, tz, 'yyyy'),
Number(Utilities.formatDate(now, tz, 'M')) - 1,
Utilities.formatDate(now, tz, 'd')
);
}
function defaultTemplate_() {
return [
'🕐 오전',
'- ',
'',
'🌇 오후',
'- ',
'',
'📝 메모',
'- '
].join('\n');
}
function getTodayLogEvent_(cal) {
const today = todayDate_();
const events = cal.getEventsForDay(today);
return events.find(e => e.isAllDayEvent() && e.getTitle() === EVENT_TITLE) || null;
}
/***** 1) 매일 0시에 템플릿 이벤트 생성 (주말 스킵 추가) *****/
function createDailyLogEvent() {
const fn = 'createDailyLogEvent';
try {
const cal = getCal_();
const today = todayDate_();
// ⛔ 주말에는 생성 스킵
if (isWeekend_(today)) {
log_(fn, 'SKIP', 'Weekend — no event created');
return;
}
const existing = getTodayLogEvent_(cal);
if (existing) {
log_(fn, 'SKIP', 'Already exists for today');
return;
}
const ev = cal.createAllDayEvent(EVENT_TITLE, today);
ev.setDescription(defaultTemplate_());
log_(fn, 'OK', 'Created all-day event with template');
} catch (e) {
log_(fn, 'ERROR', String(e && e.stack ? e.stack : e));
throw e;
}
}
/***** 2) 한 줄 추가 (주말엔 기본적으로 스킵, force로 강제 가능) *****/
function addLogItem(text = '작업 내용 예시', force = false) {
const fn = 'addLogItem';
try {
const cal = getCal_();
const today = todayDate_();
let ev = getTodayLogEvent_(cal);
// 주말 + 이벤트 없음 → 기본 스킵 (force=true면 생성해서 기록)
if (!ev) {
if (isWeekend_(today) && !force) {
log_(fn, 'SKIP', 'Weekend with no event (use force to override)');
return;
}
createDailyLogEvent(); // createDailyLogEvent도 주말 가드가 있으니 force일 때만 효과
ev = getTodayLogEvent_(cal);
if (!ev) {
// 주말인데 force=false로 호출된 경우 등
log_(fn, 'SKIP', 'No event available');
return;
}
}
const tz = Session.getScriptTimeZone();
const now = new Date();
const hhmm = Utilities.formatDate(now, tz, 'HH:mm');
let desc = ev.getDescription() || defaultTemplate_();
const line = `- ${hhmm} ${text}`;
if (now.getHours() < 12) {
const pattern = /(🕐 오전[\s\S]*?)(\n\n🌇 오후)/;
if (pattern.test(desc)) {
desc = desc.replace(pattern, (_, p1, p2) => `${p1}\n${line}${p2}`);
} else {
desc = `🕐 오전\n${line}\n\n🌇 오후\n- \n\n📝 메모\n- `;
}
} else {
const pattern = /(🌇 오후[\s\S]*?)(\n\n📝 메모)/;
if (pattern.test(desc)) {
desc = desc.replace(pattern, (_, p1, p2) => `${p1}\n${line}${p2}`);
} else {
desc = `🕐 오전\n- \n\n🌇 오후\n${line}\n\n📝 메모\n- `;
}
}
ev.setDescription(desc);
log_(fn, 'OK', `Added: ${text}${isWeekend_(today) ? ' (forced on weekend)' : ''}`);
} catch (e) {
log_(fn, 'ERROR', String(e && e.stack ? e.stack : e));
throw e;
}
}
/***** 3) 웹앱 — URL?text=내용[&force=1] *****/
function doGet(e) {
const fn = 'doGet';
try {
const text = e && e.parameter && e.parameter.text;
const forceParam = e && e.parameter && e.parameter.force;
const force = forceParam === '1' || String(forceParam).toLowerCase() === 'true';
if (text) {
addLogItem(text, force);
log_(fn, 'OK', `text="${text}"${force ? ' (force)' : ''}`);
return ContentService.createTextOutput('OK');
}
log_(fn, 'SKIP', 'NO_TEXT');
return ContentService.createTextOutput('NO_TEXT');
} catch (e2) {
log_(fn, 'ERROR', String(e2 && e2.stack ? e2.stack : e2));
return ContentService.createTextOutput('ERROR');
}
}
/***** 4) 수동 테스트/확인 (기존 동일) *****/
function testCreateNow() {
createDailyLogEvent();
}
function verifyToday() {
const fn = 'verifyToday';
try {
const cal = getCal_();
const ev = getTodayLogEvent_(cal);
if (!ev) {
log_(fn, 'NOT_FOUND', 'No event for today');
return '오늘 이벤트가 없습니다.';
}
const desc = ev.getDescription() || '';
const hasTemplate = /🕐 오전/.test(desc) && /🌇 오후/.test(desc);
const msg = `이벤트 존재 / 템플릿=${hasTemplate ? 'OK' : 'N/A'}`;
log_(fn, 'OK', msg);
return msg;
} catch (e) {
log_(fn, 'ERROR', String(e && e.stack ? e.stack : e));
throw e;
}
}
/***** 5) 트리거 (기존 동일) *****/
function setupTimeTrigger() {
const triggers = ScriptApp.getProjectTriggers();
triggers
.filter(t => t.getHandlerFunction() === 'createDailyLogEvent')
.forEach(t => ScriptApp.deleteTrigger(t));
ScriptApp.newTrigger('createDailyLogEvent')
.timeBased()
.atHour(0) // 00시대
.nearMinute(5) // 05분 근처
.everyDays(1)
.create();
log_('setupTimeTrigger', 'OK', 'Daily at 00:05 created');
}
https://code-soo.tistory.com/58
이전꺼는 그냥 매일매일 트리거가 걸리고 돌았다면...
work log용으로 사용하는거니 주말을 예외처리 한걸 추가해봄 !!