refactor: move visit handling code into its own lib file
This commit is contained in:
parent
6bc35b1629
commit
3e640524e8
@ -1,7 +1,4 @@
|
|||||||
import type { Cookies } from '@sveltejs/kit'
|
import type { Cookies } from '@sveltejs/kit'
|
||||||
import { env } from '$env/dynamic/private'
|
|
||||||
import { get, writable } from 'svelte/store'
|
|
||||||
import { existsSync, readFileSync } from 'fs'
|
|
||||||
|
|
||||||
export const scopeCookies = (cookies: Cookies, path: string) => {
|
export const scopeCookies = (cookies: Cookies, path: string) => {
|
||||||
return {
|
return {
|
||||||
@ -15,7 +12,4 @@ export const scopeCookies = (cookies: Cookies, path: string) => {
|
|||||||
cookies.delete(key, { ...props, path })
|
cookies.delete(key, { ...props, path })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const visitCountFile = `${env.WEBSITE_DATA_DIR}/visitcount`
|
|
||||||
export const visitCount = writable(parseInt(existsSync(visitCountFile) ? readFileSync(visitCountFile).toString() : '0'));
|
|
57
src/lib/visits.ts
Normal file
57
src/lib/visits.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { env } from "$env/dynamic/private";
|
||||||
|
import { scopeCookies } from "$lib";
|
||||||
|
import type { Cookies } from "@sveltejs/kit";
|
||||||
|
import { existsSync, readFileSync, writeFileSync } from "fs";
|
||||||
|
import { get, writable } from "svelte/store";
|
||||||
|
|
||||||
|
const visitCountFile = `${env.WEBSITE_DATA_DIR}/visitcount`
|
||||||
|
const visitCount = writable(parseInt(existsSync(visitCountFile) ? readFileSync(visitCountFile).toString() : '0'));
|
||||||
|
|
||||||
|
export const incrementVisitCount = (request: Request, cookies: Cookies) => {
|
||||||
|
let currentVisitCount = get(visitCount)
|
||||||
|
// check whether the request is from a bot or not (this doesnt need to be accurate we just want to filter out honest bots)
|
||||||
|
const ua = request.headers.get('user-agent')
|
||||||
|
const isBot = ua ? ua.toLowerCase().match(/(bot|crawl|spider|walk)/) !== null : true
|
||||||
|
if (!isBot) {
|
||||||
|
const scopedCookies = scopeCookies(cookies, '/')
|
||||||
|
// parse the last visit timestamp from cookies if it exists
|
||||||
|
const visitedTimestamp = parseInt(scopedCookies.get('visitedTimestamp') || "0")
|
||||||
|
// get unix timestamp
|
||||||
|
const currentTime = new Date().getTime()
|
||||||
|
const timeSinceVisit = currentTime - visitedTimestamp
|
||||||
|
// check if this is the first time a client is visiting or if an hour has passed since they last visited
|
||||||
|
if (visitedTimestamp === 0 || timeSinceVisit > 1000 * 60 * 60 * 24) {
|
||||||
|
// increment current and write to the store
|
||||||
|
currentVisitCount += 1; visitCount.set(currentVisitCount)
|
||||||
|
// update the cookie with the current timestamp
|
||||||
|
scopedCookies.set('visitedTimestamp', currentTime.toString())
|
||||||
|
// write the visit count to a file so we can load it later again
|
||||||
|
writeFileSync(visitCountFile, currentVisitCount.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return currentVisitCount
|
||||||
|
}
|
||||||
|
|
||||||
|
export const notifyDarkVisitors = (url: URL, request: Request) => {
|
||||||
|
fetch('https://api.darkvisitors.com/visits', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${env.DARK_VISITORS_TOKEN}`,
|
||||||
|
'content-type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
request_path: url.pathname,
|
||||||
|
request_method: request.method,
|
||||||
|
request_headers: request.headers,
|
||||||
|
})
|
||||||
|
}).catch((why) => {
|
||||||
|
console.log("failed sending dark visitors analytics:", why)
|
||||||
|
return null
|
||||||
|
}).then(async (resp) => {
|
||||||
|
if (resp !== null) {
|
||||||
|
const msg = await resp.json()
|
||||||
|
const host = `(${request.headers.get('host')} ${request.headers.get('x-real-ip')})`
|
||||||
|
console.log(`sent visitor analytic to dark visitors: ${resp.statusText}; ${msg.message ?? ''}${host}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
@ -1,7 +1,4 @@
|
|||||||
import { env } from '$env/dynamic/private';
|
import { incrementVisitCount, notifyDarkVisitors } from '$lib/visits.js';
|
||||||
import { scopeCookies, visitCount, visitCountFile } from '$lib';
|
|
||||||
import { writeFileSync } from 'fs';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
export const csr = true;
|
export const csr = true;
|
||||||
export const ssr = true;
|
export const ssr = true;
|
||||||
@ -9,54 +6,12 @@ export const prerender = false;
|
|||||||
export const trailingSlash = 'always';
|
export const trailingSlash = 'always';
|
||||||
|
|
||||||
export async function load({ request, cookies, url, setHeaders, fetch }) {
|
export async function load({ request, cookies, url, setHeaders, fetch }) {
|
||||||
fetch('https://api.darkvisitors.com/visits', {
|
notifyDarkVisitors(url, request) // no await so it doesnt block load
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${env.DARK_VISITORS_TOKEN}`,
|
|
||||||
'content-type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
request_path: url.pathname,
|
|
||||||
request_method: request.method,
|
|
||||||
request_headers: request.headers,
|
|
||||||
})
|
|
||||||
}).catch((why) => {
|
|
||||||
console.log("failed sending dark visitors analytics:", why)
|
|
||||||
return null
|
|
||||||
}).then(async (resp) => {
|
|
||||||
if (resp !== null) {
|
|
||||||
const msg = await resp.json()
|
|
||||||
const host = `(${request.headers.get('host')} ${request.headers.get('x-real-ip')})`
|
|
||||||
console.log(`sent visitor analytic to dark visitors: ${resp.statusText}; ${msg.message ?? ''}${host}`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
let currentVisitCount = get(visitCount)
|
|
||||||
// check whether the request is from a bot or not (this doesnt need to be accurate we just want to filter out honest bots)
|
|
||||||
const ua = request.headers.get('user-agent')
|
|
||||||
const isBot = ua ? ua.toLowerCase().match(/(bot|crawl|spider|walk)/) !== null : true
|
|
||||||
if (!isBot) {
|
|
||||||
const scopedCookies = scopeCookies(cookies, '/')
|
|
||||||
// parse the last visit timestamp from cookies if it exists
|
|
||||||
const visitedTimestamp = parseInt(scopedCookies.get('visitedTimestamp') || "0")
|
|
||||||
// get unix timestamp
|
|
||||||
const currentTime = new Date().getTime()
|
|
||||||
const timeSinceVisit = currentTime - visitedTimestamp
|
|
||||||
// check if this is the first time a client is visiting or if an hour has passed since they last visited
|
|
||||||
if (visitedTimestamp === 0 || timeSinceVisit > 1000 * 60 * 60 * 24) {
|
|
||||||
// increment current and write to the store
|
|
||||||
currentVisitCount += 1; visitCount.set(currentVisitCount)
|
|
||||||
// update the cookie with the current timestamp
|
|
||||||
scopedCookies.set('visitedTimestamp', currentTime.toString())
|
|
||||||
// write the visit count to a file so we can load it later again
|
|
||||||
writeFileSync(visitCountFile, currentVisitCount.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setHeaders({ 'Cache-Control': 'no-cache' })
|
setHeaders({ 'Cache-Control': 'no-cache' })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
route: url.pathname,
|
route: url.pathname,
|
||||||
visitCount: currentVisitCount,
|
visitCount: incrementVisitCount(request, cookies),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user