2026.5.1 #18
@@ -3,18 +3,19 @@
|
|||||||
uwuzu v1.6.7以上で利用可能です。
|
uwuzu v1.6.7以上で利用可能です。
|
||||||
|
|
||||||
## 機能
|
## 機能
|
||||||
- 時報
|
- 時報
|
||||||
毎時0分に「h:00になりました。」と投稿します。
|
毎時0分に「h:00になりました。」と投稿します。
|
||||||
- 天気予報
|
- 天気予報
|
||||||
[天気予報 API(livedoor 天気互換)](https://weather.tsukumijima.net/)を利用して、毎日7:00に天気予報を投稿します。
|
[天気予報 API(livedoor 天気互換)](https://weather.tsukumijima.net/)を利用して、毎日7:00及び18:00に天気予報を投稿します。
|
||||||
- 地震情報
|
18:00は明日の天気予報を投稿します。
|
||||||
|
- 地震情報
|
||||||
[P2P地震情報](https://www.p2pquake.net/)のWebSocket APIを利用して、以下の情報を受信した際に投稿します。
|
[P2P地震情報](https://www.p2pquake.net/)のWebSocket APIを利用して、以下の情報を受信した際に投稿します。
|
||||||
- 地震発生
|
- 地震発生
|
||||||
- 緊急地震速報(警報)
|
- 緊急地震速報(警報)
|
||||||
- 津波予報
|
- 津波予報
|
||||||
- 新年迎春
|
- 新年迎春
|
||||||
毎年1/1 0:00に投稿します。
|
毎年1/1 0:00に投稿します。
|
||||||
- デバッグモード
|
- デバッグモード
|
||||||
設定で有効化することで、以下の機能が利用できます。
|
設定で有効化することで、以下の機能が利用できます。
|
||||||
開発以外では使用しないでください。
|
開発以外では使用しないでください。
|
||||||
- NODE_TLS_REJECT_UNAUTHORIZED=1
|
- NODE_TLS_REJECT_UNAUTHORIZED=1
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"@types/node": "^25.5.2",
|
"@types/node": "^25.5.2",
|
||||||
"@types/ws": "^8.18.1",
|
"@types/ws": "^8.18.1",
|
||||||
"better-uwuzu-sdk": "git+https://gitea.last2014.com/last2014/better-uwuzu-sdk.git#1.1.7",
|
"better-uwuzu-sdk": "git+https://gitea.last2014.com/last2014/better-uwuzu-sdk.git#1.1.7",
|
||||||
|
"cron-parser": "^5.5.0",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "^4.1.0",
|
||||||
"fs": "0.0.1-security",
|
"fs": "0.0.1-security",
|
||||||
"i18next": "^26.0.3",
|
"i18next": "^26.0.3",
|
||||||
|
|||||||
Generated
+17
@@ -17,6 +17,9 @@ importers:
|
|||||||
better-uwuzu-sdk:
|
better-uwuzu-sdk:
|
||||||
specifier: git+https://gitea.last2014.com/last2014/better-uwuzu-sdk.git#1.1.7
|
specifier: git+https://gitea.last2014.com/last2014/better-uwuzu-sdk.git#1.1.7
|
||||||
version: git+https://gitea.last2014.com/last2014/better-uwuzu-sdk.git#8017146b1a2d6264d051b54afccdd46571b5fd00
|
version: git+https://gitea.last2014.com/last2014/better-uwuzu-sdk.git#8017146b1a2d6264d051b54afccdd46571b5fd00
|
||||||
|
cron-parser:
|
||||||
|
specifier: ^5.5.0
|
||||||
|
version: 5.5.0
|
||||||
date-fns:
|
date-fns:
|
||||||
specifier: ^4.1.0
|
specifier: ^4.1.0
|
||||||
version: 4.1.0
|
version: 4.1.0
|
||||||
@@ -298,6 +301,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
|
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
|
||||||
engines: {node: ^12.20.0 || >=14}
|
engines: {node: ^12.20.0 || >=14}
|
||||||
|
|
||||||
|
cron-parser@5.5.0:
|
||||||
|
resolution: {integrity: sha512-oML4lKUXxizYswqmxuOCpgFS8BNUJpIu6k/2HVHyaL8Ynnf3wdf9tkns0yRdJLSIjkJ+b0DXHMZEHGpMwjnPww==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
date-fns@4.1.0:
|
date-fns@4.1.0:
|
||||||
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
|
resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==}
|
||||||
|
|
||||||
@@ -475,6 +482,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
|
resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
|
luxon@3.7.2:
|
||||||
|
resolution: {integrity: sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
|
||||||
math-intrinsics@1.1.0:
|
math-intrinsics@1.1.0:
|
||||||
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -882,6 +893,10 @@ snapshots:
|
|||||||
|
|
||||||
commander@9.5.0: {}
|
commander@9.5.0: {}
|
||||||
|
|
||||||
|
cron-parser@5.5.0:
|
||||||
|
dependencies:
|
||||||
|
luxon: 3.7.2
|
||||||
|
|
||||||
date-fns@4.1.0: {}
|
date-fns@4.1.0: {}
|
||||||
|
|
||||||
decompress-response@6.0.0:
|
decompress-response@6.0.0:
|
||||||
@@ -1058,6 +1073,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
which-typed-array: 1.1.20
|
which-typed-array: 1.1.20
|
||||||
|
|
||||||
|
luxon@3.7.2: {}
|
||||||
|
|
||||||
math-intrinsics@1.1.0: {}
|
math-intrinsics@1.1.0: {}
|
||||||
|
|
||||||
merge2@1.4.1: {}
|
merge2@1.4.1: {}
|
||||||
|
|||||||
@@ -9,8 +9,13 @@ import unfollowCommand from "@/feature/command/unfollow";
|
|||||||
import miqCommand from "@/feature/command/miq";
|
import miqCommand from "@/feature/command/miq";
|
||||||
import initI18n from "@/lib/i18n";
|
import initI18n from "@/lib/i18n";
|
||||||
import config from "@/lib/config";
|
import config from "@/lib/config";
|
||||||
|
import CronExpressionParser from "cron-parser";
|
||||||
|
|
||||||
await initI18n();
|
await initI18n();
|
||||||
|
|
||||||
|
const next = BigInt(CronExpressionParser.parse(`*/${config.command.interval} * * * *`).next().getTime() * 1_000_000);
|
||||||
|
while (process.hrtime.bigint() > next) {}
|
||||||
|
|
||||||
console.log("コマンドの処理を行います");
|
console.log("コマンドの処理を行います");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
+17
-16
@@ -1,25 +1,26 @@
|
|||||||
import { createUeuse } from "@/lib/client";
|
import { createUeuse } from "@/lib/client";
|
||||||
import initI18n from "@/lib/i18n";
|
import initI18n from "@/lib/i18n";
|
||||||
|
import CronExpressionParser from "cron-parser";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { parentPort } from "node:worker_threads";
|
|
||||||
|
|
||||||
await initI18n();
|
await initI18n();
|
||||||
|
|
||||||
parentPort?.on("message", async () => {
|
const next = BigInt(CronExpressionParser.parse("0 0 1 1 *").next().getTime() * 1_000_000);
|
||||||
console.log("新年迎春の投稿を行います");
|
while (process.hrtime.bigint() > next) {}
|
||||||
|
|
||||||
try {
|
console.log("新年迎春の投稿を行います");
|
||||||
await createUeuse({
|
|
||||||
text: i18next.t("hnyNotice", { year: String(new Date().getFullYear()) }),
|
|
||||||
}, "新年迎春");
|
|
||||||
|
|
||||||
console.log("新年迎春投稿時刻:", format(new Date(), "yyyy/M/d H:mm:ss:SSS"));
|
try {
|
||||||
process.exit(0);
|
await createUeuse({
|
||||||
} catch (err: any) {
|
text: i18next.t("hnyNotice", { year: String(new Date().getFullYear()) }),
|
||||||
console.error("message" in err
|
}, "新年迎春");
|
||||||
? err.message
|
|
||||||
: err);
|
console.log("新年迎春投稿時刻:", format(new Date(), "yyyy/M/d H:mm:ss:SSS"));
|
||||||
process.exit(1);
|
process.exit(0);
|
||||||
}
|
} catch (err: any) {
|
||||||
});
|
console.error("message" in err
|
||||||
|
? err.message
|
||||||
|
: err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
import { createUeuse } from "@/lib/client";
|
import { createUeuse } from "@/lib/client";
|
||||||
import initI18n from "@/lib/i18n";
|
import initI18n from "@/lib/i18n";
|
||||||
|
import CronExpressionParser from "cron-parser";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
|
|
||||||
await initI18n();
|
await initI18n();
|
||||||
|
|
||||||
|
const next = BigInt(CronExpressionParser.parse("0 * * * *").next().getTime() * 1_000_000);
|
||||||
|
while (process.hrtime.bigint() > next) {}
|
||||||
|
|
||||||
console.log("時報の投稿を行います");
|
console.log("時報の投稿を行います");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import client from "@/lib/client";
|
|||||||
import config from "@/lib/config";
|
import config from "@/lib/config";
|
||||||
import initI18n from "@/lib/i18n";
|
import initI18n from "@/lib/i18n";
|
||||||
import Memory from "@/lib/memory";
|
import Memory from "@/lib/memory";
|
||||||
|
import CronExpressionParser from "cron-parser";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import { readFileSync } from "node:fs";
|
import { readFileSync } from "node:fs";
|
||||||
import { EOL } from "node:os";
|
import { EOL } from "node:os";
|
||||||
@@ -63,6 +64,13 @@ if (
|
|||||||
workerData.startsWith("scheduledWeatherNotice")
|
workerData.startsWith("scheduledWeatherNotice")
|
||||||
) {
|
) {
|
||||||
await initI18n();
|
await initI18n();
|
||||||
|
|
||||||
|
const cronStr = workerData.endsWith("Tomorrow")
|
||||||
|
? "0 18 * * *"
|
||||||
|
: "0 7 * * *"
|
||||||
|
const next = BigInt(CronExpressionParser.parse(cronStr).next().getTime() * 1_000_000);
|
||||||
|
while (process.hrtime.bigint() > next) {}
|
||||||
|
|
||||||
console.log("天気予報の投稿を行います");
|
console.log("天気予報の投稿を行います");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
+13
-13
@@ -31,34 +31,34 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
schedule("0 * * * *", async () => {
|
schedule("56 59 * * * *", async () => {
|
||||||
new Worker(`${import.meta.dirname}/feature/timeNotice.js`);
|
new Worker(`${import.meta.dirname}/feature/timeNotice.js`);
|
||||||
});
|
});
|
||||||
|
|
||||||
schedule("0 7 * * *", async () => {
|
schedule("56 59 6 * * *", async () => {
|
||||||
new Worker(`${import.meta.dirname}/feature/weatherNotice.js`, {
|
new Worker(`${import.meta.dirname}/feature/weatherNotice.js`, {
|
||||||
workerData: "scheduledWeatherNotice",
|
workerData: "scheduledWeatherNotice",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
schedule("0 18 * * *", async () => {
|
schedule("56 59 17 * * *", async () => {
|
||||||
new Worker(`${import.meta.dirname}/feature/weatherNotice.js`, {
|
new Worker(`${import.meta.dirname}/feature/weatherNotice.js`, {
|
||||||
workerData: "scheduledWeatherNoticeTomorrow",
|
workerData: "scheduledWeatherNoticeTomorrow",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
schedule(`*/${config.command.interval} * * * *`, async () => {
|
const interval = config.command.interval;
|
||||||
|
const targetMinutes = [];
|
||||||
|
for (let i = interval - 1; i < 60; i += interval) {
|
||||||
|
targetMinutes.push(i);
|
||||||
|
}
|
||||||
|
const minutesStr = targetMinutes.join(",");
|
||||||
|
schedule(`56 ${minutesStr} * * * *`, async () => {
|
||||||
new Worker(`${import.meta.dirname}/feature/command/index.js`);
|
new Worker(`${import.meta.dirname}/feature/command/index.js`);
|
||||||
});
|
});
|
||||||
|
|
||||||
let hnyWorker: Worker | undefined = undefined;
|
schedule("56 59 23 31 12 *", () => {
|
||||||
|
new Worker(`${import.meta.dirname}/feature/hnyNotice.js`);
|
||||||
schedule("57 59 23 31 12 *", () => {
|
|
||||||
hnyWorker = new Worker(`${import.meta.dirname}/feature/hnyNotice.js`);
|
|
||||||
});
|
|
||||||
|
|
||||||
schedule("0 0 0 1 1 *", () => {
|
|
||||||
hnyWorker?.postMessage("");
|
|
||||||
});
|
});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error("message" in err
|
console.error("message" in err
|
||||||
|
|||||||
Reference in New Issue
Block a user