File size: 3,171 Bytes
b268bfa
db0618c
a0040c1
 
 
 
b268bfa
aa1e918
 
a0040c1
 
 
 
b268bfa
 
db0618c
b268bfa
a0040c1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b268bfa
 
d460348
a0040c1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db0618c
a0040c1
 
 
 
 
fb8feb1
 
d460348
a0040c1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
db0618c
b268bfa
 
 
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
import { Hono } from 'hono';
// import { logger } from 'hono/logger';
import { Minesweeper } from './minesweeper.ts';
import { isGithubUserPath } from './utils.ts';

// TODO: check header referer

// https://t1ckbase-minesweeper.hf.space

const USER = 'T1ckbase';

const minesweeper = new Minesweeper(8, 8, 10, './images');

const app = new Hono();

// app.use(logger());

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', (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', (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');
});

Deno.serve(app.fetch);

Deno.cron('keep alive?', '0 0 * * *', async () => {
  await fetch('https://t1ckbase-minesweeper.hf.space');
});