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
export default async function main(req: Request): Promise<Response> {
// Helper functions for Blob storage
async function getBlob(key: string): Promise<any> {
const response = await fetch(`https://api.val.town/v/std/blob-${key}`);
if (!response.ok) throw new Error("Error fetching blob data");
return response.json();
}
async function setBlob(key: string, data: any): Promise<void> {
const response = await fetch(`https://api.val.town/v/std/blob-${key}`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (!response.ok) throw new Error("Error setting blob data");
}
const storiesKey = "hackerNewsClone_stories";
const method = req.method.toUpperCase();
const url = new URL(req.url);
const pathname = url.pathname;
// Load existing stories or initialize
let stories = await getBlob(storiesKey).catch(() => ([]));
// Seed with 30 sample stories if not present
if (stories.length === 0) {
for (let i = 1; i <= 30; i++) {
stories.push({ id: i, title: `Sample Story ${i}`, url: `https://example.com/${i}`, votes: 0 });
}
await setBlob(storiesKey, stories);
}
// Handle GET requests to show stories
if (method === "GET" && pathname === "/") {
const body = `
<html>
<body>
<h1>Hacker News Clone</h1>
<ul>
${stories.map(story => `
<li>
<a href="${story.url}">${story.title}</a>
<button onclick="fetch('/vote?id=${story.id}', { method: 'POST' }).then(() => location.reload())">Upvote (${story.votes})</button>
</li>`).join('')}
</ul>
<form method="POST" action="/submit">
<h2>Submit a new story</h2>
<input type="text" name="title" placeholder="Title" required/>
<input type="url" name="url" placeholder="URL" required/>
<button type="submit">Submit</button>
</form>
</body>
</html>
`;
return new Response(body, { headers: { "Content-Type": "text/html" } });
}
// Handle POST requests to submit a new story
if (method === "POST" && pathname === "/submit") {
const formData = await req.formData();
const title = formData.get("title")?.toString();
const url = formData.get("url")?.toString();
if (title && url) {
const newStory = { id: Date.now(), title, url, votes: 0 };
stories.push(newStory);
await setBlob(storiesKey, stories);
}
return Response.redirect("/");
}
// Handle POST requests to upvote a story
if (method === "POST" && pathname === "/vote") {
const id = parseInt(url.searchParams.get("id"));
const story = stories.find(story => story.id === id);
if (story) {
story.votes += 1;
await setBlob(storiesKey, stories);
}
return new Response("Upvoted", { status: 200 });
}
return new Response("Not Found", { status: 404 });
}
janpaul123-valle_tmp_26658746570535136802306869503814.web.val.run
July 17, 2024