2026.4.0 #13

Merged
last2014 merged 3 commits from develop into main 2026-05-03 06:14:47 +00:00
6 changed files with 57 additions and 9 deletions
+31 -1
View File
@@ -1,3 +1,33 @@
# 2026.4.0
- Breaking: noticeUwuzuを0から作り直しました
- Breaking: 25.12.0-alpha.1までの方針を全て廃止しました
- Chg: パッケージマネージャーをnpmからpnpmへ変更しました
- Chg: 全コードをsrcへ移動しました
- Chg: ユーズのメッセージをyamlとi18nextで管理することで先頭と末尾の改行のある問題などに対策しました
- Chg: 全ての保存データをmemory.jsonとして保管し、memory.tsを実装しました
- Note: 以下のログは全て実装として記録しています
- Feat: ユーザーは以下のコマンドを使用することができます。
- `/weather`: 天気予報を取得できます。
- `/help`: コマンドの利用方法などを取得できます。
- `/miq`: Make it a Quoteを操作できます。
- `/follow`: Botからフォローされます。
- `/unfollow`: Botからフォロー解除されます。
- Feat: 地震情報が利用できます。以下の情報を投稿します。
- 地震発生情報
- 津波予報
- 緊急地震速報(警報)
- Feat: 時報が利用できます。毎時0分に投稿します。
- Feat: 天気予報を利用できます。毎日7:00に投稿します。
- Feat: 新年迎春の投稿を行います。遅延が最低限になるように出来ています。
- Feat: worker_threadsによる並列処理
- Feat: ユーズの再試行
- Feat: ユーズの文字数制限回避
- Feat: コマンドを並列処理
- Feat: 地震情報のWebSocket再接続
- Feat: 最大震度の要求を設定できる機能
- Feat: 最大震度が不明な場合に投稿するかどうかを設定できる機能
- Feat: デバッグ用とで過去の地震情報を読み込み10秒おきに投稿する機能
# 2026.4.0-beta.0 # 2026.4.0-beta.0
- Feat: 地震発生情報の地域を都道府県でグループ化する機能 - Feat: 地震発生情報の地域を都道府県でグループ化する機能
- Feat: ユーズの再試行 - Feat: ユーズの再試行
@@ -31,7 +61,7 @@
- Del: 各地震情報の情報源の信頼できるかどうかの内容を削除 - Del: 各地震情報の情報源の信頼できるかどうかの内容を削除
- Chg: 津波予報情報の各時刻情報を実際に取得できる値まで削減(例: 2:03:00 > 2:03) - Chg: 津波予報情報の各時刻情報を実際に取得できる値まで削減(例: 2:03:00 > 2:03)
- Fix: フォロー・フォロー解除に失敗した際にreturnできていない問題 - Fix: フォロー・フォロー解除に失敗した際にreturnできていない問題
- Feat: デバッグ用で過去の地震情報を読み込み10秒おきに投稿する機能 - Feat: デバッグ用で過去の地震情報を読み込み10秒おきに投稿する機能
# 2026.4.0-alpha.0 # 2026.4.0-alpha.0
- Breaking: noticeUwuzuを0から作り直しました - Breaking: noticeUwuzuを0から作り直しました
+6
View File
@@ -33,5 +33,11 @@ ueuse:
# 再試行の間隔(ミリ秒) number # 再試行の間隔(ミリ秒) number
# 正数のみが有効です。 # 正数のみが有効です。
retryInterval: 1000 retryInterval: 1000
# 公開されたユーズの自主規制文字数 number
# 返信ではない(公開された)ユーズで使用する自主的な文字数制限です。
# 返信では、サーバーの設定に従います。
# 0にすると、返信ではないユーズでもサーバーの設定に従います。
# 0以上の整数が有効です。
maxLengthWithPublic: 512
# デバッグモードにするかどうか boolean # デバッグモードにするかどうか boolean
debug: false debug: false
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "notice-uwuzu", "name": "notice-uwuzu",
"version": "26.4.0-beta.0", "version": "2026.4.0",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",
"scripts": { "scripts": {
+4 -4
View File
@@ -116,7 +116,7 @@ const processMessage = async (message: any) => {
message.earthquake.maxScale !== -1 && message.earthquake.maxScale !== -1 &&
message.earthquake.maxScale < config.earthquake.requireMaxScale message.earthquake.maxScale < config.earthquake.requireMaxScale
) { ) {
console.log("投稿に必要な最大震度に満たないため、スキップします"); console.log(`最大震度(${scaleMessages[message.earthquake.maxScale]})が投稿に必要な値(${scaleMessages[config.earthquake.requireMaxScale]})に満たないため、スキップします`);
break; break;
} }
@@ -163,7 +163,7 @@ const processMessage = async (message: any) => {
.sort((a, b) => b[1].scale - a[1].scale) .sort((a, b) => b[1].scale - a[1].scale)
.map(([label, { prefs }]) => { .map(([label, { prefs }]) => {
const prefLines = Object.entries(prefs) const prefLines = Object.entries(prefs)
.map(([pref, addrs]) => `${pref}: ${addrs.join("・")}`) .map(([pref, addrs]) => `**${pref}:** ${addrs.join("・")}`)
.join(EOL); .join(EOL);
return `${label}${EOL}${prefLines}`; return `${label}${EOL}${prefLines}`;
@@ -281,7 +281,7 @@ const processMessage = async (message: any) => {
? `から${scaleMessages[String(Math.floor(area.scaleTo))]}` ? `から${scaleMessages[String(Math.floor(area.scaleTo))]}`
: ""), : ""),
kind: kindMessages[area.kindCode] ?? "😕主要動の***到達予想は***ありません。", kind: kindMessages[area.kindCode] ?? "😕主要動の***到達予想は***ありません。",
arrivalTime: area.arrivalTime !== undefined arrivalTime: typeof area.arrivalTime === "string" && area.arrivalTime !== ""
? format(new Date(area.arrivalTime), "yyyy年M月d日 H:mm:ss") ? format(new Date(area.arrivalTime), "yyyy年M月d日 H:mm:ss")
: "不明", : "不明",
}) + EOL.repeat(2); }) + EOL.repeat(2);
@@ -306,7 +306,7 @@ const processMessage = async (message: any) => {
magnitude: message.earthquake.hypocenter.magnitude === undefined || magnitude: message.earthquake.hypocenter.magnitude === undefined ||
message.earthquake.hypocenter.magnitude === -1 message.earthquake.hypocenter.magnitude === -1
? "不明" ? "不明"
: `M${message.earthquake.hypocenter.magnitude}`, : `M${message.earthquake.hypocenter.magnitude.toFixed(1)}`,
areas: areasMsg !== "" areas: areasMsg !== ""
? EOL.repeat(2) + areasMsg.trim() ? EOL.repeat(2) + areasMsg.trim()
: "", : "",
+13 -2
View File
@@ -15,7 +15,6 @@ export default client;
export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: string) => { export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: string) => {
const mem = Memory.memory; const mem = Memory.memory;
const maxLength = mem.max_length;
const excessedMessage = "👉返信に続きがあります。"; const excessedMessage = "👉返信に続きがあります。";
let lines = data.text.split(EOL); let lines = data.text.split(EOL);
@@ -26,7 +25,13 @@ export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: s
count++; count++;
let currentText = ""; let currentText = "";
const limit = maxLength - (excessedMessage.length + EOL.length * 2); const currentMaxLength = (data.replyid !== undefined || firstUniqid !== "")
? mem.max_length
: config.ueuse.maxLengthWithPublic === 0
? mem.max_length
: config.ueuse.maxLengthWithPublic;
const limit = currentMaxLength - (excessedMessage.length + EOL.length * 2);
while (lines.length > 0) { while (lines.length > 0) {
const nextLine = lines[0]; const nextLine = lines[0];
@@ -50,6 +55,8 @@ export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: s
} }
} }
currentText = currentText.trimEnd();
if (lines.length > 0) { if (lines.length > 0) {
currentText += EOL.repeat(2) + excessedMessage; currentText += EOL.repeat(2) + excessedMessage;
} }
@@ -87,5 +94,9 @@ export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: s
firstUniqid = postedUniqid; firstUniqid = postedUniqid;
console.log(`${title}を投稿(${count}):`, postedUniqid); console.log(`${title}を投稿(${count}):`, postedUniqid);
while (lines.length > 0 && lines[0]?.trim() === "") {
lines.shift();
}
} }
} }
+1
View File
@@ -37,6 +37,7 @@ const schema = z.object({
ueuse: z.object({ ueuse: z.object({
maxRetries: z.number().int().positive(), maxRetries: z.number().int().positive(),
retryInterval: z.number().positive(), retryInterval: z.number().positive(),
maxLengthWithPublic: z.number().int().nonnegative(),
}), }),
debug: z.boolean().optional(), debug: z.boolean().optional(),
}); });