40
41/**
42 * Fetches tasks from Todoist API
43 * @returns Array of Todoist tasks due today or overdue
44 */
45async function fetchTodoistTasks(): Promise<TodoistTask[]> {
46 const apiToken = Deno.env.get("TODOIST_API_TOKEN");
47
48 if (!apiToken) {
49 throw new Error("Todoist API Token is required");
50 }
51
55
56 try {
57 const response = await fetch("https://api.todoist.com/rest/v2/tasks", {
58 method: "GET",
59 headers: {
60 "Authorization": `Bearer ${apiToken}`,
61 "Content-Type": "application/json",
62 },
64
65 if (!response.ok) {
66 throw new Error(`Todoist API error: ${response.statusText}`);
67 }
68
30 // This is a no-op if nothing's changed
31 if (!isEndpointSet) {
32 await bot.api.setWebhook("https://omnipotente.val.run/telegramBotStarter", {
33 secret_token: SECRET_TOKEN,
34 });
93
94export async function sendDailyBriefing(today?: DateTime) {
95 // Get API keys from environment
96 const apiKey = Deno.env.get("ANTHROPIC_API_KEY");
97 // const telegramToken = Deno.env.get("TELEGRAM_TOKEN");
98
102 // }
103
104 if (!apiKey) {
105 console.error("Anthropic API key is not configured.");
106 return;
107 }
118
119 // Initialize Anthropic client
120 const anthropic = new Anthropic({ apiKey });
121
122 // Initialize Telegram bot
166
167 // disabled title for now, it seemes unnecessary...
168 // await bot.api.sendMessage(chatId, `*${title}*`, { parse_mode: "Markdown" });
169
170 // Then send the main content
174
175 if (content.length <= MAX_LENGTH) {
176 await bot.api.sendMessage(chatId, content, { parse_mode: "Markdown" });
177 // Store the briefing in chat history
178 await storeChatMessage(
203 // Send each chunk as a separate message and store in chat history
204 for (const chunk of chunks) {
205 await bot.api.sendMessage(chatId, chunk, { parse_mode: "Markdown" });
206 // Store each chunk in chat history
207 await storeChatMessage(
6 <title>Gorilla Rampage: Meta & Mayhem</title>
7 <script src="https://cdn.tailwindcss.com"></script>
8 <link href="https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap" rel="stylesheet">
9 <style>
10 body {
1import process from "node:process";
2import { BskyAgent } from "npm:@atproto/api";
3
4async function main() {
2export async function trackGA4Event(req, clientPrefix) {
3 const GA4_MEASUREMENT_ID = Deno.env.get(`${clientPrefix}_GA4_MEASUREMENT_ID`);
4 const GA4_API_SECRET = Deno.env.get(`${clientPrefix}_GA4_API_KEY`);
5
6 if (!GA4_MEASUREMENT_ID || !GA4_API_SECRET) {
7 return new Response(`Missing GA4 environment variables for ${clientPrefix}`, { status: 500 });
8 }
24
25 const GA4_ENDPOINT =
26 `https://www.google-analytics.com/mp/collect?measurement_id=${GA4_MEASUREMENT_ID}&api_secret=${GA4_API_SECRET}`;
27
28 const ga4Payload = {
1import { createRoute } from "https://esm.sh/@hono/zod-openapi@0.18.4";
2import { ErrorSchema, UpdateUserSchema, UserIdPathParamSchema, UserSchema } from "../schema.ts";
3
1import { z } from "https://esm.sh/@hono/zod-openapi@0.18.4";
2
3// Schema that defines presence of an ID in the path
6 .coerce
7 .number()
8 .openapi({ example: 1 }),
9});
10
12export const NewUserSchema = z
13 .object({
14 name: z.string().min(2).max(50).openapi({ example: "Mark Scout" }),
15 email: z.string().email().openapi({ example: "mark@lumen.co" }),
16 age: z.number().int().min(18).max(120).openapi({ example: 35 }),
17 }).openapi("NewUser");
18
19// Schema that defines the response of a request to get a user
21 .object({
22 id: z.number().int(),
23 name: z.string().openapi({ example: "Mark Scout" }),
24 email: z.string().email().openapi({ example: "mark@lumen.co" }),
25 age: z.number().int().openapi({ example: 35 }),
26 }).openapi("User");
27
28export const UpdateUserSchema = z
29 .object({
30 name: z.string().optional().openapi({
31 example: "Marcus Scoutius",
32 }),
33 age: z.number().int().optional().openapi({
34 example: 53,
35 }),
36 })
37 .openapi("UpdateUser");
38
39// Error schema
1**Example Hono-Zod-OpenAPI app with a Fiberplane API explorer.**
2
3> For an example with regular-old Hono, see: https://www.val.town/v/fiberplane/fiberplaneHonoStarter
8 ```
9
102. Expose your OpenAPI spec
11 ```ts
12 app.doc("/doc", {
13 openapi: "3.0.0",
14 info: {
15 title: "User Management API",
16 version: "v1.0.0",
17 },
19 ```
20
213. Mount the api explorer
22
23 This will mount it at the root `/*`, but you can mount it to another route, like `/fp/*` if you
24 are using `/` for your main app. We recommend `/` if your Hono app is an API without a frontend.
25
26 ```ts
28 "/*",
29 createFiberplane({
30 openapi: { url: "/doc" },
31 }),
32 );
33 ```
34
354. Visit your Val's root route to play with the API explorer!
36
37## How it Works
38
39`createFiberplane` mounts Fiberpalne at the root route (`/`), which can be used to explore the api's routes and make requests.
40Think of it like an embedded, lightweight postman.
1import { createRoute, z } from "https://esm.sh/@hono/zod-openapi@0.18.4";
2import { UserSchema } from "../schema.ts";
3