 @sendgrid/mail     ^8.1.4  →    ^8.1.6
 axios              ^1.8.4  →   ^1.20.0
 bcrypt             ^5.1.1  →    ^6.0.0
 discord.js       ^14.18.0  →  ^14.27.0
 ejs               ^3.1.10  →    ^7.0.1
 express           ^4.21.2  →    ^5.3.0
 express-session   ^1.18.1  →   ^1.19.0
 form-data          ^4.0.2  →    ^4.0.6
 multer             ^1.4.4  →    ^2.4.0
 mysql2            ^3.14.0  →   ^3.24.5
 ping               ^0.4.4  →    ^1.0.0
 twilio             ^5.5.1  →    ^6.2.0

update to node 24 from node 20
update file structure
Checks for status are updated to new pinging methods:
- Addresses starting with http or https use fetch API to ping, all 200 and 400 statues return good while 500 statuses return offline
- net.Socket is used fort all port pings with a 15s timeout
- Bare domains (no url proto) use fetch GET requests like URLs, if no response it falls back to a IP ping (ICMP) to check and decides from there.
- Bare IP with no port uses ICMP ping.promise.probe(ip, {timeout: 10}).

---
RAW:
Address	Check	Online when
Starts with http:// or https://	HTTP GET with global fetch and AbortSignal.timeout(15000), following redirects	Any status below 500
Has a port (IP or domain)	TCP connect with net.Socket and a 15s timeout	It connects (same as today)
Bare domain (not an IP), no port	HTTPS GET to https://<domain>. If there is no HTTP response at all (DNS failure, connection refused, TLS error or timeout), fall back to ICMP	Any status below 500, or the fallback ping succeeds
Bare IP, no port	ICMP with ping.promise.probe(ip, {timeout: 10}) (the v1.0.0 API, confirmed in node_modules/ping/lib)	alive

---

The ICMP fallback keeps existing bare-domain entries from going offline when they answer ping but don't serve HTTP. A site that returns 5xx is still marked offline.

- midnight rollover.
    - Same history average calculation as now.
    - Rewritten with connection.promise(), so minutePause clears only after every row is written. Today it clears before the async queries finish.
    - Replace the DELETE-then-INSERT of pings with a single UPDATE pings SET totalDowntime=NULL, downtime=? WHERE sid=?.
    - Remove the inline history delete, which moves to the cleanup job below.

- Daily cleanup job (30 0 * * *, also run once 10s after boot so existing bloated tables shrink straight away):

    - Delete history rows where CAST(date AS UNSIGNED) is older than 90 days.
    - Delete orphaned history rows whose serviceId is no longer in services.
    - Delete orphaned pings rows whose sid is no longer in services. pings has one row per service and no timestamp, so orphans are the only rows that pile up.
    - Each delete runs in batches of LIMIT 5000, looping until affectedRows < 5000, so a huge table doesn't lock the site.
    - Log one summary line through logger.log.

- New indexes allow the main status page to show data and load much faster

[CLEANUP]: Removed 5033 history rows older than 90 days, 0 orphaned history rows and 0 orphaned pings.

- new refreshed UI
- Toggle for auto refresh every 60 seconds
- 