sendNotificationREADME.md1 match
1# Push Notification Sender
23This val can be used in other vals to send notifications to a segment using [OneSignal's REST API](https://documentation.onesignal.com/reference/create-notification)
45This is really handy if you want to send push notifications to your phone without building a native app! I built a barebones React PWA that asks for a password then loads the OneSignal Web SDK that I deployed to [Netlify](https://www.netlify.com/) for free. OneSignal has [easy to follow docs](https://documentation.onesignal.com/docs/web-sdk-setup) so you can build this functionality into a React, Angular, Vue app or even Wordpress! Then [install the PWA](https://www.bitcot.com/how-to-install-a-pwa-to-your-device/) on your platform of choice and you're off to the races!
sendNotificationmain.tsx1 match
6const defaultSegment = [Deno.env.get("DEFAULT_ONESIGNAL_SEGMENT")];
78const onesignalURL = "https://onesignal.com/api/v1/notifications";
910/**
4async function fetchRandomJoke() {
5const response = await fetch(
6"https://official-joke-api.appspot.com/random_joke",
7);
8return response.json();
uploadImagemain.tsx1 match
24}
25async function getUploadURL(): Promise<string> {
26const data = await (await fetch("https://www.val.town/api/trpc/generateImageUploadUrl", {
27"headers": {
28"content-type": "application/json",
sanguineAquaReptileREADME.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
affableMagentaPlanarianmain.tsx4 matches
397intervalId = setInterval(async () => {
398try {
399const response = await fetch("/api/progress");
400if (!response.ok) {
401throw new Error(`HTTP error! status: ${response.status}`);
429setBrokenLinks([]);
430try {
431const response = await fetch("/api/check-links", {
432method: "POST",
433headers: {
602const url = new URL(request.url);
603604if (url.pathname === "/api/progress" && request.method === "GET") {
605const now = new Date();
606if (lastProgressUpdate && currentProgress) {
631}
632633if (url.pathname === "/api/check-links" && request.method === "POST") {
634let requestBody;
635try {
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