1## Detect New Website Contents
2
3This val fetches a given publicly-accessible URL and detects whether its contents have changed. If they have, it sends an email to notify about the change.
4
5Changes are detected by computing a quick hash of the website's contents, storing the hash, and comparing against the previously stored hash on each request. Trivial changes to the website's contents will count as a change, which may not be desired for some use cases.
65
66export default {
67 fetch: auth(app.fetch),
68};
69
2import { API_URL } from "https://esm.town/v/std/API_URL?v=5";
3import { sqlite } from "https://esm.town/v/std/sqlite?v=6";
4import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON?v=45";
5import { refs } from "https://esm.town/v/stevekrouse/refs?v=11";
6
26 headers["Authorization"] = `Bearer ${token}`;
27 }
28 const { id } = await fetchJSON(`${API_URL}/v1/alias/${userHandle}/${valName}`, { headers });
29
30 const table_name = "cron_evals";
1import { email } from "https://esm.town/v/std/email?v=9";
2import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON";
3import { nominatimSearch } from "https://esm.town/v/stevekrouse/nominatimSearch";
4import { weatherGovGrid } from "https://esm.town/v/stevekrouse/weatherGovGrid";
14 lon,
15 });
16 let { properties: { periods } } = await fetchJSON(
17 grid.forecastHourly,
18 );
77};
78
79const fetchForecast = async () => {
80 const response = await fetch(
81 `https://api.openweathermap.org/data/2.5/forecast?lat=${latitude}&lon=${longitude}&units=metric&appid=${openWeatherMapAppId}`,
82 );
104 const telegramSendUrl =
105 `https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage?chat_id=${TELEGRAM_CHAT_ID}&parse_mode=HTML&disable_notification=true&text=${text}`;
106 await fetch(telegramSendUrl);
107};
108export default async function(interval: Interval) {
109 const forecast = await fetchForecast();
110 const formatted = formatWeatherForecast(forecast);
111
62 let url = `https://api.val.town/v1/search/vals?query=${encodeURIComponent(query)}&limit=100`;
63 while (true) {
64 const resp = await fetch(url);
65 if (!resp.ok) {
66 throw new Error(await resp.text());
33
34 // Post the message so we can deal with large text data.
35 await fetch(`/post-message?threadId=${input.getAttribute("data-thread-id")}`, {
36 method: "post",
37 body: msgDiv.textContent,
147 return new Response(body, { headers: { "Content-Type": "text/event-stream" } });
148});
149export default app.fetch;
1An API that fetches the html table of small boat arrivals data from the UK gov website. This data is from the last 7 days and updated daily.
2import { API_URL } from "https://esm.town/v/std/API_URL?v=5";
3import { sqlite } from "https://esm.town/v/std/sqlite?v=6";
4import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON?v=45";
5import { refs } from "https://esm.town/v/stevekrouse/refs?v=11";
6
26 headers["Authorization"] = `Bearer ${token}`;
27 }
28 const { id } = await fetchJSON(`${API_URL}/v1/alias/${userHandle}/${valName}`, { headers });
29
30 const createCronEvalsTable = `CREATE TABLE IF NOT EXISTS cron_evals (
5const app = createApp();
6
7export default passwordAuth(app.fetch, {
8 verifyPassword: verifyToken,
9});