Pytml

Pytml is a 15KB lightweight PyScript alternative — run Python in HTML with one script tag.

git clone https://github.com/notamitgamer/Pytml.git
· rebuilt hourlyOpen on GitHub
root / api / count.js

count.js (2862B)


      1 // api/count.js
      2 const REPO = 'NodeX-AR/Pytml';
      3 const PATH = 'count.json';
      4 const FLUSH_MS = 60_000;
      5 const FLUSH_THRESHOLD = 25;
      6 
      7 let buffer = { total: 0, origins: {} };
      8 let cachedTotal = 0;
      9 let lastFlush = 0;
     10 let flushing = null;
     11 
     12 async function readCount(token) {
     13   const r = await fetch(`https://api.github.com/repos/${REPO}/contents/${PATH}`, {
     14     headers: { Authorization: `token ${token}`, Accept: 'application/vnd.github.v3+json' }
     15   });
     16   if (!r.ok) throw new Error('read failed');
     17   const data = await r.json();
     18   const text = Buffer.from(data.content, 'base64').toString('utf-8');
     19   let parsed;
     20   try { parsed = JSON.parse(text); }
     21   catch { parsed = { total: parseInt(text) || 0, origins: {} }; }
     22   return { data: parsed, sha: data.sha };
     23 }
     24 
     25 async function writeCount(token, payload, sha) {
     26   const r = await fetch(`https://api.github.com/repos/${REPO}/contents/${PATH}`, {
     27     method: 'PUT',
     28     headers: {
     29       Authorization: `token ${token}`,
     30       Accept: 'application/vnd.github.v3+json',
     31       'Content-Type': 'application/json'
     32     },
     33     body: JSON.stringify({
     34       message: `Count: ${payload.total}`,
     35       content: Buffer.from(JSON.stringify(payload, null, 2)).toString('base64'),
     36       sha
     37     })
     38   });
     39   if (!r.ok) throw new Error('write failed');
     40 }
     41 
     42 function flush() {
     43   if (flushing || buffer.total === 0) return flushing;
     44   const token = process.env.GITHUB_TOKEN;
     45   const snapshot = buffer;
     46   buffer = { total: 0, origins: {} };
     47   lastFlush = Date.now();
     48 
     49   flushing = (async () => {
     50     try {
     51       const { data, sha } = await readCount(token);
     52       data.total = (data.total || 0) + snapshot.total;
     53       data.origins = data.origins || {};
     54       for (const [o, n] of Object.entries(snapshot.origins)) {
     55         data.origins[o] = (data.origins[o] || 0) + n;
     56       }
     57       data.lastUpdated = new Date().toISOString();
     58       await writeCount(token, data, sha);
     59       cachedTotal = data.total;
     60     } catch (err) {
     61       buffer.total += snapshot.total;
     62       for (const [o, n] of Object.entries(snapshot.origins)) {
     63         buffer.origins[o] = (buffer.origins[o] || 0) + n;
     64       }
     65       console.error('flush failed:', err);
     66     } finally {
     67       flushing = null;
     68     }
     69   })();
     70 
     71   return flushing;
     72 }
     73 
     74 export default async function handler(req, res) {
     75   res.setHeader('Access-Control-Allow-Origin', '*');
     76 
     77   let origin = req.headers.origin || '';
     78   if (!origin && req.headers.referer) {
     79     try { origin = new URL(req.headers.referer).origin; } catch {}
     80   }
     81   if (!origin) origin = 'unknown';
     82 
     83   buffer.total += 1;
     84   buffer.origins[origin] = (buffer.origins[origin] || 0) + 1;
     85 
     86   if (buffer.total >= FLUSH_THRESHOLD || Date.now() - lastFlush >= FLUSH_MS) {
     87     flush().catch(() => {});
     88   }
     89 
     90   res.status(200).json({
     91     schemaVersion: 1,
     92     label: 'pytml loads',
     93     message: String(cachedTotal + buffer.total),
     94     color: 'blue'
     95   });
     96 }