my own status page
1import type { Env } from "./types";
2
3interface TailscaleDevice {
4 hostname: string;
5 connectedToControl: boolean;
6 lastSeen: string;
7 os: string;
8}
9
10const KV_KEY = "tailscale_devices";
11
12export async function refreshDevices(env: Env): Promise<void> {
13 if (!env.TAILSCALE_API_KEY) return;
14
15 const res = await fetch(
16 "https://api.tailscale.com/api/v2/tailnet/-/devices?fields=default",
17 {
18 headers: {
19 Authorization: `Bearer ${env.TAILSCALE_API_KEY}`,
20 },
21 },
22 );
23
24 if (!res.ok) return;
25
26 const data: { devices: TailscaleDevice[] } = await res.json();
27 await env.KV.put(KV_KEY, JSON.stringify(data.devices));
28}
29
30export async function getDeviceStatus(
31 env: Env,
32 hostname: string,
33): Promise<boolean> {
34 const cached = await env.KV.get(KV_KEY, "json");
35 if (!cached) return false;
36 const devices = cached as TailscaleDevice[];
37 const device = devices.find(
38 (d) => d.hostname.toLowerCase() === hostname.toLowerCase(),
39 );
40 return device?.connectedToControl ?? false;
41}