Search
emailSummaryHandler
@dazzag24
Email Summary Service This val is an email handler replies to emails it recieves with an LLM-generated summary. To use, forward an email to paulkinlan.emailSummaryHandler@valtown.email Blog post: https://paul.kinlan.me/projects/email-summary-service/
Email
role: "system",
content:
"You are a helpful email summarization assistant. Provide a concise, professional summary of the email content in HTML format optimized for email clients. Use only basic HTML tags like <p>, <strong>, <em>, <ul>, <li>, and <br>. Avoid using <div>, <span>, or any advanced HTML5 elements. Do not include any CSS or JavaScript. Keep the structure simple and focused on content.",
role: "user",
content: e.text || e.html || "No content",
solution_getter_maybe
@robsimmons
An interactive, runnable TypeScript val by robsimmons
Script
import { Dusa } from "https://unpkg.com/dusa@0.1.6/lib/client.js";
for (let i = 0; i < 15; i++) {
console.log("Iteration " + i);
arcGISHonoMiddleware
@wilt
Copy of ArcGISIdentityManager.authorize() , OAuth2 authentication for the ESRI ArcGIS API which is implemented as Express middleware, ported to Hono.
Script
Copy of [ArcGISIdentityManager.authorize()](https://github.com/Esri/arcgis-rest-js/blob/bfd7ce977d9879077e92fabfc491240d8f230844/packages/arcgis-rest-request/src/ArcGISIdentityManager.ts#L760), OAuth2 authentication for the ESRI ArcGIS API which is implemented as Express middleware, ported to Hono.
import type { Context, TypedResponse } from "npm:hono";
* Copy of https://github.com/Esri/arcgis-rest-js/blob/bfd7ce977d9879077e92fabfc491240d8f230844/packages/arcgis-rest-request/src/ArcGISIdentityManager.ts#L760
* for use with Hono instead of Express
): TypedResponse<unknown, 301, "redirect"> {
const { portal, clientId, expiration, redirectUri, state }: IOAuth2Options = {
...{ portal: "https://arcgis.com/sharing/rest", expiration: 20160 },
const queryParams: any = {
client_id: clientId,
expiration,
githubWebhookApproveDependencyPRs
@karfau
A webhook to approve dependency PRs created by bots The webhook can be configured on the repo or on the org level it needs to have the Payload URL set to the "web endpoint" of the val ( ... -> Endpoints -> Copy web endpoint) it needs to POST a json payload it needs to receive the workflow_runs events it needs to have the webhookSecret configured to the same value as in val town secrets (line 7) (else response is 401: Not verified ) It will only approve if all of the following conditions are met: the event action is completed , the workflow_run.conclusion has to be success , and the event is related to exactly one pull request (else response is 202: Ignored (event) ) the PR is authored authored by one of the users listed in allowedAuthors (line 5) (else response is 202: Ignored (pr author) ) the githubApiToken configured in line 9 needs to have repo access to the related repository (else response is 50x: some error message ) a branch protection has to be configured that requires at least one review approval and at least one status check (else response is 202: Ignored (branch protection) ) the PR has auto-merge enabled (else response is 202: Ignored (pr status) ) the PR has any failing status checks (even if not required) (else response is 202: Ignored (pr checks) ) the current value for dryRun is false (line 3) (else response is 200: Would have been approved (dryRun) ) If it approves the PR, it leaves a comment pointing to the website of this val.
Script
// if true: do all the checks but don't approve PRs (status code 200 instead of 201)
const dryRun = false;
// only PRs created by these authors will be considered
const allowedAuthors = ["renovate[bot]"];
// the secret shared with the webhook
SagaImmoScraper
@matthiasraimann
Scrapes offers from SAGA This services queries from 3 PM to 5 PM all offers listed on SAGA and filters offers cheaper than 700 EUR and sends it via mail.
Script
const details = new JSDOM(detailsHTML).window.document;
const exposeURL = details.querySelector("a.bg-primary-light[rel=\"noopener noreferrer\"]")?.getAttribute("href");
const isInsideArea = await Promise.all(areas.map(async a => {
return (await distance(a.center, location).catch(() => 0)) <= a.meters;
})).then(bools => bools.some(b => b));
if (!isInsideArea) {
console.log(`Is too far off: ${exposeURL}`);
return undefined;
dailySubscriptionStats
@petermillspaugh
Val Town email subscriptions: daily stats Cousin Val to @petermillspaugh/emailSubscription for emailing yourself daily subscriber stats.
Cron
/** @jsxImportSource https://esm.sh/preact */
import { email } from "https://esm.town/v/std/email?v=11";
import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
import { render } from "npm:preact-render-to-string";
type SubscriberRow = [
name: string,
aoc_2023_11_practical
@robsimmons
An interactive, runnable TypeScript val by robsimmons
Script
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
.trim()
twitter
@andreterron
Login with ~~Twitter~~ đť•Ź Use this val to login with đť•Ź and save your token into a twitter_token val Usage Fork this val Change the đź”’ privacy to "Unlisted" Navigate to https://developer.twitter.com/en/portal/dashboard to create an OAuth app and save your client id and secret to your secrets page Navigate to https://{your_username}-twitter.web.val.run to authenticate with đť•Ź And then you'll have your tokens saved to a twitter_token val! Other ~~Twitter~~ đť•Ź helper vals Refresh your tokens: https://www.val.town/v/andreterron/refreshTwitterToken Fetch user by id: https://www.val.town/v/andreterron/fetchTwitterUser Search posts: https://www.val.town/v/andreterron/searchTweets Write an X post: https://www.val.town/v/andreterron/postTweet
Script
2. Change the đź”’ privacy to "Unlisted"
3. Navigate to https://developer.twitter.com/en/portal/dashboard to create an OAuth app and save your client id and secret to your [secrets page](https://www.val.town/settings/secrets)
5. Navigate to https://{your_username}-twitter.web.val.run to authenticate with đť•Ź
const { res, token, storage } = await twitterAuthHandler(req, {
client_id: process.env.twitter_client_id,
client_secret: process.env.twitter_client_secret,
redirect_uri: `https://${username}-twitter.web.val.run/callback`,
spotifyAuthorizeURL
@stevekrouse
An interactive, runnable TypeScript val by stevekrouse
Script
import { spotifyRedirectURI } from "https://esm.town/v/stevekrouse/spotifyRedirectURI";
import { spotifyScopes } from "https://esm.town/v/stevekrouse/spotifyScopes";
import { spotifyClientId } from "https://esm.town/v/stevekrouse/spotifyClientId";
export let spotifyAuthorizeURL = async (params = {
response_type: 'code',
client_id: spotifyClientId,
scope: spotifyScopes.join(","),
redirect_uri: spotifyRedirectURI,
emailValHandler
@martinbowling
Email AI Assistant Chat with your favorite AI via email (with enhanced attachment and content support) What It Does This advanced email AI assistant allows you to: Send emails to an AI for comprehensive analysis and responses Automatically transform your queries into structured research objectives Parse and analyze various types of content: PDF attachments Image attachments (using GPT-4 Vision) Website content from links in your email Get detailed, context-aware responses directly to your inbox Setup Guide Copy this Val and save it as an Email Val (choose Val type in the top-right corner of the editor) Set up the required environment variables: OPENAI_API_KEY: Your OpenAI API key MD_API_KEY: Your API key for the markdown extraction service (optional) You can set these using Val Town's environment variables: https://docs.val.town/reference/environment-variables/ Copy the email address of the Val (click 3 dots in top-right > Copy > Copy email address) Compose your email: Write your query or request in the email body Attach any relevant PDFs or images Include links to websites you want analyzed Send it to the Val email address Wait for the AI's response, which will arrive in your inbox shortly How to Use Effectively Be clear and specific in your queries Provide context when necessary Utilize attachments and links to give the AI more information to work with The AI will transform your query into a structured research objective, so even simple questions may yield comprehensive answers Supported File Types and Limitations PDFs: Text content will be extracted and analyzed Images: Will be analyzed using GPT-4 Vision API Websites: Content will be extracted and converted to markdown for analysis Other file types are not currently supported and will be ignored Note: There may be size limitations for attachments and processing times may vary based on the complexity of the content. The AI uses advanced prompt transformation to enhance your queries, providing more detailed and structured responses. This process helps in generating comprehensive and relevant answers to your questions.
Email
</return_format>
<warnings>
List critical considerations for accuracy, verification requirements, and potential limitations of the data or analysis.
</warnings>
3. Ensure that your transformed request is more detailed and comprehensive than the original query, providing a clear structure for research and analysis.
getSpotifyAccessToken
@dthyresson
getSpotifyAccess Token Request an access token for use with the Spotify Web API. Requires environment variables from your Spotify Developers account. SPOTIFY_CLIENT_ID SPOTIFY_CLIENT_SECRET Uses Blob storage to cache the spotify_accessToken based on when the expires_in value in the Spotify Access Token response. Example import { getSpotifyAccessToken } from "https://esm.town/v/dthyresson/getSpotifyAccessToken";
const accessToken = await getSpotifyAccessToken();
console.debug(accessToken)
Script
Requires environment variables from your Spotify Developers account.
* `SPOTIFY_CLIENT_ID`
* `SPOTIFY_CLIENT_SECRET`
Uses Blob storage to cache the `spotify_accessToken` based on when the `expires_in` value in the Spotify Access Token response.
const KEY = "spotify_accessToken";
const clientId = Deno.env.get("SPOTIFY_CLIENT_ID");
const clientSecret = Deno.env.get("SPOTIFY_CLIENT_SECRET");
if (!clientId || !clientSecret) {
throw Error("A SPOTIFY_CLIENT_ID and SPOTIFY_CLIENT_SECRET is required.");
let spotifyAccessToken = await blob.getJSON(KEY) as SpotifyAccessToken;
"Content-Type": "application/x-www-form-urlencoded",
body: `grant_type=client_credentials&client_id=${clientId}&client_secret=${clientSecret}`,
if (response.status === 200) {
aoc_2023_11_impractical
@robsimmons
An interactive, runnable TypeScript val by robsimmons
Script
import { Dusa } from "https://unpkg.com/dusa@0.0.10/lib/client.js";
const INPUT = `
.trim()
awesome
@pomdtr
Awesome Val Town An curated list of useful community vals. Feel free to create your own awesome list! Apps @pomdtr/blob_editor @nbbaier/sqliteExplorerApp View and interact with your Val Town SQLite data. @pomdtr/http_client Attach a postman-like http client to your vals VS Code Extension vt Chrome Extension Tooling Authentication @pomdtr/basicAuth @pomdtr/email_auth @pomdtr/password_auth Sqlite @sqlite/db @pomdtr/sql @pomdtr/kv @postpostscript/sqliteUniverse Blob @stevekrouse/blobAdmin @pomdtr/lowdb Middleware @andreterron/codeOnValTown Testing @pomdtr/test_explorer Api @pomdtr/api @pomdtr/trpc Other @vladimyr/valshot @pomdtr/mdx @pomdtr/serve_readme OpenAI @pomdtr/ask_ai Web Components Val Town Playground CodeMirror
HTTP
- @nbbaier/sqliteExplorerApp View and interact with your Val Town SQLite data.
- @pomdtr/http_client Attach a postman-like http client to your vals
- [VS Code Extension](https://github.com/pomdtr/val-town-vscode)
pushNote
@dandivelbiss
Notehub A set of helper functions for interacting with the Notehub API Requires NOTEHUB_CLIENT_ID and NOTEHUB_CLIENT_SECRET environment variables to be configured.
Script
A set of helper functions for interacting with the Notehub API
Requires `NOTEHUB_CLIENT_ID` and `NOTEHUB_CLIENT_SECRET` [environment variables](https://www.val.town/settings/environment-variables) to be configured.
// Login into the Notehub API with a programmatic access client ID and client secret
// Returns the api token to be used for subsequent requests
const body = new URLSearchParams();
body.append("grant_type", "client_credentials");
body.append("client_id", Deno.env.get("NOTEHUB_CLIENT_ID"));
body.append("client_secret", Deno.env.get("NOTEHUB_CLIENT_SECRET"));
const res = await fetch("https://notehub.io/oauth2/token", {
january2024
@petermillspaugh
petemillspaugh.com clippings: #1 – January 2024 Process for sending out a newsletter: Publish newsletter on the Web Fork this val and update subject, webUrl, targetSendDate Uncomment call to insertIntoNewslettersTable Add to @petermillspaugh/newsletters list Val
Script
/** @jsxImportSource https://esm.sh/preact */
import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
export function getJanuary2024Newsletter() {
<a href="https://petemillspaugh.com/silly-tlds">
<strong>Silly TLDs</strong>
</a>. This is a short, fun one. It’s the thing I’ve written that friends outside of tech seem most interested
in / leads to the most fun conversations
</li>