181
182 try {
183 const response = await fetch("/", {
184 method: "POST",
185 body: JSON.stringify({
3import { useEffect, useRef, useState } from "https://esm.sh/react@19";
4
5import { fetchUsersById } from "../util/neynar.ts";
6import { useQuery } from "../util/useQuery.ts";
7import { Button, Input } from "./ui.tsx";
170 if (!uid) return null;
171 if (uid > 2_000_000) return null;
172 return await fetchUsersById(uid).then(users => users?.[0]);
173}
9
10 const handleLogin = async (username, password) => {
11 const response = await fetch("/login", {
12 method: "POST",
13 body: JSON.stringify({ username, password }),
21
22 const handleRegister = async (username, password) => {
23 const response = await fetch("/register", {
24 method: "POST",
25 body: JSON.stringify({ username, password, isAdmin: false }),
136
137 useEffect(() => {
138 fetchMessages();
139 }, [room]);
140
141 const fetchMessages = async () => {
142 const response = await fetch(/messages/${room});
143 const roomMessages = await response.json();
144 setMessages(roomMessages);
147 const sendMessage = async (e) => {
148 e.preventDefault();
149 const response = await fetch(/messages/${room}, {
150 method: "POST",
151 body: JSON.stringify({
156 await response.json();
157 setNewMessage("");
158 fetchMessages();
159 };
160
161 const deleteMessage = async (messageId) => {
162 await fetch(/messages/${room}/${messageId}, {
163 method: "DELETE",
164 body: JSON.stringify({
167 }),
168 });
169 fetchMessages();
170 };
171
284 const description = item.querySelector(".itemDescription");
285 try {
286 const response = await fetch("/readable", {
287 method: "POST",
288 headers: {
538
539const makeReadable = async (link: string) => {
540 console.log("fetch");
541 const response = await fetch(link, { signal: AbortSignal.timeout(5000) });
542 const text = await response.text();
543 console.log("parse");
17});
18
19export default app.fetch;
20
3
4export async function getAuctions(): Promise<Auction[]> {
5 const response = await fetch("https://www.quarterpriceauction.com/auctions", {
6 headers: {
7 "User-Agent":
113}
114
115async function fetchAuctionPage(
116 auctionId: string,
117 page: number = 1,
119 const url =
120 `https://www.quarterpriceauction.com/auctions/${auctionId}/?page=${page}`;
121 const response = await fetch(url, {
122 headers: {
123 "User-Agent":
128 if (!response.ok) {
129 throw new Error(
130 `Failed to fetch page ${page} for auction ${auctionId}: ${response.status}`,
131 );
132 }
141 try {
142 const pagePromises = pageNumbers.map((pageNum) =>
143 fetchAuctionPage(auction.id, pageNum)
144 .then((html) => parseAuctionItems(html, auction.id))
145 .catch((error) => {
163 try {
164 // Get first page to determine total pages
165 const firstPageHtml = await fetchAuctionPage(auction.id, 1);
166 const totalPages = getTotalPages(firstPageHtml);
167 const BATCH_SIZE = 5;
38
39 useEffect(() => {
40 const fetchCachedData = async () => {
41 try {
42 const response = await fetch("/api/cached-data");
43 const data = await response.json();
44 if (data.success) {
49 }
50 } catch (_err) {
51 setError("Error fetching auctions");
52 } finally {
53 setLoading(false);
54 }
55 };
56 fetchCachedData();
57 }, []);
58
209 JSON.stringify({
210 success: false,
211 error: "Failed to fetch cache" + error,
212 }),
213 {
1async function fetchAndCacheAuctions() {
2 const { blob } = await import("https://esm.town/v/std/blob");
3 const BASE_URL = "https://wolf--9dd585f0f2d711efaf6e569c3dd06744.web.val.run";
4
5 try {
6 // Fetch all auctions
7 const auctionsResponse = await fetch(`${BASE_URL}/auctions`);
8 const auctionsData = await auctionsResponse.json();
9
10 if (!auctionsData.success) {
11 throw new Error("Failed to fetch auctions");
12 }
13
14 // For each auction, fetch its items
15 const auctionsWithItems = await Promise.all(
16 auctionsData.auctions.map(async (auction) => {
17 const itemsResponse = await fetch(`${BASE_URL}/auctions/${auction.id}`);
18 const itemsData = await itemsResponse.json();
19 return {
38// Handler for both cron and HTTP requests
39export default async function handler(request: Request) {
40 const result = await fetchAndCacheAuctions();
41
42 return new Response(JSON.stringify(result), {
23});
24
25// Export the fetch handler for Val Town
26export default app.fetch;
27
24 - **`HomePage.tsx`**: Renders the blog homepage with the list of posts
25 - **`BlogPost.tsx`**: Renders individual blog posts
26- **`/utils/blogPosts.ts`**: Utilities for fetching, parsing, and caching blog posts
27- **`/blog-posts/`**: Directory containing markdown files for blog posts
28
32- **Tailwind CSS**: For styling (via CDN)
33- **Unified/Remark/Rehype**: For markdown processing with GitHub Flavored Markdown support
34- **RSS Parser**: For fetching posts from the old blog's RSS feed
35- **Gray Matter**: For parsing YAML frontmatter
36