Newest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Application, Router } from "https://deno.land/x/oak@v16.0.0/mod.ts";
// import { denoServer } from "https://esm.town/v/pomdtr/deno_server?v=7";
import { denoServer } from "https://esm.town/v/vladimyr/denoServer";
const router = new Router();
router
.get("/", (ctx) => {
ctx.response.body = "Hello world!";
})
.get("/cat", (ctx) => {
ctx.response.body = { name: "cat" };
});
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
export default denoServer(app.fetch);

AQI Alerts

Get email alerts when AQI is unhealthy near you.

Set up

  1. Click Fork
  2. Change location (Line 4) to describe your location. It accepts fairly flexible English descriptions which it turns into locations via nominatim's geocoder API.
  3. Click Run

Background

This val uses nominatim's geocoder to get your lat, lon, and air quality data from OpenAQ. It uses EPA's NowCast AQI Index calculation and severity levels. Learn more: https://www.val.town/v/stevekrouse.easyAQI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import { email } from "https://esm.town/v/std/email?v=9";
import { easyAQI } from "https://esm.town/v/stevekrouse/easyAQI";
export async function aqi(interval: Interval) {
const location = "brower park brooklyn"; // <-- change to place, city, or zip code
const data = await easyAQI({ location });
if (!interval.lastRunAt) {
email({
text:
`You will now get Air Quality alerts for ${location} if it's unhealthy. It is now ${data.aqi} which is ${data.severity}.`,
subject: `AQI Alerts for ${location} setup!`,
});
}
if (data.severity.includes("Unhealthy")) {
email({
text: "Air Quality: " + data.severity,
subject: `AQI in ${location} is ${data.aqi}`,
});
}
}
1
2
3
4
5
6
7
8
export function denoServer(handler: (req: Request) => Response | Promise<Response>, thisArg?: any) {
if (thisArg) {
handler = handler.bind(thisArg);
}
return Object.assign(handler, {
fetch: (req) => handler(req),
});
}
1
2
3
4
5
6
7
8
// import { denoServer } from "https://esm.town/v/pomdtr/deno_server?v=7";
import { denoServer } from "https://esm.town/v/vladimyr/denoServer";
import { Hono } from "npm:hono@4";
const app = new Hono();
app.get("/", (c) => c.text("Hello from Hono!"));
app.get("/yeah", (c) => c.text("Routing!"));
export default denoServer(app.fetch);
1
2
3
4
5
6
7
// import { denoServer } from "https://esm.town/v/pomdtr/deno_server?v=7";
import { denoServer } from "https://esm.town/v/vladimyr/denoServer";
import { AutoRouter } from "npm:itty-router@5";
const router = AutoRouter();
router.get("/", () => "Hi from itty-router!");
export default denoServer(router.fetch);
1
2
3
4
5
6
7
8
import * as Peko from "https://deno.land/x/peko@2.1.0/mod.ts";
import { denoServer } from "https://esm.town/v/vladimyr/denoServer";
// import { denoServer } from "https://esm.town/v/pomdtr/deno_server?v=7";
const router = new Peko.Router();
router.get("/", () => new Response("Yes? Peko is also serving something at /hello"));
router.get("/hello", () => new Response("Hello world!"));
export default denoServer(router.handle, router);
1
2
3
4
5
6
7
8
// import { denoServer } from "https://esm.town/v/pomdtr/deno_server?v=7";
import { denoServer } from "https://esm.town/v/vladimyr/denoServer";
import nhttp from "npm:nhttp-land@1";
const app = nhttp();
app.get("/", () => "Hello from nhttp");
app.get("/cat", () => ({ name: "cat" }));
export default denoServer(app.handle);

HTML example

This is an example of how to return an HTML response.

You can also preview it at https://andreterron-htmlExample.web.val.run?name=Andre

1
2
3
4
5
6
7
8
9
10
11
12
// View at https://lmackenzie94-htmlExample.web.val.run?name=Luke
export default async function(req: Request): Promise<Response> {
const query = new URL(req.url).searchParams;
// Read name from the querystring or body. Defaults to "you" if not present.
const name = query.get("name") || (await req.json().catch(() => ({}))).name || "you";
// Returns the HTML response
return new Response(`<h1>Hi ${name}!</h1>`, {
headers: { "Content-Type": "text/html" },
});
}
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
/** @jsx jsx */
import { Hono } from "npm:hono@3";
import { jsx } from "npm:hono@3/jsx";
import { cors } from 'npm:hono/cors';
import { OpenAI } from "npm:openai";
const app = new Hono();
const openai = new OpenAI();
app.use('*', cors({
origin: '*',
allowMethods: ['GET', 'POST'],
allowHeaders: ['Content-Type'],
}));
// Server-side rendering
app.get("/", async (c) => {
const html = (
<html>
<head>
<title>OpenAI Prompt Example</title>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body>
<div class="container mx-auto py-8">
<h1 class="text-4xl font-bold mb-4">OpenAI Prompt Example</h1>
<form action="/prompt" method="GET">
<label for="prompt" class="block mb-2 font-bold">Prompt:</label>
<input type="text" id="prompt" name="prompt" value="Say hello in a creative way" class="border border-gray-300 rounded px-4 py-2 mb-4 w-full" />
<button type="submit" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2 px-4 rounded">
Submit
</button>
</form>
<div class="mt-4">
<h2 class="text-xl font-bold mb-2">Response:</h2>
<div id="output" class="border border-gray-300 rounded p-4">
{c.req.query('response') || ''}
</div>
</div>
</div>
</body>
</html>
);
return c.html(html);
});
app.get('/prompt', async (c) => {
const prompt = c.req.query('prompt');
try {
const response = await openai.chat.completions.create({
model: "gpt-4",
messages: [{ role: "user", content: prompt }],
max_tokens: 100,
});
const generatedResponse = response.choices[0].message.content;
return c.redirect(`/?response=${encodeURIComponent(generatedResponse)}`);
} catch (error) {
console.error('OpenAI API error:', error);
return c.redirect('/?response=Error%20occurred.');
}
});
export default app.fetch;

Twitter 𝕏 keyword Alerts

Custom notifications for when you, your company, or anything you care about is mentioned on Twitter.

1. Authentication

You'll need a Twitter Bearer Token. Follow these instructions to get one.

Unfortunately it costs $100 / month to have a Basic Twitter Developer account. If you subscribe to Val Town Pro, I can let you "borrow" my token. Just comment on this val and I'll hook you up.

2. Query

Change the query variable for what you want to get notified for.

You can use Twitter's search operators to customize your query, for some collection of keywords, filtering out others, and much more!

3. Notification

Below I'm sending these mentions to a private channel in our company Discord, but you can customize that to whatever you want, @std/email, Slack, Telegram, whatever.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { discordWebhook } from "https://esm.town/v/stevekrouse/discordWebhook";
import { twitterSearch } from "https://esm.town/v/stevekrouse/twitterSearch";
const query = "\"val.town\" OR \"val town\" -_ValTown_";
export async function twitterAlert({ lastRunAt }: Interval) {
const results = await twitterSearch({
query,
start_time: lastRunAt,
bearerToken: Deno.env.get("twitter"),
});
if (!results.length) return;
// format results
let content = results
.map(({ author_name, author_username, text, id }) => `https://fxtwitter.com/${author_username}/status/${id}`)
.join("\n");
// notify
await discordWebhook({
url: Deno.env.get("mentionsDiscord"),
content,
});
}