diff --git a/app/bun.lock b/app/bun.lock index 50d47a3..c32286d 100644 --- a/app/bun.lock +++ b/app/bun.lock @@ -6,7 +6,6 @@ "name": "app", "dependencies": { "@azure-rest/ai-inference": "^1.0.0-beta.6", - "@google/generative-ai": "^0.24.1", "@imnyang/comcigan.ts": "^0.3.0", }, "devDependencies": { @@ -36,8 +35,6 @@ "@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="], - "@google/generative-ai": ["@google/generative-ai@0.24.1", "", {}, "sha512-MqO+MLfM6kjxcKoy0p1wRzG3b4ZZXtPI+z2IE26UogS2Cm/XHO+7gGRBh6gcJsOiIVoH93UwKvW4HdgiOZCy9Q=="], - "@imnyang/comcigan.ts": ["@imnyang/comcigan.ts@0.3.0", "", { "dependencies": { "iconv-lite": "^0.6.3", "undici": "^6.23.0" } }, "sha512-IqOoqsrziSOZe0vUBvVjCysv8Ydz5uYBoSBiBtX3eopR2b+Em5W1C7mRJwrMa/9Tt2bgZxn30F3yq7w5yJzEdg=="], "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="], diff --git a/app/index.ts b/app/index.ts index 06d4fc1..f6bf9db 100644 --- a/app/index.ts +++ b/app/index.ts @@ -9,8 +9,7 @@ async function main() { const YYYY = now.getFullYear(); const MM = String(now.getMonth() + 1).padStart(2, '0'); const DD = String(now.getDate()).padStart(2, '0'); - // const YYMMDD = `${YYYY}${MM}${DD}`; - const YYMMDD = `20260403`; + const YYMMDD = `${YYYY}${MM}${DD}`; // getDay(): 일(0) ~ 토(6) // comcigan.ts 라이브러리 기준에 맞춰 weekday 설정 필요 diff --git a/app/lib/discord.ts b/app/lib/discord.ts index 0e61d74..28f153f 100644 --- a/app/lib/discord.ts +++ b/app/lib/discord.ts @@ -40,44 +40,22 @@ export async function Meal({ MLSV_YMD, ATPT_OFCDC_SC_CODE, SD_SCHUL_CODE, userna export async function Timetable({ schoolId, grade, classNum, weekday, WEBHOOK_URL }: { schoolId: number, grade: number, classNum: number, weekday: number, WEBHOOK_URL: string }) { - // 필수 값 검증: undefined/null 이면 전송 안 함 - if ([schoolId, grade, classNum, weekday, WEBHOOK_URL].some((v) => v === undefined || v === null)) { - console.warn("⚠️ | Undefined input detected. Skip sending webhook."); - return; - } - - const weekdayText = ["월", "화", "수", "목", "금"][weekday - 1]; - if (!weekdayText) { - console.warn("⚠️ | Invalid weekday. Skip sending webhook."); - return; - } - const timetableInfo = await getTimetable({ schoolId, grade, classNum, weekday }); + console.log("🏓 | Timetable Info Retrieved", timetableInfo); - - // 받아온 시간표 값이 없거나(undefined) 항목에 undefined 값이 있으면 전송 안 함 - if ( - !timetableInfo || - timetableInfo.length === 0 || - timetableInfo.some((item) => !item || item.subject === undefined || item.teacher === undefined) - ) { - console.warn("⚠️ | Timetable contains undefined/empty data. Skip sending webhook."); - return; - } - const data = { content: `📅 | ${grade}학년 ${classNum}반 시간표 정보`, embeds: [ { title: `🏫 | 학교 : 선린인터넷고등학교`, - fields: timetableInfo.map((item) => ({ - name: `${item.subject}${item.changed ? " *" : ""}`, + fields: (timetableInfo ?? []).map((item) => ({ + name: `${item.subject}${item.changed ? (" *") : ""}`, value: `${item.teacher}${item.subject in room ? ` | ${room[item.subject as keyof typeof room]}` : ""}`, inline: false, })), footer: { - text: `${weekdayText}요일 시간표 정보`, - }, + text: `${["월", "화", "수", "목", "금"][weekday - 1]}요일 시간표 정보` + } }, ], }; diff --git a/app/lib/meal.ts b/app/lib/meal.ts index ac3c07f..f2cc62b 100644 --- a/app/lib/meal.ts +++ b/app/lib/meal.ts @@ -1,4 +1,5 @@ -import { GoogleGenerativeAI } from "@google/generative-ai"; +import ModelClient, { isUnexpected } from "@azure-rest/ai-inference"; +import { AzureKeyCredential } from "@azure/core-auth"; const KEY = process.env.NEIS_API_KEY; @@ -44,14 +45,19 @@ export async function getMealInfo(MLSV_YMD: string, ATPT_OFCDC_SC_CODE: string, }; } -export async function NameToEmoji(name: string): Promise { - const apiKey = process.env.GOOGLE_API_KEY; - if (!apiKey) { - throw new Error("GOOGLE_API_KEY environment variable is not set."); - } - const genAI = new GoogleGenerativeAI(apiKey); - const model = genAI.getGenerativeModel({ model: "gemini-3.1-flash-lite-preview" }); +export async function NameToEmoji(name: string): Promise { + const token = process.env.GITHUB_TOKEN; + if (!token) { + throw new Error("GITHUB_TOKEN environment variable is not set."); + } + const endpoint = "https://models.github.ai/inference"; + const model = "openai/gpt-5-mini"; + + const client = ModelClient( + endpoint, + new AzureKeyCredential(token), + ); const systemPrompt = `⚠️ 중요한 지침: 당신은 오직 이모지로만 응답하는 AI입니다. 다음 규칙을 예외 없이 철저히 준수해야 합니다. ⚠️ @@ -99,26 +105,24 @@ A: 🥰,☮️,🗽 `; - const response = await model.generateContent({ - contents: [ - { role: "user", parts: [{ text: systemPrompt + "\n\nUser input: " + name }] } - ], - generationConfig: { + const response = await client.path("/chat/completions").post({ + body: { + messages: [ + { role: "system", content: systemPrompt }, + { role: "user", content: name } + ], temperature: 1.0, - topP: 1.0, - candidateCount: 1, - }, + top_p: 1.0, + model: model + } }); + if (isUnexpected(response)) { + throw response.body.error; + } - const result = response.response; - if (!result.candidates || !result.candidates[0]) { + const choices = response.body?.choices; + if (!choices || !choices[0]?.message?.content) { throw new Error("No valid response from the model."); } - - const textContent = result.candidates[0].content.parts[0]; - if (!textContent) { - throw new Error("Invalid response format from the model."); - } - - return textContent.text; + return choices[0].message.content as string; } diff --git a/app/package.json b/app/package.json index 852b843..338fabf 100644 --- a/app/package.json +++ b/app/package.json @@ -11,7 +11,6 @@ }, "dependencies": { "@azure-rest/ai-inference": "^1.0.0-beta.6", - "@google/generative-ai": "^0.24.1", "@imnyang/comcigan.ts": "^0.3.0" } }