Github API examples & templates
Use these vals as a playground to view and fork Github API examples and templates on Val Town. Run any example below or find templates that can be used as a pre-built solution.
pomdtr
blog
HTTP
Val Town Blog A blog written, developed and hosted on val.town. How ? Each article on this blog is contained single val, with a #blog tag. See this example article . // #blog
// title: Example Post
import { article } from "https://esm.town/v/pomdtr/article";
import { extractValInfo } from "https://esm.town/v/pomdtr/extractValInfo";
import { html } from "https://esm.town/v/stevekrouse/html?v=5";
export async function examplePost(req: Request) {
const { author, name } = extractValInfo(import.meta.url);
return html(await article(author, name));
} Each of these post work on it's own . This val is able to: list them with the /v1/search api (with a #blog query) post with different author than the owner of this val will be filtered out only public vals will be listed render the readme of those vals using remark (with github styling) This process run each time a user visit the web endpoint , so the blog is always up to date. You can get your own instance of the blog by just forking this val .
3
g
serveUtils
Script
Serve Utils This val exports various utility functions, mainly the serve(commentFunction, contentType?) .
It enables easy serving of different files, while allowing the use of all string characters: // this is possible
const arr = ["Hello", 'world', `!`]; Townie Prompt This can be used as a replacement system prompt for Townie.
Townie will: Write client-side applications with vanilla JavaScript Serve them as different assets, ie. index.html , style.css and main.js Use modern module syntax, including importing modules directly from esm.sh on the client side Not reuse the same script for the server and client logic IMPORTANT: Due tue val.town README restrictions,
the custom prompt can now be found
here .
0
karfau
SignatureCheck
Script
This val has been created to avoid certain shortcomings of @vtdocs.verifyGithubWebhookSignature .
So it was created as a mix/evolution of two sources: The github docs about securing webhook Some code from the @octokit/webhhokmethods package This code is covered by tests which you can copy to run them, see @karfau.test_SignatureCheck This val does not contain any val.town specific code ( @ -imports, console.email ...), so it should be possible to run in Deno as is, potentially even in modern browsers (that support crypto and TextEncoder and modern ES syntax). Usage const myGithubWebhook = (req: Request) => {
const {verify} = @karfau.SignatureCheck(); // you have to call it to get the verify function!
const body = await req.text();
const signature = req.headers.get("X-Hub-Signature-256");
const verified = await verify(
{payload:body, signature},
@me.secrets.myGithubWebhookSecret,
// optionally provide fallback secrets (as many as needed)
// @me.secrets.myGithubWebhookSecretFallback
);
if (!verified) {
return new Response(`Not verified`, 401);
}
const payload = JSON.parse(body);
// actually do things in your webhook
}; By default the reason for failing verification is logged to console.error , but you can pass it a different handler: const {verify} = @karfau.SignatureCheck((reason) => { throw new Error(reason); }); (be aware that it will silently fail if you don't try catch it in an endpoint and the return code will be 502) Why @vtdocs.verifyGithubWebhookSignature has the following issues: it relies on the verify method of the outdated @octokit/webhooks-methods@3.0.2 which has (at least) two bugs that can make a difference when used in a webhook it can throws errors instead of just returning false , which can be triggered by sending an invalid signature it can be lured into checking a SHA1 signature if the signature header starts with sha1= you need to pass the secret and payload as argument to the val, which makes them appear in the evaluation logs you produce ( they are only visible for the author of the val if you run them as an API , but it still feels odd to see the secret in the evaluation logs.) parameters are all of type string and the order can be confused you can not use fallback secrets for rotating
2
postpostscript
blog
HTTP
@postpostscript 's Val Town Blog Blog Posts: Ideas 2024-03-06 - Auth for Val Town 2024-03-09 - sqliteUniverse: Make SQLite Queries Against Multiple Endpoints in Deno (Val Town) (Part 1) 2024-03-09 - sqliteUniverse: Make SQLite Queries Against Multiple Endpoints in Deno (Val Town) (Part 2) Other Projects: 2024-02-25 - moduleHighlightValueLink: Link to a Val With a Value or Method's Code Highlighted 2024-02-28 - provideBlob: Return Response Quickly and Poll for the Expensive Parts 2024-03-02 - MyFooter: my footer component which shares random vals I've liked! 2024-03-16 - readmeManager: Edit Val Readmes With Persistent Drafts 2024-04-09 - reactiveStateBlob: wrap blob state in a proxy to autosave it on changes 2024-04-24 - lock: lock that releases when it leaves the execution context 2024-04-25 - fetchWorker: communicate with a worker over a fetch-like interface 2024-01-06 - interruptibleChain: simple interface for pausing and resuming execution chains (now at https://github.com/postpostscript/chain) 2024-01-07 - expiringBlob: create-and-forget blobs using UUIDv7
1
std
openai
Script
OpenAI - Docs ↗ Use OpenAI's chat completion API with std/openai . This integration enables access to OpenAI's language models without needing to acquire API keys. For free Val Town users, all calls are sent to gpt-4o-mini . Basic Usage import { OpenAI } from "https://esm.town/v/std/openai";
const openai = new OpenAI();
const completion = await openai.chat.completions.create({
messages: [
{ role: "user", content: "Say hello in a creative way" },
],
model: "gpt-4",
max_tokens: 30,
});
console.log(completion.choices[0].message.content); Images To send an image to ChatGPT, the easiest way is by converting it to a
data URL, which is easiest to do with @stevekrouse/fileToDataURL . import { fileToDataURL } from "https://esm.town/v/stevekrouse/fileToDataURL";
const dataURL = await fileToDataURL(file);
const response = await chat([
{
role: "system",
content: `You are an nutritionist.
Estimate the calories.
We only need a VERY ROUGH estimate.
Respond ONLY in a JSON array with values conforming to: {ingredient: string, calories: number}
`,
},
{
role: "user",
content: [{
type: "image_url",
image_url: {
url: dataURL,
},
}],
},
], {
model: "gpt-4o",
max_tokens: 200,
}); Limits While our wrapper simplifies the integration of OpenAI, there are a few limitations to keep in mind: Usage Quota : We limit each user to 10 requests per minute. Features : Chat completions is the only endpoint available. If these limits are too low, let us know! You can also get around the limitation by using your own keys: Create your own API key on OpenAI's website Create an environment variable named OPENAI_API_KEY Use the OpenAI client from npm:openai : import { OpenAI } from "npm:openai";
const openai = new OpenAI(); 📝 Edit docs
5