From d429503b78164c8334dc78450818bc7f2edb578e Mon Sep 17 00:00:00 2001 From: Last2014 Date: Sun, 3 May 2026 13:50:11 +0900 Subject: [PATCH] =?UTF-8?q?Feat:=20=E3=83=A6=E3=83=BC=E3=82=BA=E3=81=AE?= =?UTF-8?q?=E5=86=8D=E8=A9=A6=E8=A1=8C=20/=20Feat:=20=E3=83=A6=E3=83=BC?= =?UTF-8?q?=E3=82=BA=E3=81=AE=E6=96=87=E5=AD=97=E6=95=B0=E5=88=B6=E9=99=90?= =?UTF-8?q?=E5=9B=9E=E9=81=BF=20/=20Feat:=20=E3=83=A6=E3=83=BC=E3=82=BA?= =?UTF-8?q?=E9=80=81=E4=BF=A1=E9=96=A2=E6=95=B0=20/=20Chg:=20weatherNotice?= =?UTF-8?q?.ts=E3=81=AE=E3=83=9E=E3=82=B8=E3=83=83=E3=82=AF=E3=83=8A?= =?UTF-8?q?=E3=83=B3=E3=83=90=E3=83=BC=E3=81=AB=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/example.yaml | 8 ++ src/feature/command/follow.ts | 13 +- src/feature/command/help.ts | 33 ++--- src/feature/command/index.ts | 15 +-- src/feature/command/miq.ts | 211 +++++++------------------------- src/feature/command/unfollow.ts | 13 +- src/feature/earthquakeNotice.ts | 57 ++------- src/feature/hnyNotice.ts | 13 +- src/feature/timeNotice.ts | 12 +- src/feature/weatherNotice.ts | 57 +++++++-- src/lib/client.ts | 62 +++++++++- src/lib/config.ts | 4 + 12 files changed, 201 insertions(+), 297 deletions(-) diff --git a/config/example.yaml b/config/example.yaml index 5dd5dda..ab1c040 100644 --- a/config/example.yaml +++ b/config/example.yaml @@ -18,6 +18,7 @@ earthquake: # デバッグ用途のみで使用してください。 useHistoryData: false # 再接続の間隔(ミリ秒) number + # 正数のみが有効です。 reconnectInterval: 3000 uwuzu: # APIトークン string @@ -25,5 +26,12 @@ uwuzu: token: API_TOKEN # uwuzuサーバーのorigin string origin: https://uwuzu.example.com +ueuse: + # 最大再試行数 number + # 自然数のみが有効です。 + maxRetries: 3 + # 再試行の間隔(ミリ秒) number + # 正数のみが有効です。 + retryInterval: 1000 # デバッグモードにするかどうか boolean debug: false \ No newline at end of file diff --git a/src/feature/command/follow.ts b/src/feature/command/follow.ts index cb71eda..ff33b58 100644 --- a/src/feature/command/follow.ts +++ b/src/feature/command/follow.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import client, { createUeuse } from "@/lib/client"; import ueuseModule from "better-uwuzu-sdk/types/1.6.8/types/modules/ueuse"; import i18next from "i18next"; @@ -14,15 +14,8 @@ export default async function followCommand(ueuse: ueuseModule) { console.log("フォロー:", follow.userid); - const notice = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("followedNotification", { username: ueuse.account.username }), replyid: ueuse.uniqid, - }); - - if (!notice.success) { - console.warn("フォロー通知に失敗:", notice.error_code); - return; - } - - console.log("フォロー通知:", notice.uniqid); + }, "フォロー通知"); } \ No newline at end of file diff --git a/src/feature/command/help.ts b/src/feature/command/help.ts index 552cde8..649aeff 100644 --- a/src/feature/command/help.ts +++ b/src/feature/command/help.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import { createUeuse } from "@/lib/client"; import ueuseModule from "better-uwuzu-sdk/types/1.6.8/types/modules/ueuse"; import i18next from "i18next"; import { EOL } from "node:os"; @@ -14,31 +14,19 @@ const helps = [ export default async function helpCommand(ueuse: ueuseModule, args: string[]) { if (args[1] !== undefined) { if (!(helps.includes(args[1]))) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("invalidOption", { option: args[1], command: "help" }), replyid: ueuse.uniqid, - }); + }, "無効なオプションである旨"); - if (!response.success) { - console.warn("コマンド詳細の返信に失敗:", response.error_code); - return; - } - - console.warn("コマンド詳細:", response.uniqid); return; } - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t(`fullHelp${args[1].charAt(0).toUpperCase()}${args[1].slice(1)}`), replyid: ueuse.uniqid, - }); + }, "コマンド詳細"); - if (!response.success) { - console.warn("コマンド詳細の返信に失敗:", response.error_code); - return; - } - - console.warn("コマンド詳細:", response.uniqid); return; } @@ -52,15 +40,8 @@ export default async function helpCommand(ueuse: ueuseModule, args: string[]) { summarys += `${i18next.t(`help${help.charAt(0).toUpperCase()}${help.slice(1)}`)}${EOL}`; } - const response = await client.request("ueuse/create", { + await createUeuse({ text: summarys.trim(), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("コマンド概要の返信に失敗:", response.error_code); - return; - } - - console.warn("コマンド概要:", response.uniqid); + }, "コマンド概要"); } diff --git a/src/feature/command/index.ts b/src/feature/command/index.ts index 9b18e70..0f70e07 100644 --- a/src/feature/command/index.ts +++ b/src/feature/command/index.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import client, { createUeuse } from "@/lib/client"; import Memory from "@/lib/memory"; import ueuseModule from "better-uwuzu-sdk/types/1.6.8/types/modules/ueuse"; import i18next from "i18next"; @@ -100,13 +100,10 @@ try { if (!commandRow || commandRow === "") { console.warn("コマンドが本文から参照できません"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("commandNotFound"), replyid: ueuse.uniqid, - }); - - if (!response.success) - console.warn("ユーズの作成に失敗しました:", response.error_code); + }, "コマンドが見つからない旨"); return; } @@ -132,13 +129,11 @@ try { default: console.warn("不明なコマンドが入力されました:", args[0]); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("unknownCommand", { command: args[0] }), replyid: ueuse.uniqid, - }); + }, "コマンドが不明である旨"); - if (!response.success) - console.warn("ユーズの作成に失敗しました:", response.error_code); break; } })); diff --git a/src/feature/command/miq.ts b/src/feature/command/miq.ts index d02eff3..8618f99 100644 --- a/src/feature/command/miq.ts +++ b/src/feature/command/miq.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import client, { createUeuse } from "@/lib/client"; import Memory from "@/lib/memory"; import ueuseModule from "better-uwuzu-sdk/types/1.6.8/types/modules/ueuse"; import i18next from "i18next"; @@ -7,14 +7,10 @@ import { EOL } from "node:os"; export default async function miqCommand(ueuse: ueuseModule, args: string[]) { if (!args[1]) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("lackOption", { command: "miq" }), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - } + }, "オプションが不足している旨"); return; } @@ -32,14 +28,10 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { ? itUeuse.error_code : "データなし"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("replySourceFailed"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.log("返信に失敗:", response.error_code); - } + }, "ソースが見つからない旨"); return; } @@ -49,27 +41,19 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { switch (permission) { case "me": if (itUeuse.data[0].account.userid !== ueuse.account.userid) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("miqPermissionMe"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - } + }, "権限が自分自身のみである旨"); return; } case "consent": if (itUeuse.data[0].account.userid !== ueuse.account.userid) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("miqPermissionConsent", { userid: itUeuse.data[0].account.userid }), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - } + }, "権限が許可制である旨"); return; } @@ -85,19 +69,15 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { }); if (!(typeof result === "string")) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("miqGenerateFailed"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - } + }, "Make it a Quoteの生成に失敗した旨"); return; } - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("miqSuccess", { message: (args[2] ?? "") === "color" ? "カラーモードで生成しました。" : "モノクロモードで生成しました。" @@ -106,14 +86,7 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { photo: [result], }, replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("MiQを生成:", response.uniqid); + }, "Make it a Quote"); break; case "permission": @@ -121,33 +94,21 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { mem = Memory.memory; const permission = mem["permissions"][ueuse.account.userid] ?? "consent"; - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("permissionResponse", { permission }), replyid: ueuse.uniqid, - }); + }, "権限"); - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); return; } const availablePermission = ["me", "everyone", "consent"]; if (!(availablePermission.includes(args[2]))) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("invalidOption", { option: args[2], command: "miq" }), replyid: ueuse.uniqid, - }); + }, "無効なオプションである旨"); - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); return; } @@ -156,33 +117,20 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { mem["permissions"][ueuse.account.userid] = args[2]; Memory.memory = mem; - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("permissionChangeSuccess", { username: ueuse.account.username, permission: args[2] }), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); + }, "権限の変更に成功した旨"); } break; case "allow": if (ueuse.replyid === "") { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("injusticeFormat"), replyid: ueuse.uniqid, - }); + }, "形式が異なる旨"); - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); return; } @@ -191,17 +139,11 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { const permission = mem["permissions"][ueuse.account.userid] ?? "consent"; if (permission !== "consent") { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("permisionIsNotConsent"), replyid: ueuse.uniqid, - }); + }, "権限が許可制ではない旨"); - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); return; } } @@ -215,30 +157,20 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { ? confirmUeuse.error_code : "データなし"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("replySourceFailed"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.log("返信に失敗:", response.error_code); - } + }, "ソースが見つからない旨"); return; } if (confirmUeuse.data[0].replyid === "") { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("injusticeFormat"), replyid: ueuse.uniqid, - }); + }, "形式が異なる旨"); - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); return; } @@ -248,14 +180,10 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { ? confirmUeuse.error_code : "データなし"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("replySourceIsNotThis"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.log("返信に失敗:", response.error_code); - } + }, "返信元がこのBotではない旨"); return; } @@ -269,30 +197,19 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { ? requestUeuse.error_code : "データなし"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("replySourceFailed"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.log("返信に失敗:", response.error_code); - } + }, "ソースが見つからない旨"); return; } if (requestUeuse.data[0].replyid === "") { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("injusticeFormat"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); + }, "形式が異なる旨"); return; } @@ -305,30 +222,19 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { ? sourceUeuse.error_code : "データなし"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("replySourceFailed"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.log("返信に失敗:", response.error_code); - } + }, "ソースが見つからない旨"); return; } if (sourceUeuse.data[0].account.userid !== ueuse.account.userid) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("replySourceIsNotSourceUser"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.log("返信に失敗:", response.error_code); - return; - } - - console.warn("ソースのユーズと/miq allowのユーザーが一致しない:", response.uniqid); + }, "ソースのユーズと/miq allowのユーザーが一致しない旨"); return; } @@ -345,27 +251,15 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { if (!commandRow || commandRow === "") { console.warn("コマンドが本文から参照できません"); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("commandNotFound"), replyid: requestUeuse.data[0].uniqid, - }); + }, "コマンドが見つからない旨"); - if (!response.success) - console.warn("ユーズの作成に失敗しました:", response.error_code); - - { - const response = await client.request("ueuse/create", { - text: i18next.t("injusticeFormat"), - replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("返信:", response.uniqid); - } + await createUeuse({ + text: i18next.t("injusticeFormat"), + replyid: ueuse.uniqid, + }, "形式が異なる旨"); break; } @@ -382,19 +276,15 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { }); if (!(typeof result === "string")) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("miqGenerateFailed"), replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - } + }, "Make it a Quoteの生成に失敗した旨"); return; } - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("miqSuccess", { message: ((requestUeuseArgs[2] ?? "") === "color" ? "カラーモードで生成しました。" : "モノクロモードで生成しました。") @@ -404,14 +294,7 @@ export default async function miqCommand(ueuse: ueuseModule, args: string[]) { photo: [result], }, replyid: ueuse.uniqid, - }); - - if (!response.success) { - console.warn("返信に失敗:", response.error_code); - return; - } - - console.log("MiQを生成:", response.uniqid); + }, "Make it a Quote"); } break; diff --git a/src/feature/command/unfollow.ts b/src/feature/command/unfollow.ts index d9f7ed8..2ff6916 100644 --- a/src/feature/command/unfollow.ts +++ b/src/feature/command/unfollow.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import client, { createUeuse } from "@/lib/client"; import ueuseModule from "better-uwuzu-sdk/types/1.6.8/types/modules/ueuse"; import i18next from "i18next"; @@ -14,15 +14,8 @@ export default async function unfollowCommand(ueuse: ueuseModule) { console.log("フォロー解除:", unfollow.userid); - const notice = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("unfollowedNotification", { username: ueuse.account.username }), replyid: ueuse.uniqid, - }); - - if (!notice.success) { - console.warn("フォロー解除通知に失敗:", notice.error_code); - return; - } - - console.log("フォロー解除通知:", notice.uniqid); + }, "フォロー解除通知"); } \ No newline at end of file diff --git a/src/feature/earthquakeNotice.ts b/src/feature/earthquakeNotice.ts index 45f37d8..5fcc4bd 100644 --- a/src/feature/earthquakeNotice.ts +++ b/src/feature/earthquakeNotice.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import { createUeuse } from "@/lib/client"; import config from "@/lib/config"; import initI18n from "@/lib/i18n"; import Memory from "@/lib/memory"; @@ -169,7 +169,7 @@ const processMessage = async (message: any) => { `【${label}】${EOL}${addrs.join("・")}`) .join(EOL.repeat(2)).trim(); - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("earthquakeNotice", { occuredTime: format(new Date(message.earthquake.time), "yyyy年M月d日 H:mm"), maxScale: scaleMessages[String(message.earthquake.maxScale)], @@ -194,14 +194,7 @@ const processMessage = async (message: any) => { ? "" : EOL + message.comments.freeFormComment + EOL, }), - }); - - if (!response.success) { - console.warn("ユーズの作成に失敗しました:", response.error_code); - break; - } - - console.log("地震発生情報を投稿:", response.uniqid); + }, "地震発生情報"); } break; case 552: @@ -209,19 +202,12 @@ const processMessage = async (message: any) => { console.log("津波予報情報を受信しました"); if (message.cancelled) { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("tsunamiCancelNotice", { announceTime: format(new Date(message.issue.time), "yyyy年M月d日 H:mm:ss"), source: message.issue.source ?? "不明", }), - }); - - if (!response.success) { - console.warn("ユーズの作成に失敗しました:", response.error_code); - break; - } - - console.log("津波予報解除情報を投稿:", response.uniqid); + }, "津波予報解除情報"); break; } @@ -252,20 +238,13 @@ const processMessage = async (message: any) => { }) + EOL.repeat(2); } - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("tsunamiForecastNotice", { announceTime: format(new Date(message.issue.time), "yyyy年M月d日 H:mm:ss"), areasMsg: areasMsg.trim(), source: message.issue.source ?? "不明", }), - }); - - if (!response.success) { - console.warn("ユーズの作成に失敗しました:", response.error_code); - break; - } - - console.log("津波予報情報を投稿:", response.uniqid); + }, "津波予報情報"); } break; case 556: @@ -273,21 +252,14 @@ const processMessage = async (message: any) => { console.log("緊急地震速報(警報)を受信しました"); if (message.cancelled) { - const response = await client.request("ueuse/create", { + await createUeuse({ 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 = { @@ -313,7 +285,7 @@ const processMessage = async (message: any) => { }) + EOL.repeat(2); } - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("eewNotice", { isTest: message.test ? "⚒️これは**テストです。**" @@ -337,14 +309,7 @@ const processMessage = async (message: any) => { ? EOL.repeat(2) + areasMsg.trim() : "", }), - }); - - if (!response.success) { - console.warn("ユーズの作成に失敗しました:", response.error_code); - break; - } - - console.log("緊急地震速報(警報)情報を投稿:", response.uniqid); + }, "緊急地震速報(警報)情報"); } break; default: diff --git a/src/feature/hnyNotice.ts b/src/feature/hnyNotice.ts index e9036a5..8868313 100644 --- a/src/feature/hnyNotice.ts +++ b/src/feature/hnyNotice.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import { createUeuse } from "@/lib/client"; import initI18n from "@/lib/i18n"; import { format } from "date-fns"; import i18next from "i18next"; @@ -10,16 +10,11 @@ parentPort?.on("message", async () => { console.log("新年迎春の投稿を行います"); try { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("hnyNotice", { year: String(new Date().getFullYear()) }), - }); + }, "新年迎春"); - if (!response.success) { - console.warn("新年迎春投稿に失敗しました:", response.error_code); - process.exit(1); - } - - console.log("新年迎春投稿:", `${response.uniqid} (${format(new Date(), "yyyy/M/d H:mm:ss:SSS")})`); + console.log("新年迎春投稿時刻:", format(new Date(), "yyyy/M/d H:mm:ss:SSS")); process.exit(0); } catch (err: any) { console.error("message" in err diff --git a/src/feature/timeNotice.ts b/src/feature/timeNotice.ts index f3141cf..4ad0bfe 100644 --- a/src/feature/timeNotice.ts +++ b/src/feature/timeNotice.ts @@ -1,4 +1,4 @@ -import client from "@/lib/client"; +import { createUeuse } from "@/lib/client"; import initI18n from "@/lib/i18n"; import { format } from "date-fns"; import i18next from "i18next"; @@ -7,16 +7,10 @@ await initI18n(); console.log("時報の投稿を行います"); try { - const response = await client.request("ueuse/create", { + await createUeuse({ text: i18next.t("timeNotice", { time: format(new Date(), "H:mm") }), - }); + }, "時報"); - if (!response.success) { - console.warn("時報投稿に失敗しました:", response.error_code); - process.exit(1); - } - - console.log("時報投稿:", response.uniqid); process.exit(0); } catch (err: any) { console.error("message" in err diff --git a/src/feature/weatherNotice.ts b/src/feature/weatherNotice.ts index 79412d0..2d69206 100644 --- a/src/feature/weatherNotice.ts +++ b/src/feature/weatherNotice.ts @@ -1,4 +1,5 @@ import client from "@/lib/client"; +import config from "@/lib/config"; import initI18n from "@/lib/i18n"; import Memory from "@/lib/memory"; import i18next from "i18next"; @@ -61,12 +62,27 @@ if (!isMainThread && workerData === "scheduledWeatherNotice") { console.log("天気予報の投稿を行います"); try { - const provisionalUeuse = await client.request("ueuse/create", { - text: i18next.t("weatherProvisional"), - }); + let provisionalUeuse; + let success = false; - if (!provisionalUeuse.success) { - console.error("天気仮投稿に失敗しました:", provisionalUeuse.error_code); + for (let attempt = 1; attempt <= config.ueuse.maxRetries; attempt++) { + provisionalUeuse = await client.request("ueuse/create", { + text: i18next.t("weatherProvisional"), + }); + + if (provisionalUeuse.success) { + success = true; + break; + } + + console.warn(`天気仮投稿に失敗しました (試行 ${attempt}/${config.ueuse.maxRetries}):`, provisionalUeuse.error_code); + if (attempt < config.ueuse.maxRetries) { + await new Promise(resolve => setTimeout(resolve, 1000)); + } + } + + if (!success || !provisionalUeuse?.success) { + console.error("天気仮投稿の全試行に失敗したため、終了します。"); process.exit(1); } @@ -84,8 +100,9 @@ if (!isMainThread && workerData === "scheduledWeatherNotice") { export async function weatherReply(uniqid: string) { // インデックス + const aboutFullLength = 3100; const mem = Memory.memory; - const splitCount = Math.round(3100 / mem.max_length); + const splitCount = Math.round(aboutFullLength / mem.max_length); const total = cityList.length; const chunkSizes = Array(splitCount).fill(0).map((_, i) => Math.floor((total + i) / splitCount) @@ -149,13 +166,29 @@ export async function weatherReply(uniqid: string) { // 分割投稿 for (let i = 0; i < splitCount; i++) { - const replyUeuse = await client.request("ueuse/create", { - text: weatherResults[i].trim(), - replyid: uniqid, - }); + let replyUeuse; + let success = false; - if (!replyUeuse.success) { - console.error("天気返信に失敗しました:", replyUeuse.error_code); + for (let attempt = 1; attempt <= config.ueuse.maxRetries; attempt++) { + replyUeuse = await client.request("ueuse/create", { + text: weatherResults[i].trim(), + replyid: uniqid, + }); + + if (replyUeuse.success) { + success = true; + break; + } + + console.warn(`天気返信に失敗しました (試行 ${attempt}/${config.ueuse.maxRetries}):`, replyUeuse.error_code); + if (attempt < config.ueuse.maxRetries) { + await new Promise(resolve => setTimeout(resolve, config.ueuse.retryInterval)); + } + } + + if (!success || !replyUeuse?.success) { + console.error("天気返信の全試行に失敗したため、終了します。"); + process.exit(1); } console.log("天気返信:", replyUeuse.uniqid); diff --git a/src/lib/client.ts b/src/lib/client.ts index d5bc847..2db59f2 100644 --- a/src/lib/client.ts +++ b/src/lib/client.ts @@ -2,6 +2,8 @@ import uwuzu from "better-uwuzu-sdk"; import config from "@/lib/config"; import Parser from "better-uwuzu-sdk/1.6.8/parser"; import ApiMap from "better-uwuzu-sdk/types/1.6.8/map"; +import Memory from "@/lib/memory"; +import { EOL } from "node:os"; const client = new uwuzu({ origin: config.uwuzu.origin, @@ -9,5 +11,63 @@ const client = new uwuzu({ }); client.token = config.uwuzu.token; +export default client; -export default client; \ No newline at end of file +export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: string) => { + const mem = Memory.memory; + const maxLength = mem.max_length; + const excessedMessage = "👉返信に続きがあります。"; + + let remainingText = data.text; + let firstUniqid = ""; + + while (remainingText.length > 0) { + let currentText = ""; + let bodyTextLength = 0; + + if (remainingText.length <= maxLength) { + currentText = remainingText; + bodyTextLength = remainingText.length; + remainingText = ""; + } else { + bodyTextLength = maxLength - excessedMessage.length - 2; + currentText = remainingText.slice(0, bodyTextLength) + EOL.repeat(2) + excessedMessage; + remainingText = remainingText.slice(bodyTextLength); + } + + let postedUniqid = ""; + let success = false; + + for (let attempt = 1; attempt <= config.ueuse.maxRetries; attempt++) { + const response = await client.request("ueuse/create", { + ...data, + text: currentText, + replyid: data.replyid === undefined && firstUniqid !== "" + ? firstUniqid + : data.replyid, + }); + + if (response.success) { + success = true; + postedUniqid = response.uniqid; + break; + } + + console.warn(`${title}の投稿に失敗しました (試行 ${attempt}/${config.ueuse.maxRetries}):`, response.error_code); + if (attempt < config.ueuse.maxRetries) { + await new Promise(resolve => setTimeout(resolve, config.ueuse.retryInterval)); + } + } + + if (!success) { + console.error(`${title}の全試行が失敗したため、処理を中断します。`); + break; + } + + if (firstUniqid === "") { + firstUniqid = postedUniqid; + } + + console.log(`${title}を投稿:`, postedUniqid); + } +} diff --git a/src/lib/config.ts b/src/lib/config.ts index 20ce3d4..76c9c64 100644 --- a/src/lib/config.ts +++ b/src/lib/config.ts @@ -34,6 +34,10 @@ const schema = z.object({ } }), }), + ueuse: z.object({ + maxRetries: z.number().int().positive(), + retryInterval: z.number().positive(), + }), debug: z.boolean().optional(), });