send notifs at launch
This commit is contained in:
parent
9226295072
commit
4680b3ac44
3 changed files with 143 additions and 71 deletions
196
index.js
196
index.js
|
|
@ -26,6 +26,8 @@ loadEnv();
|
|||
|
||||
const NTFY_URL = process.env.NTFY_URL ?? "https://ntfy.sh";
|
||||
const NTFY_TOPIC = process.env.NTFY_TOPIC;
|
||||
const NTFY_TOKEN = process.env.NTFY_TOKEN;
|
||||
const TEST_NTFY = process.argv.includes("--test-ntfy");
|
||||
|
||||
// Toutes les 60 secondes par défaut.
|
||||
const POLL_INTERVAL_MS =
|
||||
|
|
@ -36,17 +38,10 @@ if (!NTFY_TOPIC) {
|
|||
process.exit(1);
|
||||
}
|
||||
|
||||
const codex = spawn("codex", ["app-server", "--stdio"], {
|
||||
stdio: ["pipe", "pipe", "inherit"],
|
||||
});
|
||||
|
||||
const lines = readline.createInterface({
|
||||
input: codex.stdout,
|
||||
crlfDelay: Infinity,
|
||||
});
|
||||
|
||||
let nextId = 1;
|
||||
const pending = new Map();
|
||||
let codex = null;
|
||||
let lines = null;
|
||||
|
||||
let previousState = null;
|
||||
let refreshInProgress = false;
|
||||
|
|
@ -120,22 +115,26 @@ function formatDuration(ms) {
|
|||
.join(" ");
|
||||
}
|
||||
|
||||
async function sendResetNotification(oldState, newState) {
|
||||
async function sendNtfyNotification({
|
||||
title,
|
||||
tags,
|
||||
priority = "default",
|
||||
body,
|
||||
}) {
|
||||
const url =
|
||||
`${NTFY_URL.replace(/\/$/, "")}/${encodeURIComponent(NTFY_TOPIC)}`;
|
||||
const headers = {
|
||||
Title: title,
|
||||
Tags: tags,
|
||||
Priority: priority,
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
...(NTFY_TOKEN ? { Authorization: `Bearer ${NTFY_TOKEN}` } : {}),
|
||||
};
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Title: "Codex disponible",
|
||||
Tags: "robot,white_check_mark",
|
||||
Priority: "high",
|
||||
"Content-Type": "text/plain; charset=utf-8",
|
||||
},
|
||||
body:
|
||||
`🚀 Ton quota Codex est de nouveau disponible !\n\n` +
|
||||
`Avant : ${oldState.usedPercent}% utilisé\n` +
|
||||
`Maintenant : ${newState.usedPercent}% utilisé`,
|
||||
headers,
|
||||
body,
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
|
|
@ -143,6 +142,29 @@ async function sendResetNotification(oldState, newState) {
|
|||
}
|
||||
}
|
||||
|
||||
async function sendStartupNotification() {
|
||||
await sendNtfyNotification({
|
||||
title: "Codex Reset Alerts lancé",
|
||||
tags: "robot,eyes",
|
||||
priority: "default",
|
||||
body:
|
||||
`👀 Codex Reset Alerts vient de démarrer.\n\n` +
|
||||
`Surveillance du quota Codex en cours.`,
|
||||
});
|
||||
}
|
||||
|
||||
async function sendResetNotification(oldState, newState) {
|
||||
await sendNtfyNotification({
|
||||
title: "Codex disponible",
|
||||
tags: "robot,white_check_mark",
|
||||
priority: "high",
|
||||
body:
|
||||
`🚀 Ton quota Codex est de nouveau disponible !\n\n` +
|
||||
`Avant : ${oldState.usedPercent}% utilisé\n` +
|
||||
`Maintenant : ${newState.usedPercent}% utilisé`,
|
||||
});
|
||||
}
|
||||
|
||||
function stop(exitCode = 0) {
|
||||
if (shuttingDown) return;
|
||||
|
||||
|
|
@ -157,7 +179,7 @@ function stop(exitCode = 0) {
|
|||
}
|
||||
|
||||
try {
|
||||
codex.kill();
|
||||
codex?.kill();
|
||||
} catch {
|
||||
// Rien.
|
||||
}
|
||||
|
|
@ -337,53 +359,84 @@ async function refreshQuota(source = "polling") {
|
|||
}
|
||||
}
|
||||
|
||||
lines.on("line", async (line) => {
|
||||
let message;
|
||||
function startCodexServer() {
|
||||
codex = spawn("codex", ["app-server", "--stdio"], {
|
||||
stdio: ["pipe", "pipe", "inherit"],
|
||||
});
|
||||
|
||||
try {
|
||||
message = JSON.parse(line);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
lines = readline.createInterface({
|
||||
input: codex.stdout,
|
||||
crlfDelay: Infinity,
|
||||
});
|
||||
|
||||
if (
|
||||
message.id !== undefined &&
|
||||
pending.has(message.id)
|
||||
) {
|
||||
const { resolve, reject } =
|
||||
pending.get(message.id);
|
||||
lines.on("line", async (line) => {
|
||||
let message;
|
||||
|
||||
pending.delete(message.id);
|
||||
|
||||
if (message.error) {
|
||||
reject(
|
||||
new Error(JSON.stringify(message.error))
|
||||
);
|
||||
} else {
|
||||
resolve(message.result);
|
||||
try {
|
||||
message = JSON.parse(line);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (
|
||||
message.id !== undefined &&
|
||||
pending.has(message.id)
|
||||
) {
|
||||
const { resolve, reject } =
|
||||
pending.get(message.id);
|
||||
|
||||
if (
|
||||
message.method ===
|
||||
"account/rateLimits/updated"
|
||||
) {
|
||||
console.log("");
|
||||
console.log(
|
||||
"⚡ Codex signale une modification du quota."
|
||||
);
|
||||
pending.delete(message.id);
|
||||
|
||||
await refreshQuota("événement Codex");
|
||||
}
|
||||
});
|
||||
if (message.error) {
|
||||
reject(
|
||||
new Error(JSON.stringify(message.error))
|
||||
);
|
||||
} else {
|
||||
resolve(message.result);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
message.method ===
|
||||
"account/rateLimits/updated"
|
||||
) {
|
||||
console.log("");
|
||||
console.log(
|
||||
"⚡ Codex signale une modification du quota."
|
||||
);
|
||||
|
||||
await refreshQuota("événement Codex");
|
||||
}
|
||||
});
|
||||
|
||||
codex.on("exit", (code) => {
|
||||
if (!shuttingDown && code !== 0) {
|
||||
console.error(
|
||||
`❌ Codex App Server s'est arrêté avec le code ${code}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
await sendStartupNotification();
|
||||
console.log("📱 Notification ntfy de démarrage envoyée.");
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"❌ Échec de la notification ntfy de démarrage :",
|
||||
error.message
|
||||
);
|
||||
}
|
||||
|
||||
console.log(
|
||||
"🔌 Connexion à Codex App Server..."
|
||||
);
|
||||
|
||||
startCodexServer();
|
||||
|
||||
await request("initialize", {
|
||||
clientInfo: {
|
||||
name: "codex-reset-alerts",
|
||||
|
|
@ -428,15 +481,24 @@ process.on("SIGTERM", () => {
|
|||
stop(0);
|
||||
});
|
||||
|
||||
codex.on("exit", (code) => {
|
||||
if (!shuttingDown && code !== 0) {
|
||||
console.error(
|
||||
`❌ Codex App Server s'est arrêté avec le code ${code}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
main().catch((error) => {
|
||||
console.error("❌", error);
|
||||
stop(1);
|
||||
});
|
||||
if (TEST_NTFY) {
|
||||
sendResetNotification(
|
||||
{ usedPercent: 100 },
|
||||
{ usedPercent: 0 }
|
||||
)
|
||||
.then(() => {
|
||||
console.log("📱 Notification ntfy de test envoyée.");
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
"❌ Échec de la notification ntfy de test :",
|
||||
error.message
|
||||
);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
} else {
|
||||
main().catch((error) => {
|
||||
console.error("❌", error);
|
||||
stop(1);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue