v2.1.0
This commit is contained in:
parent
93b1c5e1b3
commit
6c4f5f799e
5 changed files with 416 additions and 11 deletions
28
app/index.ts
28
app/index.ts
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Discord } from "./lib/discord";
|
||||||
import { CreateImage } from "./lib/image";
|
import { CreateImage } from "./lib/image";
|
||||||
import { Login, Upload } from "./lib/instagram";
|
import { Login, Upload } from "./lib/instagram";
|
||||||
|
|
||||||
|
|
@ -29,6 +30,7 @@ async function main() {
|
||||||
const tomorrow = new Date();
|
const tomorrow = new Date();
|
||||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
YYMMDD = tomorrow.toISOString().slice(0, 10).replace(/-/g, "").toString();
|
YYMMDD = tomorrow.toISOString().slice(0, 10).replace(/-/g, "").toString();
|
||||||
|
YYMMDD = "20250602";
|
||||||
|
|
||||||
console.log("📅 | date:", YYMMDD);
|
console.log("📅 | date:", YYMMDD);
|
||||||
|
|
||||||
|
|
@ -51,7 +53,7 @@ async function main() {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
console.time("📷 | Create Post Image");
|
console.time("📷 | Create Post Image");
|
||||||
await CreateImage.PostMeal(YYMMDD);
|
const NutritionInfo = await CreateImage.PostMeal(YYMMDD);
|
||||||
console.timeEnd("📷 | Create Post Image");
|
console.timeEnd("📷 | Create Post Image");
|
||||||
|
|
||||||
console.time("📱 | Create Story Image");
|
console.time("📱 | Create Story Image");
|
||||||
|
|
@ -59,15 +61,37 @@ async function main() {
|
||||||
console.timeEnd("📱 | Create Story Image");
|
console.timeEnd("📱 | Create Story Image");
|
||||||
|
|
||||||
console.time("📤 | Upload Post");
|
console.time("📤 | Upload Post");
|
||||||
|
|
||||||
|
let NutritionInfoText = ""
|
||||||
|
|
||||||
|
const entries = Object.entries(NutritionInfo ?? {}).filter(([_, value]) => value.toString().length > 0);
|
||||||
|
entries.forEach(([name, value], idx) => {
|
||||||
|
NutritionInfoText += `${name} : ${value.toString().replace(",", ", ")}`;
|
||||||
|
if (idx !== entries.length - 1) {
|
||||||
|
NutritionInfoText += "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await Upload.Post(
|
await Upload.Post(
|
||||||
`./temp/${YYMMDD}.png`,
|
`./temp/${YYMMDD}.png`,
|
||||||
`#인천상정중학교 #상정중학교 #급식 \n${YYMMDD}일자 급식`
|
[
|
||||||
|
`🍽️ | ${YYMMDD}일자 급식`,
|
||||||
|
"===========================",
|
||||||
|
"⚠️ 알레르기 유발 가능 성분이 포함되어 있습니다.",
|
||||||
|
NutritionInfoText,
|
||||||
|
"===========================",
|
||||||
|
"#인천상정중학교 #상정중학교 #급식"
|
||||||
|
].join("\n")
|
||||||
);
|
);
|
||||||
console.timeEnd("📤 | Upload Post");
|
console.timeEnd("📤 | Upload Post");
|
||||||
|
|
||||||
console.time("📤 | Upload Story");
|
console.time("📤 | Upload Story");
|
||||||
await Upload.Story(`./temp/${YYMMDD}-story.png`, YYMMDD);
|
await Upload.Story(`./temp/${YYMMDD}-story.png`, YYMMDD);
|
||||||
console.timeEnd("📤 | Upload Story");
|
console.timeEnd("📤 | Upload Story");
|
||||||
|
|
||||||
|
console.time("🤖 | Discord Webhook");
|
||||||
|
await Discord(YYMMDD);
|
||||||
|
console.timeEnd("🤖 | Discord Webhook");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("❌ | Error during image creation or upload:", error);
|
console.error("❌ | Error during image creation or upload:", error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { join } from "path";
|
import { join } from "path";
|
||||||
import { createCanvas, loadImage, GlobalFonts } from "@napi-rs/canvas";
|
import { createCanvas, loadImage, GlobalFonts } from "@napi-rs/canvas";
|
||||||
import { getMealInfo, NameToEmoji } from "./meal"; // 이 함수의 내용은 제공되지 않았으므로 그대로 둡니다.
|
import { getMealInfo, getNutritionInfo, NameToEmoji, removeNutritionInfo } from "./meal"; // 이 함수의 내용은 제공되지 않았으므로 그대로 둡니다.
|
||||||
import { getAllSchedules } from "./schedule";
|
import { getAllSchedules } from "./schedule";
|
||||||
import { isVTS } from "./vts";
|
import { isVTS } from "./vts";
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ GlobalFonts.registerFromPath('./template/Pretendard-Bold.ttf', 'Pretendard Bold'
|
||||||
GlobalFonts.registerFromPath('./template/NotoColorEmoji-Regular.ttf', 'NotoColorEmoji Regular')
|
GlobalFonts.registerFromPath('./template/NotoColorEmoji-Regular.ttf', 'NotoColorEmoji Regular')
|
||||||
|
|
||||||
export class CreateImage {
|
export class CreateImage {
|
||||||
static async PostMeal(MLSV_YMD: string): Promise<void> {
|
static async PostMeal(MLSV_YMD: string): Promise<{ [key: string]: any } | undefined> {
|
||||||
const mealInfo = await getMealInfo(MLSV_YMD);
|
const mealInfo = await getMealInfo(MLSV_YMD);
|
||||||
const img = await loadImage(path.join("./template/skeleton.png"));
|
const img = await loadImage(path.join("./template/skeleton.png"));
|
||||||
const canvas = createCanvas(img.width, img.height);
|
const canvas = createCanvas(img.width, img.height);
|
||||||
|
|
@ -20,7 +20,7 @@ export class CreateImage {
|
||||||
ctx.fillStyle = "white";
|
ctx.fillStyle = "white";
|
||||||
ctx.textAlign = "left";
|
ctx.textAlign = "left";
|
||||||
|
|
||||||
const lines = mealInfo.meal.split("\n").reverse();
|
const lines = removeNutritionInfo(mealInfo.meal).split("\n").reverse();
|
||||||
let emojis = (await NameToEmoji(lines.toString())).split(",");
|
let emojis = (await NameToEmoji(lines.toString())).split(",");
|
||||||
|
|
||||||
if (lines.length !== emojis.length) {
|
if (lines.length !== emojis.length) {
|
||||||
|
|
@ -65,6 +65,16 @@ export class CreateImage {
|
||||||
console.log("🍲 | Meal Info Image Saved");
|
console.log("🍲 | Meal Info Image Saved");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error saving meal info image:", error);
|
console.error("Error saving meal info image:", error);
|
||||||
|
} finally {
|
||||||
|
const meals = removeNutritionInfo(mealInfo.meal).split("\n");
|
||||||
|
const nutritionInfo = getNutritionInfo(mealInfo.meal);
|
||||||
|
const retrunValue: { [key: string]: any } = {};
|
||||||
|
for (let i = 0; i < meals.length; i++) {
|
||||||
|
const meal = (meals[i] ?? "").trim();
|
||||||
|
retrunValue[meal] = nutritionInfo[i] || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return retrunValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,31 @@ const KEY = process.env.NEIS_API_KEY;
|
||||||
|
|
||||||
export function removeNutritionInfo(value: string): string {
|
export function removeNutritionInfo(value: string): string {
|
||||||
const lines = value.trim().split('\n');
|
const lines = value.trim().split('\n');
|
||||||
const cleanedLines = lines.map(line => line.replace(/\(.*?\)/g, '').trim());
|
const cleanedLines = lines.map(line => line.replace(/\s*\([\d.,]+\)/g, '').trim());
|
||||||
const result = cleanedLines.join('\n');
|
const result = cleanedLines.join('\n');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nutritionList = [
|
||||||
|
"난류", "우유", "메밀", "땅콩", "대두", "밀", "고등어", "게", "새우", "돼지고기",
|
||||||
|
"복숭아", "토마토", "아황산류", "호두", "닭고기", "쇠고기", "오징어", "조개류(굴, 전복, 홍합 포함)", "잣"
|
||||||
|
];
|
||||||
|
|
||||||
|
export function getNutritionInfo(value: string): string[][] {
|
||||||
|
const lines = value.trim().split('\n');
|
||||||
|
return lines.map(line => {
|
||||||
|
const indexes = line
|
||||||
|
.replace(/[()\s]/g, "")
|
||||||
|
.split(".")
|
||||||
|
.map(v => parseInt(v, 10) - 1)
|
||||||
|
.filter(i => i >= 0 && i < nutritionList.length);
|
||||||
|
return indexes
|
||||||
|
.map(i => nutritionList[i])
|
||||||
|
.filter((item): item is string => typeof item === "string");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function getMealInfo(MLSV_YMD: string): Promise<{ meal: string; date: string, kcal: string }> {
|
export async function getMealInfo(MLSV_YMD: string): Promise<{ meal: string; date: string, kcal: string }> {
|
||||||
const url = `https://open.neis.go.kr/hub/mealServiceDietInfo?Type=json&ATPT_OFCDC_SC_CODE=E10&SD_SCHUL_CODE=7331071&MLSV_YMD=${MLSV_YMD}&KEY=${KEY}`;
|
const url = `https://open.neis.go.kr/hub/mealServiceDietInfo?Type=json&ATPT_OFCDC_SC_CODE=E10&SD_SCHUL_CODE=7331071&MLSV_YMD=${MLSV_YMD}&KEY=${KEY}`;
|
||||||
const response = await fetch(url);
|
const response = await fetch(url);
|
||||||
|
|
@ -17,7 +37,7 @@ export async function getMealInfo(MLSV_YMD: string): Promise<{ meal: string; dat
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const DDISH_NM = data.mealServiceDietInfo[1].row[0].DDISH_NM;
|
const DDISH_NM = data.mealServiceDietInfo[1].row[0].DDISH_NM;
|
||||||
return {
|
return {
|
||||||
meal: removeNutritionInfo(DDISH_NM.replace(/<br\s*\/?>/gi, '\n')),
|
meal: DDISH_NM.replace(/<br\s*\/?>/gi, '\n'),
|
||||||
date: MLSV_YMD,
|
date: MLSV_YMD,
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
||||||
|
|
@ -32,7 +52,7 @@ export async function NameToEmoji(name: string): Promise<string> {
|
||||||
throw new Error("GITHUB_TOKEN environment variable is not set.");
|
throw new Error("GITHUB_TOKEN environment variable is not set.");
|
||||||
}
|
}
|
||||||
const endpoint = "https://models.github.ai/inference";
|
const endpoint = "https://models.github.ai/inference";
|
||||||
const model = "openai/gpt-4.1";
|
const model = "openai/gpt-4.1-mini";
|
||||||
|
|
||||||
const client = ModelClient(
|
const client = ModelClient(
|
||||||
endpoint,
|
endpoint,
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,24 @@
|
||||||
import { CreateImage } from "./lib/image";
|
import { CreateImage } from "./lib/image";
|
||||||
|
|
||||||
//const YYMMDD = new Date().toISOString().slice(0, 10).replace(/-/g, "").toString();
|
//const YYMMDD = new Date().toISOString().slice(0, 10).replace(/-/g, "").toString();
|
||||||
const YYMMDD = "20250509"
|
const YYMMDD = "20250530"
|
||||||
//console.log(YYMMDD);
|
//console.log(YYMMDD);
|
||||||
|
|
||||||
//Discord("20250509")
|
//Discord("20250509")
|
||||||
async function run() {
|
async function run() {
|
||||||
console.time("Post");
|
console.time("Post");
|
||||||
await CreateImage.PostMeal(YYMMDD);
|
const post = await CreateImage.PostMeal(YYMMDD);
|
||||||
console.timeEnd("Post");
|
console.timeEnd("Post");
|
||||||
|
console.log("Post created:", post);
|
||||||
|
let NutritionInfoText = "";
|
||||||
|
const entries = Object.entries(post ?? {}).filter(([_, value]) => value.toString().length > 0);
|
||||||
|
entries.forEach(([name, value], idx) => {
|
||||||
|
NutritionInfoText += `${name} : ${value.toString().replace(",", ", ")}`;
|
||||||
|
if (idx !== entries.length - 1) {
|
||||||
|
NutritionInfoText += "\n";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("Nutrition Info Text:", NutritionInfoText);
|
||||||
|
|
||||||
console.time("Story");
|
console.time("Story");
|
||||||
await CreateImage.ConvertToStory(`./temp/${YYMMDD}.png`);
|
await CreateImage.ConvertToStory(`./temp/${YYMMDD}.png`);
|
||||||
|
|
@ -18,6 +28,8 @@ async function run() {
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
|
||||||
|
import { getAllSchedules } from "./lib/schedule";
|
||||||
|
|
||||||
|
|
||||||
//import { CreateImage } from "./lib/image";
|
//import { CreateImage } from "./lib/image";
|
||||||
|
|
||||||
|
|
@ -40,3 +52,12 @@ VTSList().then(results => {
|
||||||
console.log("\n5번째 행에서 노란색 배경의 셀을 찾지 못했거나, 'V.T.S.' 조건 불충족.");
|
console.log("\n5번째 행에서 노란색 배경의 셀을 찾지 못했거나, 'V.T.S.' 조건 불충족.");
|
||||||
}
|
}
|
||||||
});*/
|
});*/
|
||||||
|
/*
|
||||||
|
getAllSchedules()
|
||||||
|
.then((schedules) => {
|
||||||
|
console.log("학사 일정:", schedules);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error fetching schedules:", error);
|
||||||
|
});
|
||||||
|
*/
|
||||||
330
temp.ics
Normal file
330
temp.ics
Normal file
|
|
@ -0,0 +1,330 @@
|
||||||
|
BEGIN:VCALENDAR
|
||||||
|
VERSION:2.0
|
||||||
|
PRODID:-//Google Inc//Google Calendar 70.9054//EN
|
||||||
|
CALSCALE:GREGORIAN
|
||||||
|
METHOD:PUBLISH
|
||||||
|
X-WR-CALNAME:2025년 학사일정
|
||||||
|
X-WR-TIMEZONE:Asia/Seoul
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250301
|
||||||
|
DTEND;VALUE=DATE:20250302
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250301-삼일절@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:삼일절
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250304
|
||||||
|
DTEND;VALUE=DATE:20250305
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250304-입학식@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:입학식
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250305
|
||||||
|
DTEND;VALUE=DATE:20250306
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250305-창체-봉사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체/봉사
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250312
|
||||||
|
DTEND;VALUE=DATE:20250313
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250312-창체@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250313
|
||||||
|
DTEND;VALUE=DATE:20250314
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250313-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250317
|
||||||
|
DTEND;VALUE=DATE:20250318
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250317-학부모총회@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:학부모총회
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250320
|
||||||
|
DTEND;VALUE=DATE:20250321
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250320-기초학력진단검사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:기초학력진단검사
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250326
|
||||||
|
DTEND;VALUE=DATE:20250327
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250326-1학기-방과후학교-시작@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:1학기 방과후학교 시작
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250331
|
||||||
|
DTEND;VALUE=DATE:20250401
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250331-창체-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체/동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250430
|
||||||
|
DTEND;VALUE=DATE:20250502
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250430-1학기-1회고사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:1학기 1회고사(2,3학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250506
|
||||||
|
DTEND;VALUE=DATE:20250507
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250506-대체휴일@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:대체휴일
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250509
|
||||||
|
DTEND;VALUE=DATE:20250510
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250509-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250513
|
||||||
|
DTEND;VALUE=DATE:20250514
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250513-리더십캠프@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:리더십캠프
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250516
|
||||||
|
DTEND;VALUE=DATE:20250517
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250516-스포츠대축제@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:스포츠대축제
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250521
|
||||||
|
DTEND;VALUE=DATE:20250522
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250521-진로체험활동@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:진로체험활동(3학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250523
|
||||||
|
DTEND;VALUE=DATE:20250524
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250523-진로체험활동@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:진로체험활동(1,2학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250530
|
||||||
|
DTEND;VALUE=DATE:20250531
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250530-창체-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체/동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250604
|
||||||
|
DTEND;VALUE=DATE:20250605
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250604-교과연계-체험학습@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:교과연계 체험학습(2학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250605
|
||||||
|
DTEND;VALUE=DATE:20250606
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250605-재량휴업일@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:재량휴업일
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250627
|
||||||
|
DTEND;VALUE=DATE:20250628
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250627-1학기-방과후학교-종강@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:1학기 방과후학교 종강
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250707
|
||||||
|
DTEND;VALUE=DATE:20250710
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250707-1학기-2회고사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:1학기 2회고사(2,3학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250721
|
||||||
|
DTEND;VALUE=DATE:20250722
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250721-1학년-건강검진@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:1학년 건강검진
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250722
|
||||||
|
DTEND;VALUE=DATE:20250723
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250722-방학식@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:방학식
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250723
|
||||||
|
DTEND;VALUE=DATE:20250812
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250723-여름방학@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:여름방학
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250812
|
||||||
|
DTEND;VALUE=DATE:20250813
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250812-개학식@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:개학식
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250827
|
||||||
|
DTEND;VALUE=DATE:20250828
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250827-2학기-방과후학교-시작@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:2학기 방과후학교 시작
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250903
|
||||||
|
DTEND;VALUE=DATE:20250904
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250903-학부모-공개수업@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:학부모 공개수업
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250925
|
||||||
|
DTEND;VALUE=DATE:20250926
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250925-진로체험활동@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:진로체험활동
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20250926
|
||||||
|
DTEND;VALUE=DATE:20250927
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20250926-창체-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체/동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251010
|
||||||
|
DTEND;VALUE=DATE:20251011
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251010-재량휴업일@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:재량휴업일
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251016
|
||||||
|
DTEND;VALUE=DATE:20251018
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251016-2학기-1회고사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:2학기 1회고사(1,2학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251020
|
||||||
|
DTEND;VALUE=DATE:20251021
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251020-창체@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251029
|
||||||
|
DTEND;VALUE=DATE:20251101
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251029-2학기-1회고사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:2학기 1회고사(3학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251104
|
||||||
|
DTEND;VALUE=DATE:20251105
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251104-스포츠-클럽데이@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:스포츠 클럽데이(1,2학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251107
|
||||||
|
DTEND;VALUE=DATE:20251108
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251107-스포츠-클럽데이@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:스포츠 클럽데이(3학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251113
|
||||||
|
DTEND;VALUE=DATE:20251114
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251113-재량휴업일@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:재량휴업일
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251114
|
||||||
|
DTEND;VALUE=DATE:20251115
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251114-개교기념일@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:개교기념일
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251120
|
||||||
|
DTEND;VALUE=DATE:20251121
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251120-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251121
|
||||||
|
DTEND;VALUE=DATE:20251122
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251121-샘소슬제@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:샘소슬제
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251128
|
||||||
|
DTEND;VALUE=DATE:20251129
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251128-동아리@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:동아리
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251205
|
||||||
|
DTEND;VALUE=DATE:20251206
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251205-2학기-방과후학교-종강@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:2학기 방과후학교 종강
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251206
|
||||||
|
DTEND;VALUE=DATE:20251207
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251206-상정-소통의-날@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:상정 소통의 날
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251216
|
||||||
|
DTEND;VALUE=DATE:20251219
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251216-2학기-2회고사@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:2학기 2회고사(1,2학년)
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20251224
|
||||||
|
DTEND;VALUE=DATE:20251225
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20251224-창체@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:창체
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20260107
|
||||||
|
DTEND;VALUE=DATE:20260108
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20260107-종업식-및-졸업식@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:종업식 및 졸업식
|
||||||
|
END:VEVENT
|
||||||
|
BEGIN:VEVENT
|
||||||
|
DTSTART;VALUE=DATE:20260108
|
||||||
|
DTEND;VALUE=DATE:20260228
|
||||||
|
DTSTAMP:20250514T115950Z
|
||||||
|
UID:20260108-겨울방학@today.isangjeong@al-1s.kr
|
||||||
|
SUMMARY:겨울방학
|
||||||
|
END:VEVENT
|
||||||
|
END:VCALENDAR
|
||||||
Loading…
Add table
Add a link
Reference in a new issue