Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
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
// This approach injects a notification indicator with a counter into the top toolbar
// of the Hacker News proxy for logged-in users. It modifies the HTML response
// to include the notification count in an orange box with rounded corners.
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo?v=29";
import { sqlite } from "https://esm.town/v/stevekrouse/sqlite";
const { httpEndpoint, name } = extractValInfo(import.meta.url);
// Initialize the SQLite table
await sqlite.execute(`
CREATE TABLE IF NOT EXISTS user_cookie_${name} (
id INTEGER PRIMARY KEY CHECK (id = 1),
cookie_value TEXT
)
`);
function createErrorPage(title: string, message: string): string {
return `
<html>
<head>
<title>${title}</title>
<style>
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 10pt;
color: #828282;
background-color: #f6f6ef;
margin: 0;
padding: 8px;
}
.error-container {
background-color: #ff6600;
padding: 2px;
}
.error-content {
background-color: #f6f6ef;
padding: 15px;
}
h1 {
color: #000000;
margin-top: 0;
}
a {
color: #000000;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="error-container">
<div class="error-content">
<h1>HN Proxy</h1>
<h2>${title}</h2>
<p>${message}</p>
<p><a href="${httpEndpoint}/login?goto=news">Login</a> | <a href="https://www.val.town/v/maxm/hn">Source Code</a></p>
</div>
</div>
</body>
</html>
`;
}
const checkUser = async (req: Request): Promise<string | Response> => {
// Extract the "user" cookie value
const userCookie = req.headers.get("cookie")?.split(";")
.find(c => c.trim().startsWith("user="))?.split("=")[1];
// Check if a user cookie is already stored
const storedCookie = await sqlite.execute(
`SELECT cookie_value FROM user_cookie_${name} WHERE id = 1`,
);
if (!userCookie) {
const errorPage = createErrorPage(
"Authentication Error",
"No user cookie provided. Please log in to access this page.",
);
return new Response(errorPage, { status: 401, headers: { "Content-Type": "text/html" } });
}
if (storedCookie.rows.length === 0) {
// No stored cookie, save the current one
await sqlite.execute(
`INSERT INTO user_cookie_${name} (id, cookie_value) VALUES (1, ?)`,
[userCookie],
);
} else if (userCookie !== storedCookie.rows[0].cookie_value) {
if (storedCookie.rows[0].cookie_value.split("&")[0] === userCookie.split("&")[0]) {
// Same user, different cookie value, update it
await sqlite.execute(
`UPDATE user_cookie_${name} SET cookie_value = ? WHERE id = 1`,
[userCookie],
);
} else {
// Different user, return an error
const errorPage = createErrorPage(
maxm-hn.web.val.run
August 22, 2024