Compare commits

..

16 Commits

Author SHA1 Message Date
last2014 16b1b9d2ab Merge pull request '2026.4.3' (#16) from develop into main
Reviewed-on: #16
2026-05-03 10:19:41 +00:00
last2014 f0246d7ce9 Merge branch 'main' into develop 2026-05-03 10:19:33 +00:00
last2014 165500e71d 2026.4.3 / Chg: コマンド実行の際にメンションと通知を時系列にソートしないように 2026-05-03 19:18:58 +09:00
last2014 4f2be0e0ed Chg: forループ内でlastRead*を記録するように / Chg: lastRead*を時刻ベースに 2026-05-03 19:12:27 +09:00
last2014 7f2ef21557 Chg: コマンド実行の際にメンションと通知を時系列にソートするように 2026-05-03 18:49:01 +09:00
last2014 b33b998ae4 Merge pull request '2026.4.2' (#15) from develop into main
Reviewed-on: #15
2026-05-03 07:36:22 +00:00
last2014 e17da1686d Merge branch 'main' into develop 2026-05-03 07:36:16 +00:00
last2014 ab06f4ceec 2026.4.2 / Fix: id除外が機能しない問題 2026-05-03 16:35:59 +09:00
last2014 47fe174ac6 Merge pull request '2026.4.1' (#14) from develop into main
Reviewed-on: #14
2026-05-03 07:11:02 +00:00
last2014 747bf00e7b Merge branch 'main' into develop 2026-05-03 07:10:56 +00:00
last2014 3baa55bd29 Merge branch 'develop' of https://gitea.last2014.com/last2014/noticeUwuzu into develop 2026-05-03 16:10:06 +09:00
last2014 90e9d614f9 2026.4.1 / Chg: notificationsもfor内でlastReadを更新しないように 2026-05-03 16:09:04 +09:00
last2014 41dc68340f Merge pull request '2026.4.0' (#13) from develop into main
Reviewed-on: #13
2026-05-03 06:14:47 +00:00
last2014 0dcbbf993c Merge branch 'main' into develop 2026-05-03 06:14:42 +00:00
last2014 fbef68ce79 2026.4.0 2026-05-03 15:14:01 +09:00
last2014 953c49583c Chg: 最大震度が投稿に必要な値に満たない場合のコンソール表示を変更 / Feat: 返信ではないユーズの自主的な文字数制限 2026-05-03 15:10:37 +09:00
9 changed files with 92 additions and 24 deletions
+41 -1
View File
@@ -1,3 +1,43 @@
# 2026.4.3
- Chg: forループ内でlastReadを記録するように
- Chg: lastReadを時刻ベースに
# 2026.4.2
- Fix: id除外が機能しない問題
# 2026.4.1
- Chg: notificationsもfor内でlastReadを更新しないように
# 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
- Feat: 地震発生情報の地域を都道府県でグループ化する機能
- Feat: ユーズの再試行
@@ -31,7 +71,7 @@
- Del: 各地震情報の情報源の信頼できるかどうかの内容を削除
- Chg: 津波予報情報の各時刻情報を実際に取得できる値まで削減(例: 2:03:00 > 2:03)
- Fix: フォロー・フォロー解除に失敗した際にreturnできていない問題
- Feat: デバッグ用で過去の地震情報を読み込み10秒おきに投稿する機能
- Feat: デバッグ用で過去の地震情報を読み込み10秒おきに投稿する機能
# 2026.4.0-alpha.0
- Breaking: noticeUwuzuを0から作り直しました
+2
View File
@@ -22,6 +22,8 @@ uwuzu v1.6.3以上で利用可能です。
- 地震情報のWebSocketの接続先をテスト用サンドボックスに変更
P2P地震情報の接続先を本番環境から[テスト用サンドボックスのエンドポイント](https://www.p2pquake.net/develop/json_api_v2/)に変更します。
そのため、最新の情報は配信されません。
- 地震情報のid除外を無効化
地震情報のid除外を記録も確認も行わなくなります。
- i18nextのdebugを有効化
[i18nextでのdebug](https://www.i18next.com/overview/configuration-options#logging)が有効化されます。
+6
View File
@@ -33,5 +33,11 @@ ueuse:
# 再試行の間隔(ミリ秒) number
# 正数のみが有効です。
retryInterval: 1000
# 公開されたユーズの自主規制文字数 number
# 返信ではない(公開された)ユーズで使用する自主的な文字数制限です。
# 返信では、サーバーの設定に従います。
# 0にすると、返信ではないユーズでもサーバーの設定に従います。
# 0以上の整数が有効です。
maxLengthWithPublic: 512
# デバッグモードにするかどうか boolean
debug: false
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "notice-uwuzu",
"version": "26.4.0-beta.0",
"version": "2026.4.3",
"type": "module",
"main": "dist/index.js",
"scripts": {
+16 -9
View File
@@ -32,9 +32,6 @@ try {
if (notification.category !== "reply" || typeof notification.valueid !== "string")
continue;
if (lastReadReply === notification.valueid)
break;
const ueuseResponse = await client.request("ueuse/get", {
uniqid: notification.valueid,
});
@@ -44,12 +41,17 @@ try {
continue;
}
const time = new Date(ueuseResponse.data[0].datetime).getTime();
if (index === 0) {
const mem = Memory.memory;
mem.lastReadReply = ueuseResponse.data[0].uniqid;
mem.lastReadReply = time;
Memory.memory = mem;
}
if (lastReadReply >= time)
break;
ueuses.push(ueuseResponse.data[0]);
}
} else {
@@ -68,14 +70,19 @@ try {
const mem = Memory.memory;
const lastReadMention = mem.lastReadMention;
mem.lastReadMention = mentions[0]?.uniqid ?? lastReadMention;
Memory.memory = mem;
for (const mention of mentions) {
if (lastReadMention === mention.uniqid) {
break;
for (const [index, mention] of mentions.entries()) {
const time = new Date(mention.datetime).getTime();
if (index === 0) {
const mem = Memory.memory;
mem.lastReadMention = time;
Memory.memory = mem;
}
if (lastReadMention >= time)
break;
ueuses.push(mention);
}
} else {
+6 -5
View File
@@ -68,7 +68,8 @@ if (config.earthquake?.useHistoryData) {
processMessage(message);
if (!config.debug) {
mem.processedInfo.concat([id]);
const mem = Memory.memory;
mem.processedInfo = mem.processedInfo.concat([id]);
Memory.memory = mem;
}
});
@@ -116,7 +117,7 @@ const processMessage = async (message: any) => {
message.earthquake.maxScale !== -1 &&
message.earthquake.maxScale < config.earthquake.requireMaxScale
) {
console.log("投稿に必要な最大震度に満たないため、スキップします");
console.log(`最大震度(${scaleMessages[message.earthquake.maxScale]})が投稿に必要な値(${scaleMessages[config.earthquake.requireMaxScale]})に満たないため、スキップします`);
break;
}
@@ -163,7 +164,7 @@ const processMessage = async (message: any) => {
.sort((a, b) => b[1].scale - a[1].scale)
.map(([label, { prefs }]) => {
const prefLines = Object.entries(prefs)
.map(([pref, addrs]) => `${pref}: ${addrs.join("・")}`)
.map(([pref, addrs]) => `**${pref}:** ${addrs.join("・")}`)
.join(EOL);
return `${label}${EOL}${prefLines}`;
@@ -281,7 +282,7 @@ const processMessage = async (message: any) => {
? `から${scaleMessages[String(Math.floor(area.scaleTo))]}`
: ""),
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")
: "不明",
}) + EOL.repeat(2);
@@ -306,7 +307,7 @@ const processMessage = async (message: any) => {
magnitude: message.earthquake.hypocenter.magnitude === undefined ||
message.earthquake.hypocenter.magnitude === -1
? "不明"
: `M${message.earthquake.hypocenter.magnitude}`,
: `M${message.earthquake.hypocenter.magnitude.toFixed(1)}`,
areas: areasMsg !== ""
? 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) => {
const mem = Memory.memory;
const maxLength = mem.max_length;
const excessedMessage = "👉返信に続きがあります。";
let lines = data.text.split(EOL);
@@ -26,7 +25,13 @@ export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: s
count++;
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) {
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) {
currentText += EOL.repeat(2) + excessedMessage;
}
@@ -87,5 +94,9 @@ export const createUeuse = async (data: ApiMap["ueuse/create"]["body"], title: s
firstUniqid = 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({
maxRetries: z.number().int().positive(),
retryInterval: z.number().positive(),
maxLengthWithPublic: z.number().int().nonnegative(),
}),
debug: z.boolean().optional(),
});
+2 -2
View File
@@ -11,8 +11,8 @@ class MemoryClass {
writeFileSync(path, JSON.stringify({
processedInfo: [],
permissions: {},
lastReadMention: "",
lastReadReply: "",
lastReadMention: 0,
lastReadReply: 0,
userid: "",
max_length: 0,
}));