Fixed and changes
This commit is contained in:
@@ -1,53 +1,55 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
// Configuration - Update these URLs to match your actual services
|
||||
const SERVICES = [
|
||||
{ name: 'Website', url: 'https://www.akkolli.net' },
|
||||
{ name: 'Gitea', url: 'https://code.akkolli.net' },
|
||||
{ name: 'Nextcloud', url: 'http://localhost:6060' },
|
||||
];
|
||||
import { getDb } from '@/lib/db';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET() {
|
||||
const results = await Promise.all(
|
||||
SERVICES.map(async (service) => {
|
||||
const start = performance.now();
|
||||
try {
|
||||
// Set a short timeout (e.g., 5 seconds)
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
try {
|
||||
const db = await getDb();
|
||||
|
||||
const response = await fetch(service.url, {
|
||||
method: 'HEAD',
|
||||
signal: controller.signal,
|
||||
cache: 'no-store',
|
||||
});
|
||||
// Get live status (most recent log per service)
|
||||
const live = await db.all(`
|
||||
SELECT service_name as name, url, status, latency
|
||||
FROM uptime_logs
|
||||
WHERE id IN (SELECT MAX(id) FROM uptime_logs GROUP BY service_name)
|
||||
`);
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
// Get 24h stats
|
||||
const stats24h = await db.all(`
|
||||
SELECT service_name,
|
||||
count(*) as total,
|
||||
sum(case when status = 'up' then 1 else 0 end) as up_count
|
||||
FROM uptime_logs
|
||||
WHERE timestamp > datetime('now', '-24 hours')
|
||||
GROUP BY service_name
|
||||
`);
|
||||
|
||||
const end = performance.now();
|
||||
const latency = Math.round(end - start);
|
||||
// Get 7d stats
|
||||
const stats7d = await db.all(`
|
||||
SELECT service_name,
|
||||
count(*) as total,
|
||||
sum(case when status = 'up' then 1 else 0 end) as up_count
|
||||
FROM uptime_logs
|
||||
WHERE timestamp > datetime('now', '-7 days')
|
||||
GROUP BY service_name
|
||||
`);
|
||||
|
||||
return {
|
||||
name: service.name,
|
||||
url: service.url,
|
||||
status: response.ok ? 'up' : 'down',
|
||||
latency: latency,
|
||||
timestamp: new Date().toISOString(),
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
name: service.name,
|
||||
url: service.url,
|
||||
status: 'down',
|
||||
latency: 0,
|
||||
timestamp: new Date().toISOString(),
|
||||
error: 'Unreachable'
|
||||
};
|
||||
}
|
||||
})
|
||||
);
|
||||
// Merge data
|
||||
const results = live.map(l => {
|
||||
const s24 = stats24h.find(s => s.service_name === l.name);
|
||||
const s7d = stats7d.find(s => s.service_name === l.name);
|
||||
|
||||
return NextResponse.json(results);
|
||||
return {
|
||||
...l,
|
||||
uptime24h: s24 ? Math.round((s24.up_count / s24.total) * 100) : 100,
|
||||
uptime7d: s7d ? Math.round((s7d.up_count / s7d.total) * 100) : 100,
|
||||
};
|
||||
});
|
||||
|
||||
return NextResponse.json(results);
|
||||
} catch (error) {
|
||||
console.error('Uptime stats error:', error);
|
||||
// Fallback to simple check if DB fails
|
||||
return NextResponse.json([]);
|
||||
}
|
||||
}
|
||||
|
||||
44
app/api/track/route.ts
Normal file
44
app/api/track/route.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { getDb } from '@/lib/db';
|
||||
import geoip from 'geoip-lite';
|
||||
|
||||
export async function POST(req: Request) {
|
||||
try {
|
||||
const body = await req.json();
|
||||
const headers = req.headers;
|
||||
|
||||
// Get IP (proxies can complicate this, but X-Forwarded-For is standard)
|
||||
const forwarded = headers.get('x-forwarded-for');
|
||||
const ip = forwarded ? forwarded.split(',')[0] : '127.0.0.1'; // Fallback for dev
|
||||
|
||||
// Geo lookup
|
||||
const geo = geoip.lookup(ip);
|
||||
|
||||
// Hash IP for privacy (simple hash for demo, salt in prod)
|
||||
// For this personal dash, we might just store it or a simple hash
|
||||
const ipHash = ip; // Storing raw IP for personal dash context, or hash if preferred.
|
||||
|
||||
if (geo) {
|
||||
const db = await getDb();
|
||||
await db.run(
|
||||
`INSERT INTO visitors (ip_hash, city, country, lat, lon) VALUES (?, ?, ?, ?, ?)`,
|
||||
ipHash, geo.city, geo.country, geo.ll[0], geo.ll[1]
|
||||
);
|
||||
} else {
|
||||
// Fallback for localhost testing
|
||||
if (ip === '127.0.0.1' || ip === '::1') {
|
||||
const db = await getDb();
|
||||
// Mock NYC for localhost
|
||||
await db.run(
|
||||
`INSERT INTO visitors (ip_hash, city, country, lat, lon) VALUES (?, ?, ?, ?, ?)`,
|
||||
'localhost', 'New York', 'US', 40.7128, -74.0060
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Track error:', error);
|
||||
return NextResponse.json({ success: false }, { status: 500 });
|
||||
}
|
||||
}
|
||||
35
app/api/visitors/route.ts
Normal file
35
app/api/visitors/route.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { getDb } from '@/lib/db';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const db = await getDb();
|
||||
|
||||
// Get active/recent visitors (last 24h)
|
||||
const recent = await db.all(`
|
||||
SELECT lat, lon, city, country, count(*) as count
|
||||
FROM visitors
|
||||
WHERE timestamp > datetime('now', '-24 hours')
|
||||
GROUP BY lat, lon
|
||||
`);
|
||||
|
||||
// Get total count
|
||||
const total = await db.get(`SELECT count(*) as count FROM visitors`);
|
||||
|
||||
return NextResponse.json({
|
||||
locations: recent.map(r => ({
|
||||
location: [r.lat, r.lon],
|
||||
size: Math.min(0.1, 0.05 + (r.count * 0.005)), // Scale size by visitor count
|
||||
city: r.city,
|
||||
country: r.country
|
||||
})),
|
||||
totalVisitors: total.count,
|
||||
active24h: recent.reduce((sum, r) => sum + r.count, 0)
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Visitor fetch error:', error);
|
||||
return NextResponse.json({ locations: [], totalVisitors: 0, active24h: 0 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user