feat: WordPress Monitor API + Site Availability Checker

- Add POST /api/wp-monitor endpoint for WP plugin data
- Add GET /api/wp-monitor for listing monitored sites
- Add checkSiteAvailability() function for HTTP health checks
- Add checkAllSitesAvailability() for batch checking
- Add /api/scripts/check-sites.ts for cron execution
- Add POST /api/monitor/check-sites for manual trigger

DeskCRM Task: #1556

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-04 23:12:32 +00:00
parent 853b2f526e
commit 13608a69bf
10 changed files with 840 additions and 1 deletions

View File

@@ -25,6 +25,105 @@ interface CategorySummary {
critical: number
}
/**
* Check if a URL is accessible (HTTP HEAD request)
*/
export async function checkSiteAvailability(url: string, timeout = 10000): Promise<{
available: boolean
statusCode?: number
responseTime?: number
error?: string
}> {
const startTime = Date.now()
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), timeout)
try {
const response = await fetch(url, {
method: 'HEAD',
signal: controller.signal,
headers: {
'User-Agent': 'Descomplicar-Monitor/1.0'
}
})
clearTimeout(timeoutId)
const responseTime = Date.now() - startTime
return {
available: response.ok || response.status < 500,
statusCode: response.status,
responseTime
}
} catch (error) {
clearTimeout(timeoutId)
return {
available: false,
error: (error as Error).message,
responseTime: Date.now() - startTime
}
}
}
/**
* Check all sites and update their availability status
*/
export async function checkAllSitesAvailability(): Promise<{
checked: number
up: number
down: number
results: any[]
}> {
// Get all sites from monitoring table
const [sites] = await db.query<RowDataPacket[]>(`
SELECT id, name, details FROM tbl_eal_monitoring
WHERE category = 'site'
`)
const results: any[] = []
let up = 0
let down = 0
for (const site of sites) {
const details = typeof site.details === 'string' ? JSON.parse(site.details) : site.details
const siteUrl = details?.site_url || `https://${site.name}`
const check = await checkSiteAvailability(siteUrl)
// Update status if site is down
if (!check.available) {
await db.query(
'UPDATE tbl_eal_monitoring SET status = ?, last_check = NOW() WHERE id = ?',
['down', site.id]
)
down++
} else {
// If was down and now is up, set to 'up' (will be replaced by plugin data later)
const currentStatus = details?.health?.status || 'ok'
if (currentStatus === 'down') {
await db.query(
'UPDATE tbl_eal_monitoring SET status = ?, last_check = NOW() WHERE id = ?',
['up', site.id]
)
}
up++
}
results.push({
name: site.name,
url: siteUrl,
...check
})
}
return {
checked: sites.length,
up,
down,
results
}
}
export async function getMonitoringData() {
// Get all items
const [items] = await db.query<RowDataPacket[]>(`