import type { APIRoute } from 'astro'; import crypto from 'crypto'; import { initPbServer } from '@lib/pbServer'; const POCKETBASE_ID_REGEX = /^[a-z0-9]{15}$/; function getClientIp(request: Request): string { const forwarded = request.headers.get('x-forwarded-for'); if (forwarded) { return forwarded.split(',')[0].trim(); } return request.headers.get('x-real-ip') || 'unknown'; } function generateVisitorHash(ip: string, userAgent: string): string { return crypto.createHash('sha256').update(ip + userAgent).digest('hex').slice(0, 32); } export const POST: APIRoute = async ({ request, url }) => { console.log('[Increment Views] PB_URL:', import.meta.env.POCKETBASE_URL); console.log('[Increment Views] PB_ADMIN_EMAIL:', import.meta.env.PB_ADMIN_EMAIL); console.log('[Increment Views] PB_ADMIN_PASSWORD:', import.meta.env.PB_ADMIN_PASSWORD ? '***SET***' : '***NOT SET***'); try { console.log('[Increment Views] Calling initPbServer...'); const pb = await initPbServer(); console.log('[Increment Views] initPbServer done, auth valid:', pb.authStore.isValid); const postId = url.searchParams.get('postId'); if (!postId || !POCKETBASE_ID_REGEX.test(postId)) { return new Response( JSON.stringify({ error: 'Некорректный postId' }), { status: 400, headers: { 'Content-Type': 'application/json' } } ); } let post; try { post = await pb.collection('posts').getOne(postId); } catch { return new Response( JSON.stringify({ error: 'Пост не найден' }), { status: 404, headers: { 'Content-Type': 'application/json' } } ); } const ip = getClientIp(request); const userAgent = request.headers.get('user-agent') || 'unknown'; const visitorHash = generateVisitorHash(ip, userAgent); const now = new Date(); const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000); const yesterdayStr = yesterday.toISOString(); let existingViews; try { existingViews = await pb.collection('post_views').getList(1, 1, { filter: `post="${postId}" && visitor_hash="${visitorHash}" && created >= "${yesterdayStr}"`, }); } catch { existingViews = { totalItems: 0 }; } let isNewView = false; if (existingViews.totalItems === 0) { isNewView = true; try { await pb.collection('post_views').create({ post: postId, visitor_hash: visitorHash, ip: ip, user_agent: userAgent, }); } catch { // ignore } } let totalViews = post.views || 0; if (isNewView) { totalViews += 1; try { await pb.collection('posts').update(postId, { views: totalViews }); } catch { // ignore } } return new Response( JSON.stringify({ views: totalViews, isNewView }), { status: 200, headers: { 'Content-Type': 'application/json' } } ); } catch (error) { console.error('[Increment Views] Error:', error); return new Response( JSON.stringify({ error: 'Внутренняя ошибка сервера' }), { status: 500, headers: { 'Content-Type': 'application/json' } } ); } };