1[IIIF Presentation API](https://iiif.io/api/presentation/3.0/) for [4TU.ResearchData](https://data.4tu.nl/).
23URL scheme:
16Todo:
1718- Add more metadata from the Djehuty API response.
1920Limitations:
2122- This is a temporary workaround until the Presentation API is implemented as part of Djehuty
23- Only images are currently supported (not video/audio)
24- The val needs to do some API requests before producing the manifest and doesn't cache responses
2526Credits:
2728- Image API implementation by Roel Janssen of 4TU.ResearchData. The source code can be found [here](https://github.com/4TUResearchData/djehuty)
29- [IIIF Builder](https://github.com/IIIF-Commons/iiif-builder) by Stephen Fraser
1import * as uuid from "https://deno.land/std/uuid/mod.ts";
2import { blob } from "https://esm.town/v/std/blob";
3import { getPolicy } from "https://esm.town/v/xkonti/memoryApiPolicy";
4import { Hono } from "npm:hono@3";
56export const handleMemoryApiRequest = async (
7req: Request,
8apiName: string,
9contactEmail: string,
10lastPolicyUpdate: string,
11blobKeyPrefix: string,
12apiKeyPrefix: string,
13) => {
14// ==== HELPERS ====
5152const verifyRequest = (c): { memoriesKey: string; error: any } => {
53// Verify API key coming as a Bearer header
54const authHeader = c.req.headers.get("Authorization");
55if (!authHeader || !authHeader.startsWith("Basic ")) {
67return { memoriesKey: "", error: c.text("Forbidden", 403) };
68}
69const expectedKey = Deno.env.get(apiKeyPrefix + key) ?? null;
70if (token !== expectedKey) {
71console.error("Invalid API KEY header");
72return { memoriesKey: "", error: c.text("Forbidden", 403) };
73}
75};
7677// API
7879const app = new Hono();
405// PRIVACY POLICY
406app.get("/privacy", async (c) => {
407const policy = getPolicy(apiName, contactEmail, lastPolicyUpdate);
408c.header("Content-Type", "text/html");
409return c.html(policy);
410});
411412app.get("/openapi", async (c) => {
413const specification = `
414{
415"openapi": "3.1.0",
416"info": {
417"title": "Memories and Conversations API",
418"description": "API for managing and storing long-term memories, AI conversations, and file attachments.",
419"version": "1.2.0"
420},
421"servers": [
422{
423"url": "<APIURL>"
424}
425],
434},
435"401": {
436"description": "Unauthorized - Missing or invalid API key."
437},
438"403": {
439"description": "Forbidden - Invalid API key."
440}
441},
468},
469"401": {
470"description": "Unauthorized - Missing or invalid API key."
471},
472"403": {
473"description": "Forbidden - Invalid API key."
474}
475},
524},
525"401": {
526"description": "Unauthorized - Missing or invalid API key."
527},
528"403": {
529"description": "Forbidden - Invalid API key."
530}
531},
571},
572"401": {
573"description": "Unauthorized - Missing or invalid API key."
574},
575"403": {
576"description": "Forbidden - Invalid API key."
577}
578},
602},
603"401": {
604"description": "Unauthorized - Missing or invalid API key."
605},
606"403": {
607"description": "Forbidden - Invalid API key."
608},
609"404": {
641},
642"401": {
643"description": "Unauthorized - Missing or invalid API key."
644},
645"403": {
646"description": "Forbidden - Invalid API key."
647}
648},
674},
675"401": {
676"description": "Unauthorized - Missing or invalid API key."
677},
678"403": {
679"description": "Forbidden - Invalid API key."
680},
681"404": {
728},
729"401": {
730"description": "Unauthorized - Missing or invalid API key."
731},
732"403": {
733"description": "Forbidden - Invalid API key."
734},
735"404": {
781},
782"401": {
783"description": "Unauthorized - Missing or invalid API key."
784},
785"403": {
786"description": "Forbidden - Invalid API key."
787},
788"404": {
4async function fetchRandomJoke() {
5const response = await fetch(
6"https://official-joke-api.appspot.com/random_joke",
7);
8return response.json();
blob_adminREADME.md1 match
11[](https://www.val.town/v/stevekrouse/blob_admin_app/fork)
1213It uses [basic authentication](https://www.val.town/v/pomdtr/basicAuth) with your [Val Town API Token](https://www.val.town/settings/api) as the password (leave the username field blank).
1415# TODO
4async function fetchRandomJoke() {
5const response = await fetch(
6"https://official-joke-api.appspot.com/random_joke",
7);
8return response.json();
searchArXiVmain.tsx1 match
1export const searchArXiV = async ({ query = "", start = 0, max_results = 10 }) => {
2const { parseStringPromise } = await import("npm:xml2js")
3const url = new URL("https://export.arxiv.org/api/query")
4url.searchParams.set("search_query", query)
5url.searchParams.set("start", String(start))
sqlite_adminREADME.md1 match
9To use it on your own Val Town SQLite database, [fork it](https://www.val.town/v/stevekrouse/sqlite_admin/fork) to your account.
1011It uses [basic authentication](https://www.val.town/v/pomdtr/basicAuth) with your [Val Town API Token](https://www.val.town/settings/api) as the password (leave the username field blank).
StripeCheckoutDemomain.tsx2 matches
425if (url.pathname === "/create-checkout-session" && req.method === "POST") {
426const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY"), {
427apiVersion: "2022-11-15",
428});
429464465const stripe = new Stripe(Deno.env.get("STRIPE_SECRET_KEY"), {
466apiVersion: "2022-11-15",
467});
468
sqliteExplorerAppmain.tsx2 matches
27<head>
28<title>SQLite Explorer</title>
29<link rel="preconnect" href="https://fonts.googleapis.com" />
3031<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
32<link
33href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300..700&family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap"
34rel="stylesheet"
35/>
sqliteExplorerAppREADME.md1 match
13## Authentication
1415Login to your SQLite Explorer with [password authentication](https://www.val.town/v/pomdtr/password_auth) with your [Val Town API Token](https://www.val.town/settings/api) as the password.
1617## Todos / Plans