Spaces:
Paused
Paused
File size: 4,148 Bytes
b268bfa c58b31c a0040c1 8b94c2a a0040c1 b268bfa 7910130 a0040c1 b268bfa d460348 a0040c1 7910130 a0040c1 db0618c a0040c1 fb8feb1 d460348 a0040c1 7910130 a0040c1 db0618c b268bfa 8b94c2a b268bfa a9fbe0c 21ba00e a9fbe0c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
import { Hono } from 'hono';
import { logger } from 'hono/logger';
import { Minesweeper } from './minesweeper.ts';
import { isGithubUserPath } from './utils.ts';
const USER = 'T1ckbase';
const MINE_COUNT = 10;
const minesweeper = new Minesweeper(8, 8, MINE_COUNT, './images');
const app = new Hono();
const customLogger = (message: string, ...rest: string[]) => {
const timestamp = new Intl.DateTimeFormat('sv-SE', {
timeZone: 'Asia/Taipei',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
})
.format(new Date());
console.log(`[${timestamp}] ${message}`, ...rest);
};
app.get('/', (c) => c.text(`Play minesweeper:\nhttps://github.com/${USER}`));
app.get('/headers', (c) => c.text(Array.from(c.req.raw.headers).join('\n')));
if (Deno.env.get('DENO_ENV') === 'development') {
// app.get('/board', (c) => c.text(JSON.stringify(minesweeper.getBoard(), null, 2)));
app.get('/board', (c) => c.text(minesweeper.getBoard().map((row) => row.map((cell) => cell.isMine ? 'b' : cell.adjacentMines).join('')).join('\n')));
}
app.get('/cell/:row/:col/image', (c) => {
const row = Number(c.req.param('row'));
const col = Number(c.req.param('col'));
if (Number.isNaN(row) || Number.isNaN(col)) return c.text('Invalid coordinates', 400);
const cellImage = minesweeper.getCellImage(row, col);
if (!cellImage) return c.text(`Not Found: Image for cell (${row}, ${col}) could not be found. Coordinates may be invalid or no image is defined for this cell state.`, 404);
c.header('Content-Type', 'image/svg+xml');
c.header('Cache-Control', 'max-age=0, no-cache, no-store, must-revalidate');
return c.body(cellImage);
});
app.get('/cell/:row/:col/click', logger(customLogger), (c) => {
const row = Number(c.req.param('row'));
const col = Number(c.req.param('col'));
if (Number.isNaN(row) || Number.isNaN(col)) return c.text('Invalid coordinates', 400);
const referer = c.req.header('Referer');
let redirectUrl = `https://github.com/${USER}`;
if (referer) {
if (isGithubUserPath(referer, USER)) {
redirectUrl = referer;
} else {
console.warn(`Invalid or non-GitHub referer: ${referer}`);
// return c.text('?', 403);
}
} else {
console.warn('Referer header is missing.');
// return c.text('?', 403);
}
minesweeper.revealCell(row, col);
return c.redirect(redirectUrl + '#minesweeper');
});
app.get('/game/status', (c) => {
const image = minesweeper.getGameStatusImage();
if (!image) return c.text('Status image is not available.', 404);
c.header('Content-Type', 'image/svg+xml');
c.header('Cache-Control', 'max-age=0, no-cache, no-store, must-revalidate');
return c.body(image);
});
app.get('/game/reset', logger(customLogger), (c) => {
const referer = c.req.header('Referer');
let redirectUrl = `https://github.com/${USER}`;
if (referer) {
if (isGithubUserPath(referer, USER)) {
redirectUrl = referer;
} else {
console.warn(`Invalid or non-GitHub referer: ${referer}`);
// return c.text('?', 403);
}
} else {
console.warn('Referer header is missing.');
// return c.text('?', 403);
}
try {
minesweeper.resetGame();
} catch (e) {
console.warn(e instanceof Error ? e.message : e);
}
return c.redirect(redirectUrl + '#minesweeper');
});
app.get('/mines/count', (c) => {
const image = minesweeper.getCounterImage(MINE_COUNT);
if (!image) return c.text('Counter image is not available.', 404);
c.header('Content-Type', 'image/svg+xml');
c.header('Cache-Control', 'max-age=0, no-cache, no-store, must-revalidate');
return c.body(image);
});
app.get('/timer', (c) => {
const image = minesweeper.getTimerImage();
if (!image) return c.text('Timer image is not available.', 404);
c.header('Content-Type', 'image/svg+xml');
c.header('Cache-Control', 'max-age=0, no-cache, no-store, must-revalidate');
return c.body(image);
});
Deno.serve(app.fetch);
Deno.cron('keep alive', '0 0 * * *', async () => { // keep alive?
await fetch('https://t1ckbase-minesweeper.hf.space');
});
|