My Changes

This commit is contained in:
MarcUs7 2024-12-27 12:37:26 +01:00
parent eaef31dc1e
commit 9beb9ff0c7
4 changed files with 172 additions and 41 deletions

148
config.js
View file

@ -1,8 +1,8 @@
export default { export default {
interval : 15, // Interval in minutes between each pulse interval : 1440, // Interval in minutes between each pulse; 1 day (24 * 60)
nDataPoints : 90, // Number of datapoints to display on the dashboard nDataPoints : 90, // Number of datapoints to display on the dashboard
responseTimeGood : 300, // In milliseconds, this and below will be green responseTimeGood : 500, // In milliseconds, this and below will be green
responseTimeWarning : 600, // In milliseconds, above this will be red responseTimeWarning : 1000, // In milliseconds, above this will be red
timeout : 5000, // In milliseconds, requests will be aborted above this timeout : 5000, // In milliseconds, requests will be aborted above this
verbose : true, // Whether or not to output pulse messages in the console verbose : true, // Whether or not to output pulse messages in the console
readableStatusJson : true, // Format status.json to be human readable readableStatusJson : true, // Format status.json to be human readable
@ -33,19 +33,149 @@ export default {
consecutiveHighLatencyNotify : 3, // After how many consecutive High latency events should we send a notification consecutiveHighLatencyNotify : 3, // After how many consecutive High latency events should we send a notification
sites : [ // List of sites to monitor sites : [ // List of sites to monitor
{ {
id : 'google', // optional id : 'marcus7i', // optional
name : 'Google', name : 'MarcUs7i.Net',
endpoints : [ // Each site is a bunch of endpoints that can be tested endpoints : [ // Each site is a bunch of endpoints that can be tested
{ {
id : 'homepage', // optional id : 'homepage', // optional
name : 'Homepage', // optional name : 'Homepage', // optional
link : 'https://www.google.com', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false link : 'https://marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://www.google.com', // required url : 'https://marcus7i.net', // required
request : { // optional, fetch options request : { // optional, fetch options
method: 'GET', method: 'GET',
}, },
mustFind : 'Feeling Lucky', // optional, String | Array | Regex | Function | AsyncFunction mustFind : 'MarcUs7i.Net', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : /Page not found/i, // optional, String | Array | Regex | Function | AsyncFunction mustNotFind : ["Page not found", "Error", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'airin', // optional
name : 'Airin', // optional
link : 'https://airin.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://airin.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : 'Airin', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'anywave', // optional
name : 'Anywave', // optional
link : 'https://anywave.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://anywave.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : 'Anywave', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'btcnd', // optional
name : 'Bitcoin Node', // optional
link : 'https://btcnd.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://btcnd.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : 'Anywave', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200, 520], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'fs', // optional
name : 'File Sharing', // optional
link : 'https://fs.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://fs.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : 'nginx', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200, 403], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'git', // optional
name : 'MarcUs7i Git', // optional
link : 'https://git.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://git.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : 'Home', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'ollama', // optional
name : 'Ollama Webui', // optional
link : 'https://ollama.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://ollama.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : '', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'ollama-api', // optional
name : 'Ollama API', // optional
link : 'https://ollama.marcus7i.net/api/chat/completions', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://ollama.marcus7i.net/api/chat/completions', // required
request : { // optional, fetch options
method: 'POST',
},
mustFind : '{\"detail\":\"Not authenticated\"}', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200, 401], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'sd', // optional
name : 'Stable Diffusion API', // optional
link : 'https://sd.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://sd.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : 'Login', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'u', // optional
name : 'Link shortener', // optional
link : 'https://u.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://u.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : '', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
},
{
id : 'xmrnd', // optional
name : 'Monero Node', // optional
link : 'https://xmrnd.marcus7i.net', // optional, for notifications and dashboard only, [defaults to endpoint.url], can be disabled by setting it to false
url : 'https://xmrnd.marcus7i.net', // required
request : { // optional, fetch options
method: 'GET',
},
mustFind : '', // optional, String | Array | Regex | Function | AsyncFunction
mustNotFind : ["Page not found", "cloudflare"], // optional, String | Array | Regex | Function | AsyncFunction
customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors customCheck : async (content, response)=>{return true;}, // optional, Function | AsyncFunction -> Run your own custom checks return false in case of errors
validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299] validStatus : [200], // optional, Which http status should be considered non errors [defaults to 200-299]
} }

View file

@ -1,7 +1,7 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>aPulse — Server Status</title> <title>MarcUs7i - Status</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="favicon.png"> <link rel="shortcut icon" href="favicon.png">
@ -14,16 +14,9 @@
</head> </head>
<body> <body>
<header> <header>
<h1><img src="logo.svg" alt="aPulse" />aPulse</h1> <h1><img src="logo.svg" alt="MarcUs7i - Status" />MarcUs7i - Status</h1>
</header> </header>
<error-notice></error-notice> <error-notice></error-notice>
<main></main> <main></main>
<footer>
Powered by <a href="https://github.com/ybouane/aPulse">aPulse</a> — Made with 🤍 by <a href="https://x.com/ybouane">@ybouane</a>
</footer>
<div id="github-button">
<a class="github-button" href="https://github.com/ybouane" data-color-scheme="no-preference: light; light: light; dark: dark;" data-size="large" aria-label="Follow @ybouane on GitHub">Follow @ybouane</a>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</div>
</body> </body>
</html> </html>

View file

@ -1 +0,0 @@
{}

View file

@ -43,18 +43,17 @@ const sendTelegramMessage = async (text) => {
return await response.json(); return await response.json();
}; };
const sendDiscordMessage = async (text) => { const sendDiscordMessage = async (text) => {
const webhookUrl = 'YOUR_DISCORD_WEBHOOK_URL'; try {
const response = await fetch(config.discord.webhookUrl, { const response = await fetch(config.discord.webhookUrl, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ body: JSON.stringify({ content: text })
content: text });
}) const data = await response.json();
}); return data;
if (!response.ok) { } catch (error) {
throw new Error(`[Discord] Failed to send message: ${response.statusText}`); console.error('Error sending Discord message:', error);
} }
return await response.json();
}; };
const sendSMSMessage = async (text) => { const sendSMSMessage = async (text) => {
const response = await fetch(`https://api.twilio.com/2010-04-01/Accounts/${config.twilio.accountSid}/Messages.json`, { const response = await fetch(`https://api.twilio.com/2010-04-01/Accounts/${config.twilio.accountSid}/Messages.json`, {
@ -112,16 +111,20 @@ const sendEmailMessage = async (text) => {
return await response.json(); return await response.json();
}; };
const sendNotification = async (message) => { const sendNotification = async (message) => {
if(config.telegram?.botToken && config.telegram?.chatId) try {
await sendTelegramMessage(message); if(config.telegram?.botToken && config.telegram?.chatId)
if(config.slack?.botToken && config.slack?.channelId) await sendTelegramMessage(message);
await sendSlackMessage(message); if(config.slack?.botToken && config.slack?.channelId)
if(config.discord?.webhookUrl) await sendSlackMessage(message);
await sendDiscordMessage(message); if(config.discord?.webhookUrl)
if(config.twilio?.accountSid && config.twilio?.accountToken && config.twilio?.toNumber && config.twilio?.twilioNumber) await sendDiscordMessage(message);
await sendSMSMessage(message); if(config.twilio?.accountSid && config.twilio?.accountToken && config.twilio?.toNumber && config.twilio?.twilioNumber)
if(config.sendgrid?.apiKey && config.sendgrid?.toEmail && config.sendgrid?.toFromEmail) await sendSMSMessage(message);
await sendEmailMessage(message); if(config.sendgrid?.apiKey && config.sendgrid?.toEmail && config.sendgrid?.toFromEmail)
await sendEmailMessage(message);
} catch (error) {
console.error('Error sending notification:', error);
}
} }
while(true) { while(true) {
@ -131,7 +134,13 @@ while(true) {
try { try {
try { try {
status = JSON.parse((await fs.readFile(statusFile)).toString()); // We re-read the file each time in case it was manually modified. status = JSON.parse((await fs.readFile(statusFile)).toString()); // We re-read the file each time in case it was manually modified.
} catch(e) {console.error(`Could not find status.json file [${statusFile}], will create it.`)} } catch(e) {
if (e instanceof SyntaxError) {
console.error(`Syntax error in status.json file [${statusFile}]:`, e);
} else {
console.error(`Could not find status.json file [${statusFile}], will create it.`);
}
}
status = status || {}; status = status || {};
status.sites = status.sites || {}; status.sites = status.sites || {};
status.config = { status.config = {