Compare commits

..

No commits in common. "48727b60e7a0751de56b956868d6d4359fa93aa4" and "e88feaa80fe2bd7dba0161c5b13f34763d201521" have entirely different histories.

10 changed files with 32 additions and 72 deletions

View File

@ -59,7 +59,7 @@
class=" class="
window-titlebar p-1 border-ralsei-white border-8 window-titlebar p-1 border-ralsei-white border-8
bg-gradient-to-l from-ralsei-pink-neon to-ralsei-black to-75% bg-gradient-to-l from-ralsei-pink-neon to-ralsei-black to-75%
{!isOnMobile ? "cursor-move" : ""} {!isOnMobile ? "cursor-move" : ""} uppercase
" "
style="border-style: hidden hidden ridge hidden;" style="border-style: hidden hidden ridge hidden;"
> >

View File

@ -2,15 +2,15 @@ import { env } from "$env/dynamic/private";
import { scopeCookies } from "$lib"; import { scopeCookies } from "$lib";
import type { Cookies } from "@sveltejs/kit"; import type { Cookies } from "@sveltejs/kit";
import { existsSync, readFileSync, writeFileSync } from "fs"; import { existsSync, readFileSync, writeFileSync } from "fs";
import { nanoid } from "nanoid";
import { get, writable } from "svelte/store"; import { get, writable } from "svelte/store";
const visitCountFile = `${env.WEBSITE_DATA_DIR}/visitcount` const visitCountFile = `${env.WEBSITE_DATA_DIR}/visitcount`
const visitCount = writable(parseInt(existsSync(visitCountFile) ? readFileSync(visitCountFile).toString() : '0')) const visitCount = writable(parseInt(existsSync(visitCountFile) ? readFileSync(visitCountFile).toString() : '0'));
type Visitor = { visits: number[] } type Visitor = { since: number }
const lastVisitors = writable<Map<string, Visitor>>(new Map()) const lastVisitors = writable<Visitor[]>([]);
const VISITOR_EXPIRY_SECONDS = 60 * 60 * 1 const MAX_VISITORS = 10
const VISITOR_EXPIRY_SECONDS = 60 * 30 // half an hour is reasonable
export const incrementVisitCount = (request: Request, cookies: Cookies) => { export const incrementVisitCount = (request: Request, cookies: Cookies) => {
let currentVisitCount = get(visitCount) let currentVisitCount = get(visitCount)
@ -35,51 +35,31 @@ export const incrementVisitCount = (request: Request, cookies: Cookies) => {
} }
export const addLastVisitor = (request: Request, cookies: Cookies) => { export const addLastVisitor = (request: Request, cookies: Cookies) => {
let visitors = get(lastVisitors)
visitors = _addLastVisitor(visitors, request, cookies)
lastVisitors.set(visitors)
return visitors
}
// why not use this for incrementVisitCount? cuz i wanna have separate visit counts (one per hour and one per day, per hour being recent visitors)
const _addLastVisitor = (visitors: Map<string, Visitor>, request: Request, cookies: Cookies) => {
const currentTime = Date.now() const currentTime = Date.now()
// filter out old entries let visitors = get(lastVisitors).filter(
visitors = new Map( (value) => { return currentTime - value.since > 1000 * VISITOR_EXPIRY_SECONDS }
visitors.entries().filter(
([_, visitor]) =>
{ return currentTime - visitor.visits[0] < 1000 * VISITOR_EXPIRY_SECONDS }
).map(
([id, visitor]) => {
visitor.visits = visitor.visits.filter((since) => {
return currentTime - since < 1000 * VISITOR_EXPIRY_SECONDS
})
return [id, visitor]
}
)
) )
// check whether the request is from a bot or not (this doesnt need to be accurate we just want to filter out honest bots) // check whether the request is from a bot or not (this doesnt need to be accurate we just want to filter out honest bots)
if (isBot(request)) { return visitors } if (isBot(request)) { return visitors }
const scopedCookies = scopeCookies(cookies, '/') const scopedCookies = scopeCookies(cookies, '/')
// parse the last visit timestamp from cookies if it exists // parse the last visit timestamp from cookies if it exists
let visitorId = scopedCookies.get('visitorId') || "" const visitorTimestamp = parseInt(scopedCookies.get('visitorTimestamp') || "0")
// if no such id exists, create one and assign it to the client // get unix timestamp
if (! visitors.has(visitorId)) { const timeSinceVisit = currentTime - visitorTimestamp
visitorId = nanoid() // check if this is the first time a client is visiting or if an hour has passed since they last visited
scopedCookies.set('visitorId', visitorId) if (visitorTimestamp === 0 || timeSinceVisit > 1000 * VISITOR_EXPIRY_SECONDS) {
console.log(`new client visitor id ${visitorId}`) visitors.push({ since: currentTime })
if (visitors.length > MAX_VISITORS) { visitors.shift() }
// update the cookie with the current timestamp
scopedCookies.set('visitorTimestamp', currentTime.toString())
} }
// update the entry
let visitorEntry = visitors.get(visitorId) || {visits: []}
// put new visit in the front
visitorEntry.visits = [currentTime].concat(visitorEntry.visits)
visitors.set(visitorId, visitorEntry);
return visitors return visitors
} }
const isBot = (request: Request) => { const isBot = (request: Request) => {
const ua = request.headers.get('user-agent') const ua = request.headers.get('user-agent')
return ua ? ua.toLowerCase().match(/(bot|crawl|spider|walk|fetch|scrap|proxy|image)/) !== null : true return ua ? ua.toLowerCase().match(/(bot|crawl|spider|walk|fetch|scrap|proxy|image)/) !== null : true
} }
export const notifyDarkVisitors = (url: URL, request: Request) => { export const notifyDarkVisitors = (url: URL, request: Request) => {

View File

@ -1,5 +1,5 @@
import { testUa } from '$lib/robots.js'; import { testUa } from '$lib/robots.js';
import { addLastVisitor, incrementVisitCount, notifyDarkVisitors } from '$lib/visits.js'; import { incrementVisitCount, notifyDarkVisitors } from '$lib/visits.js';
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
export const csr = true; export const csr = true;
@ -18,6 +18,5 @@ export async function load({ request, cookies, url }) {
return { return {
route: url.pathname, route: url.pathname,
visitCount: incrementVisitCount(request, cookies), visitCount: incrementVisitCount(request, cookies),
lastVisitors: addLastVisitor(request, cookies),
} }
} }

View File

@ -1,7 +1,6 @@
<script lang="ts"> <script lang="ts">
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import getTitle from '$lib/getTitle'; import getTitle from '$lib/getTitle';
import type { Visitor } from 'svelte/types/compiler/interfaces';
import NavButton from '../components/navButton.svelte'; import NavButton from '../components/navButton.svelte';
import Tooltip from '../components/tooltip.svelte'; import Tooltip from '../components/tooltip.svelte';
import Window from '../components/window.svelte'; import Window from '../components/window.svelte';
@ -42,10 +41,6 @@
$: title = getTitle(data.route); $: title = getTitle(data.route);
$: recentVisitCount = data.lastVisitors.values().reduce(
(total, visitor) => { return total + visitor.visits.length; }, 0
)
const svgSquiggles = [[2], [3], [2], [3], [1]]; const svgSquiggles = [[2], [3], [2], [3], [1]];
</script> </script>
@ -145,7 +140,7 @@
<slot /> <slot />
</div> </div>
<nav class="w-full min-h-[5vh] max-h-[6vh] fixed bottom-0 z-[999] bg-ralsei-black overflow-visible"> <nav class="w-full min-h-[5vh] max-h-[6vh] fixed bottom-0 z-[999] bg-ralsei-black overflow-visible uppercase">
<div <div
class=" class="
max-w-full max-h-fit p-1 z-[999] max-w-full max-h-fit p-1 z-[999]
@ -165,17 +160,14 @@
<div class="hidden md:block grow" /> <div class="hidden md:block grow" />
<div class="navbox"> <div class="navbox">
<a title="previous site" class="hover:underline" href="https://xn--sr8hvo.ws/previous"></a> <a title="previous site" class="hover:underline" href="https://xn--sr8hvo.ws/previous"></a>
<a class="hover:underline" href="https://xn--sr8hvo.ws">indieweb 🕸💍</a> <a class="hover:underline" href="https://xn--sr8hvo.ws">IndieWeb 🕸💍</a>
<a title="next site" class="hover:underline" href="https://xn--sr8hvo.ws/next"></a> <a title="next site" class="hover:underline" href="https://xn--sr8hvo.ws/next"></a>
</div> </div>
<Tooltip> <Tooltip>
<svelte:fragment slot="tooltipContent"> <svelte:fragment slot="tooltipContent">
<p class="font-monospace"> <img class="min-w-64" style="image-rendering: crisp-edges pixelated;" alt="visits" src="https://count.getloli.com/@yusdacrawebsite?name=yusdacrawebsitetest&theme=booru-lewd&padding=5&offset=0&align=center&scale=1&pixelated=1&darkmode=0&num={data.visitCount}"/>
<nobr>total visits = <span class="text-ralsei-green-light text-shadow-green">{data.visitCount.toString().padStart(9, ".")}</span></nobr>
<nobr>uniq recent visits = <span class="text-ralsei-green-light text-shadow-green">{data.lastVisitors.size.toString().padStart(3, ".")}</span></nobr>
</p>
</svelte:fragment> </svelte:fragment>
<div class="navbox"><p><span class="text-ralsei-green-light text-shadow-green">{recentVisitCount}</span> recent clicks</p></div> <div class="navbox"><p><span class="text-ralsei-green-light text-shadow-green">{data.visitCount}</span> visit(s)</p></div>
</Tooltip> </Tooltip>
{#if isRoute("entries") || isRoute("log")} {#if isRoute("entries") || isRoute("log")}
<div class="navbox !gap-1"> <div class="navbox !gap-1">

View File

@ -4,18 +4,10 @@ import { steamGetNowPlaying } from "$lib/steam"
export const load = async ({}) => { export const load = async ({}) => {
const lastTrack = await lastFmGetNowPlaying() const lastTrack = await lastFmGetNowPlaying()
const lastGame = await steamGetNowPlaying() const lastGame = await steamGetNowPlaying()
let banners: number[] = [] const banners = [getBannerNo(), getBannerNo(), getBannerNo()]
while (banners.length < 3) {
const no = getBannerNo(banners)
banners.push(no)
}
return {banners, lastTrack, lastGame} return {banners, lastTrack, lastGame}
} }
const getBannerNo = (others: number[]) => { const getBannerNo = () => {
const no = Math.floor(Math.random() * 20) + 1 return Math.floor(Math.random() * 18) + 1;
if (others.includes(no)) {
return ((no + (Math.floor(Math.random() * 20))) % 20) + 1
}
return no
}; };

View File

@ -19,7 +19,6 @@
<img <img
width="150" width="150"
height="20" height="20"
title="banners from https://blinkies.cafe/"
alt="banner" alt="banner"
class=" class="
{hideIfMobile ? 'hidden' : ''} sm:inline w-[150px] [height:20px] {hideIfMobile ? 'hidden' : ''} sm:inline w-[150px] [height:20px]

View File

@ -3,11 +3,10 @@ title = "itches"
layout = "simple" layout = "simple"
+++ +++
*last updated on: 16-01-2025*
- website / social presence todos on [the indieweb wiki](https://indieweb.org/User:Gaze.systems) - website / social presence todos on [the indieweb wiki](https://indieweb.org/User:Gaze.systems)
- want to start reading chaos;head and chaos;child
- start playing killer7 and the silver case etc.
- participate in a game jam every month - participate in a game jam every month
- stream game dev stuff (...if i can stop being anxiety x1000) - stream game dev stuff (...if i can stop being anxiety x1000)
- mess around with kinect devkit, try to reimplement skeleton estimation? - mess around with kinect devkit, try to reimplement skeleton estimation?
- want to start reading chaos;head and chaos;child - fly more in VTOL VR with people
- start playing killer7 and the silver case etc.

View File

@ -20,12 +20,11 @@ import Window from '../../components/window.svelte';
<div class="flex flex-col gap-4 2xl:w-[60ch] leading-6"> <div class="flex flex-col gap-4 2xl:w-[60ch] leading-6">
<p> <p>
hia, here is the guestbook if you wanna post anything :) hia, here is the guestbook if you wanna post anything :)
</p> <br />
<p>
just fill the post in and click on your preferred auth method to post just fill the post in and click on your preferred auth method to post
(auth is there because i don't want to deal with any bots, sorry -.-)
</p> </p>
<p>rules: be a good human bean pretty please (and don't be shy!!!)</p> <p>rules: be a good human bean pretty please</p>
<p>don't be shy!!!</p>
<form method="post"> <form method="post">
<div class="entry entryflex"> <div class="entry entryflex">
<div class="flex flex-row"> <div class="flex flex-row">

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB