From 3bd235b0cb21ce86745e46114565e78ba9e54876 Mon Sep 17 00:00:00 2001 From: Last2014 Date: Wed, 29 Apr 2026 14:17:54 +0900 Subject: [PATCH 1/6] Feat: #7 --- src/feature/earthquakeNotice.ts | 13 ++++++++++++- src/lib/memory.ts | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/feature/earthquakeNotice.ts b/src/feature/earthquakeNotice.ts index 9276c60..6965635 100644 --- a/src/feature/earthquakeNotice.ts +++ b/src/feature/earthquakeNotice.ts @@ -1,6 +1,7 @@ import client from "@/lib/client"; import config from "@/lib/config"; import initI18n from "@/lib/i18n"; +import Memory from "@/lib/memory"; import { format } from "date-fns"; import i18next from "i18next"; import { readFileSync } from "node:fs"; @@ -39,11 +40,21 @@ if (config.earthquake?.useHistoryData) { ? JSON.parse(event.data) : event.data; } catch (err) { - console.error(`メッセージのパースでエラーが発生: ${err}`); + console.error(`地震情報メッセージのパースでエラーが発生: ${err}`); + return; + } + + const mem = Memory.memory; + if (mem.processedInfo.includes(message.id) && !config.debug) { + console.log("重複した地震情報: ", message.id); return; } processMessage(message); + if (!config.debug) { + mem.processedInfo.concat([message.id]); + Memory.memory = mem; + } }); } diff --git a/src/lib/memory.ts b/src/lib/memory.ts index 11a4436..6db4ada 100644 --- a/src/lib/memory.ts +++ b/src/lib/memory.ts @@ -9,6 +9,7 @@ class MemoryClass { constructor() { if (!existsSync(path)) { writeFileSync(path, JSON.stringify({ + processedInfo: [], repliedUeuse: [], permissions: {}, userid: "", -- 2.52.0 From 109d32a3eddf9d8329da349cb5ec3c45c8a9a7e2 Mon Sep 17 00:00:00 2001 From: Last2014 Date: Wed, 29 Apr 2026 14:45:29 +0900 Subject: [PATCH 2/6] =?UTF-8?q?Feat:=20=E6=96=B0=E5=B9=B4=E8=BF=8E?= =?UTF-8?q?=E6=98=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 ++ locales/ja.yaml | 2 ++ src/feature/hnyNotice.ts | 29 +++++++++++++++++++++++++++++ src/index.ts | 38 +++++++++++++++++++++++++++++--------- 4 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 src/feature/hnyNotice.ts diff --git a/README.md b/README.md index 2bc58ea..ef5d3fe 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ uwuzu v1.6.3以上で利用可能です。 - 地震発生 - 緊急地震速報(警報) - 津波予報 +- 新年迎春 + 毎年1/1 0:00に投稿します。 - デバッグモード 設定で有効化することで、以下の機能が利用できます。 開発以外では使用しないでください。 diff --git a/locales/ja.yaml b/locales/ja.yaml index 75d8a28..e455ad2 100644 --- a/locales/ja.yaml +++ b/locales/ja.yaml @@ -50,6 +50,8 @@ eewNotice: | 📍震源地: {{ epicenter }} 💪マグニチュード: {{ magnitude }} 🪨深さ: {{ depth }}{{ areas }} +hnyNotice: | + あけましておめでとうございます。今年は、{{ year }}年です。 commandNotFound: | コマンドが本文から参照できませんでした。 Botでは、このアカウントに対してのメンション部分を取り除きます。 diff --git a/src/feature/hnyNotice.ts b/src/feature/hnyNotice.ts new file mode 100644 index 0000000..aae83f4 --- /dev/null +++ b/src/feature/hnyNotice.ts @@ -0,0 +1,29 @@ +import client from "@/lib/client"; +import initI18n from "@/lib/i18n"; +import i18next from "i18next"; +import { parentPort } from "node:worker_threads"; + +await initI18n(); + +parentPort?.on("message", async () => { + console.log("新年迎春の投稿を行います"); + + try { + const response = await client.request("ueuse/create", { + text: i18next.t("hnyNotice", { year: String(new Date().getFullYear()) }), + }); + + if (!response.success) { + console.warn("新年迎春投稿に失敗しました:", response.error_code); + process.exit(1); + } + + console.log("新年迎春投稿:", response.uniqid); + } catch (err: any) { + console.error("message" in err + ? err.message + : err); + } finally { + parentPort?.postMessage(""); + } +}); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index cc99953..15d13ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,14 +30,34 @@ try { process.exit(1); } -schedule("0 * * * *", async () => { - new Worker(`${import.meta.dirname}/feature/timeNotice.js`); -}); +try { + schedule("0 * * * *", async () => { + new Worker(`${import.meta.dirname}/feature/timeNotice.js`); + }); -schedule("0 7 * * *", async () => { - new Worker(`${import.meta.dirname}/feature/weatherNotice.js`); -}); + schedule("0 7 * * *", async () => { + new Worker(`${import.meta.dirname}/feature/weatherNotice.js`); + }); -schedule(`*/${config.command.interval} * * * *`, async () => { - new Worker(`${import.meta.dirname}/feature/command/index.js`); -}); \ No newline at end of file + schedule(`*/${config.command.interval} * * * *`, async () => { + new Worker(`${import.meta.dirname}/feature/command/index.js`); + }); + + let hnyWorker: Worker | undefined = undefined; + + schedule("59 23 31 12 *", () => { + hnyWorker = new Worker(`${import.meta.dirname}/feature/hnyNotice.js`); + }); + + schedule("0 0 1 1 *", () => { + hnyWorker?.once("message", async () => { + await hnyWorker?.terminate(); + hnyWorker = undefined; + }); + hnyWorker?.postMessage(""); + }); +} catch (err: any) { + console.error("message" in err + ? err.message + : err); +} \ No newline at end of file -- 2.52.0 From 90b308afa0631a63f800c908b7188c9995010018 Mon Sep 17 00:00:00 2001 From: Last2014 Date: Wed, 29 Apr 2026 19:13:08 +0900 Subject: [PATCH 3/6] =?UTF-8?q?Chg:=20=E6=96=B0=E5=B9=B4=E8=BF=8E=E6=98=A5?= =?UTF-8?q?=E3=81=AE=E6=8A=95=E7=A8=BF=E3=81=99=E3=82=8B=E9=9A=9B=E3=81=AE?= =?UTF-8?q?=E9=81=85=E5=BB=B6=E3=82=92=E5=89=8A=E6=B8=9B=20/=20Feat:=20?= =?UTF-8?q?=E6=96=B0=E5=B9=B4=E8=BF=8E=E6=98=A5=E3=82=92=E6=8A=95=E7=A8=BF?= =?UTF-8?q?=E3=81=97=E3=81=9F=E6=99=82=E5=88=BB=E3=82=92=E3=82=B3=E3=83=B3?= =?UTF-8?q?=E3=82=BD=E3=83=BC=E3=83=AB=E3=81=AB=E8=A1=A8=E7=A4=BA=20/=20Fi?= =?UTF-8?q?x:=20=E5=9C=B0=E9=9C=87=E6=83=85=E5=A0=B1=E3=81=AEid=E9=99=A4?= =?UTF-8?q?=E5=A4=96=E3=81=8C=E6=9C=AC=E7=95=AA=E7=92=B0=E5=A2=83=E3=81=A7?= =?UTF-8?q?=E5=8B=95=E4=BD=9C=E3=81=97=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/feature/earthquakeNotice.ts | 9 +++++++-- src/feature/hnyNotice.ts | 7 ++++--- src/index.ts | 8 ++------ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/feature/earthquakeNotice.ts b/src/feature/earthquakeNotice.ts index 6965635..1ef9c99 100644 --- a/src/feature/earthquakeNotice.ts +++ b/src/feature/earthquakeNotice.ts @@ -44,15 +44,17 @@ if (config.earthquake?.useHistoryData) { return; } + const id = message.id ?? message._id; const mem = Memory.memory; - if (mem.processedInfo.includes(message.id) && !config.debug) { + if (mem.processedInfo.includes(id) && !config.debug) { console.log("重複した地震情報: ", message.id); return; } processMessage(message); + if (!config.debug) { - mem.processedInfo.concat([message.id]); + mem.processedInfo.concat([id]); Memory.memory = mem; } }); @@ -76,6 +78,9 @@ const processMessage = async (message: any) => { } switch (message.code) { + case 555: + console.log("ピアの地域分布情報を受信しました"); + break; case 551: { console.log("地震発生情報を受信しました"); diff --git a/src/feature/hnyNotice.ts b/src/feature/hnyNotice.ts index aae83f4..e9036a5 100644 --- a/src/feature/hnyNotice.ts +++ b/src/feature/hnyNotice.ts @@ -1,5 +1,6 @@ import client from "@/lib/client"; import initI18n from "@/lib/i18n"; +import { format } from "date-fns"; import i18next from "i18next"; import { parentPort } from "node:worker_threads"; @@ -18,12 +19,12 @@ parentPort?.on("message", async () => { process.exit(1); } - console.log("新年迎春投稿:", response.uniqid); + console.log("新年迎春投稿:", `${response.uniqid} (${format(new Date(), "yyyy/M/d H:mm:ss:SSS")})`); + process.exit(0); } catch (err: any) { console.error("message" in err ? err.message : err); - } finally { - parentPort?.postMessage(""); + process.exit(1); } }); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 15d13ba..18be265 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,15 +45,11 @@ try { let hnyWorker: Worker | undefined = undefined; - schedule("59 23 31 12 *", () => { + schedule("57 59 23 31 12 *", () => { hnyWorker = new Worker(`${import.meta.dirname}/feature/hnyNotice.js`); }); - schedule("0 0 1 1 *", () => { - hnyWorker?.once("message", async () => { - await hnyWorker?.terminate(); - hnyWorker = undefined; - }); + schedule("0 0 0 1 1 *", () => { hnyWorker?.postMessage(""); }); } catch (err: any) { -- 2.52.0 From 3b66c47aa38fca060a10b4e227d5b8ccdc07b9d0 Mon Sep 17 00:00:00 2001 From: Last2014 Date: Thu, 30 Apr 2026 20:10:59 +0900 Subject: [PATCH 4/6] =?UTF-8?q?Fix:=20for=E6=96=87=E3=81=A7=E3=82=B9?= =?UTF-8?q?=E3=82=AD=E3=83=83=E3=83=97=E3=81=A7=E3=81=AF=E3=81=AA=E3=81=8F?= =?UTF-8?q?=E3=83=AB=E3=83=BC=E3=83=97=E3=81=AE=E7=B5=82=E4=BA=86=E3=82=92?= =?UTF-8?q?=E8=A1=8C=E3=81=A3=E3=81=A6=E3=81=84=E3=81=9F=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=20/=20Feat:=20#10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/feature/command/help.ts | 2 +- src/feature/command/index.ts | 47 ++++++++++++++++++++------------- src/feature/earthquakeNotice.ts | 2 +- src/lib/memory.ts | 3 ++- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/feature/command/help.ts b/src/feature/command/help.ts index 50a0a24..552cde8 100644 --- a/src/feature/command/help.ts +++ b/src/feature/command/help.ts @@ -47,7 +47,7 @@ export default async function helpCommand(ueuse: ueuseModule, args: string[]) { for (let i = 0; i < helps.length; i++) { const help = helps[i]; if (!help) - break; + continue; summarys += `${i18next.t(`help${help.charAt(0).toUpperCase()}${help.slice(1)}`)}${EOL}`; } diff --git a/src/feature/command/index.ts b/src/feature/command/index.ts index 2d89369..0d04155 100644 --- a/src/feature/command/index.ts +++ b/src/feature/command/index.ts @@ -17,16 +17,22 @@ try { { const response = await client.request("me/notification/", { + page: 1, limit: 20, }); if (response.success) { - for (const notification of response.data) { + for (const [index, notification] of response.data.entries()) { if (notification.category !== "reply") - break; + continue; if (!notification.valueid) { console.warn("返信通知にvalueidが存在しないため、スキップします"); + continue; + } + + const mem = Memory.memory; + if (mem.lastReadReply === notification.valueid) { break; } @@ -36,7 +42,12 @@ try { if (!ueuseResponse.success || !ueuseResponse.data[0]) { console.warn("返信通知からユーズを参照できないため、スキップします"); - break; + continue; + } + + if (index === 0) { + const mem = Memory.memory; + mem.lastReadReply = ueuseResponse.data[0].uniqid; } ueuses.push(ueuseResponse.data[0]); @@ -48,11 +59,24 @@ try { { const response = await client.request("ueuse/mentions", { + page: 1, limit: 20, }); if (response.success) { - ueuses.push(...response.data); + for (const [index, mention] of response.data.entries()) { + const mem = Memory.memory; + if (mem.lastReadMention === mention.uniqid) { + break; + } + + if (index === 0) { + const mem = Memory.memory; + mem.lastReadMention = mention.uniqid; + } + + ueuses.push(mention); + } } else { console.warn("メンションの取得に失敗しましたが、続行します"); } @@ -61,13 +85,6 @@ try { ueuses = [...new Set(ueuses)]; for (const ueuse of ueuses) { - const repliedUeuse = (Memory.memory["repliedUeuse"] as string[]); - - if (repliedUeuse.includes(ueuse.uniqid)) { - console.log("既に応答しているため、スキップします"); - break; - } - const mem = Memory.memory; let text = ueuse.text; text = text.replace(`@${mem.userid}`, ""); @@ -119,14 +136,6 @@ try { console.warn("ユーズの作成に失敗しました:", response.error_code); break; } - - { - const repliedUeuse = (Memory.memory["repliedUeuse"] as string[]); - repliedUeuse.push(ueuse.uniqid); - const mem = Memory.memory; - mem["repliedUeuse"] = repliedUeuse; - Memory.memory = mem; - } } process.exit(0); diff --git a/src/feature/earthquakeNotice.ts b/src/feature/earthquakeNotice.ts index 1ef9c99..43da366 100644 --- a/src/feature/earthquakeNotice.ts +++ b/src/feature/earthquakeNotice.ts @@ -111,7 +111,7 @@ const processMessage = async (message: any) => { for (const point of message.points) { const scaleMsg = scaleMessages[String(point.scale)]; if (!scaleMsg) - break; + continue; points[scaleMsg]?.push(point); } diff --git a/src/lib/memory.ts b/src/lib/memory.ts index 6db4ada..0e41425 100644 --- a/src/lib/memory.ts +++ b/src/lib/memory.ts @@ -10,8 +10,9 @@ class MemoryClass { if (!existsSync(path)) { writeFileSync(path, JSON.stringify({ processedInfo: [], - repliedUeuse: [], permissions: {}, + lastReadMention: "", + lastReadReply: "", userid: "", })); } -- 2.52.0 From 23a06fc88fa5c19fdca9ef061194340e946794f9 Mon Sep 17 00:00:00 2001 From: Last2014 Date: Fri, 1 May 2026 22:06:04 +0900 Subject: [PATCH 5/6] =?UTF-8?q?Chg:=20=E6=99=82=E5=A0=B1=E3=81=AE=E6=99=82?= =?UTF-8?q?=E5=88=BB=E3=83=95=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=83=E3=83=88?= =?UTF-8?q?=E3=82=92HH:mm=E3=81=8B=E3=82=89H:mm=E3=81=AB=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=20/=20Feat:=20=E7=B7=8A=E6=80=A5=E5=9C=B0=E9=9C=87=E9=80=9F?= =?UTF-8?q?=E5=A0=B1=EF=BC=88=E8=AD=A6=E5=A0=B1=EF=BC=89=E8=A7=A3=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja.yaml | 4 ++++ src/feature/earthquakeNotice.ts | 18 ++++++++++++++++++ src/feature/timeNotice.ts | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/locales/ja.yaml b/locales/ja.yaml index e455ad2..813145d 100644 --- a/locales/ja.yaml +++ b/locales/ja.yaml @@ -50,6 +50,10 @@ eewNotice: | 📍震源地: {{ epicenter }} 💪マグニチュード: {{ magnitude }} 🪨深さ: {{ depth }}{{ areas }} +eewCancelNotice: | + ### ==緊急地震速報(警報)**解除**== + {{ isTest }} + ⏰発表時刻: {{ announceTime }} hnyNotice: | あけましておめでとうございます。今年は、{{ year }}年です。 commandNotFound: | diff --git a/src/feature/earthquakeNotice.ts b/src/feature/earthquakeNotice.ts index 43da366..3e43130 100644 --- a/src/feature/earthquakeNotice.ts +++ b/src/feature/earthquakeNotice.ts @@ -237,6 +237,24 @@ const processMessage = async (message: any) => { { console.log("緊急地震速報(警報)を受信しました"); + if (message.cancelled) { + const response = await client.request("ueuse/create", { + text: i18next.t("eewCancelNotice", { + isTest: message.test + ? "⚒️これは**テストです。**" + : "🚨これは**テストではありません。**", + announceTime: format(new Date(message.issue.time), "yyyy年M月d日 H:mm:ss"), + }), + }); + + if (!response.success) { + console.warn("ユーズの作成に失敗しました:", response.error_code); + break; + } + + console.log("緊急地震速報(警報)解除情報を投稿:", response.uniqid); + } + const kindMessages: Record = { "10": "⏳主要動は、**未到達と予測**されています。", "11": "🫨主要動が、**既に到達していると予測**されています。", diff --git a/src/feature/timeNotice.ts b/src/feature/timeNotice.ts index 1f8e7e4..f3141cf 100644 --- a/src/feature/timeNotice.ts +++ b/src/feature/timeNotice.ts @@ -8,7 +8,7 @@ console.log("時報の投稿を行います"); try { const response = await client.request("ueuse/create", { - text: i18next.t("timeNotice", { time: format(new Date(), "HH:mm") }), + text: i18next.t("timeNotice", { time: format(new Date(), "H:mm") }), }); if (!response.success) { -- 2.52.0 From d59857593ad78f90b04e5b667f8dcaac575e4841 Mon Sep 17 00:00:00 2001 From: Last2014 Date: Fri, 1 May 2026 22:10:50 +0900 Subject: [PATCH 6/6] 2026.4.0-alpha.2 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88c5f54..759d015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# 2026.4.0-alpha.2 +- Feat: 地震情報のid除外 +- Feat: 新年迎春 +- Fix: for文でスキップではなくループの終了を行っていた問題 +- Feat: 返信済みかどうかをuniqidのみで判断する機能 +- Chg: 時報の時刻フォーマットをHH:mmからH:mmに変更 +- Feat: 緊急地震速報(警報)解除 + # 2026.4.0-alpha.1 - Del: tsxの開発環境を削除 - Chg: typescriptを5.9.3にダウングレード diff --git a/package.json b/package.json index 879e04b..b30f999 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "notice-uwuzu", - "version": "26.4.0-alpha.1", + "version": "26.4.0-alpha.2", "type": "module", "main": "dist/index.js", "scripts": { -- 2.52.0