1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2
3export function ThankYouPage() {
4 return (
5 <div className="bg-white shadow-lg rounded-lg p-8 mt-8 max-w-2xl mx-auto text-center">
7import { CanceledPage } from "./CanceledPage.tsx";
8
9export function App() {
10 return (
11 <BrowserRouter>
6
7- `migrations.ts` - Contains the database schema and table creation logic
8- `queries.ts` - Contains typed functions for interacting with the database
9
10## Tables
27
28// Item queries
29export async function getItems(): Promise<Item[]> {
30 return await sqlite.execute(`SELECT * FROM ${ITEMS_TABLE}`);
31}
32
33export async function getItem(id: number): Promise<Item | null> {
34 const items = await sqlite.execute(`SELECT * FROM ${ITEMS_TABLE} WHERE id = ?`, [id]);
35 return items.length > 0 ? items[0] : null;
36}
37
38export async function getFirstItem(): Promise<Item | null> {
39 const items = await sqlite.execute(`SELECT * FROM ${ITEMS_TABLE} LIMIT 1`);
40 return items.length > 0 ? items[0] : null;
42
43// Preorder queries
44export async function createPreorder(preorder: Omit<Preorder, "id">): Promise<number> {
45 const result = await sqlite.execute(
46 `INSERT INTO ${PREORDERS_TABLE}
65}
66
67export async function getPreorderBySessionId(sessionId: string): Promise<Preorder | null> {
68 const preorders = await sqlite.execute(
69 `SELECT * FROM ${PREORDERS_TABLE} WHERE sessionID = ?`,
74}
75
76export async function updatePreorderStatus(
77 sessionId: string,
78 status: "pending" | "completed" | "canceled",
17export default app.fetch;
18
19function userScript() {
20 /*
21// ==UserScript==
33// ==/UserScript==
34
35(function() {
36 'use strict';
37
1export default async function (interval: Interval) {
2
3}
6// INICIO INDEX HTML
7const INDEX =
8 `<!DOCTYPE html><html lang="es"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Crea fichas en BBCode</title><script src="https://unpkg.com/htmx.org@2.0.4" integrity="sha384-HGfztofotfshcF7+8n44JQL2oJmowVChPTg48S+jvZoztPfvwD79OC/LTtG6dMp+" crossorigin="anonymous"></script><style> body { display: flex; flex-direction: column; min-height: 100vh; margin: 0; width: initial; } main { flex: 1; } body { font-family: sans-serif; line-height: 1.6; padding: 0; } h1 { margin-bottom: 20px; } main, header { width: -moz-available; width: -webkit-fill-available; max-width: 600px; margin: 20px auto; padding: 20px; border-radius: 5px; } #generar-ficha { padding: 20px; border: 1px solid #ccc; } input[type="url"] { width: -moz-available; width: -webkit-fill-available; padding: 10px; border: 1px solid #ccc; border-radius: 5px; } button { padding: 10px 20px; background-color: #007bff; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 10px auto 0 auto; display: block; } button:hover { background-color: #0056b3; } .htmx-indicator { display: none; } .htmx-request .htmx-indicator { display: inline-block; } #ficha { margin-top: 20px; } #ficha textarea { width: -moz-available; width: -webkit-fill-available; min-height: 200px; padding: 10px; border: 1px solid #ccc; border-radius: 5px; } .centrar { text-align: center; } .cargando { stroke: #000; } .error { color: red; } footer { background-color: #f0f0f0; /* Un gris claro de fondo */ padding: 20px; text-align: center; font-size: 0.9em; color: #555; border-top: 1px solid #ddd; /* Una lĂnea sutil en la parte superior */ } footer a { color: #007bff; /* Color azul para los enlaces */ text-decoration: none; /* Elimina el subrayado por defecto */ } footer a:hover { text-decoration: underline; /* Subrayado al pasar el ratĂłn */ } /* Tema scuro */ @media (prefers-color-scheme: dark) { body { background-color: #121212; color: #e0e0e0; } main { border-color: #555; } input[type="text"], #ficha textarea { background-color: #333; color: #e0e0e0; border-color: #555; } .cargando { stroke: #fff; } } </style></head> <body> <header> <h1 class="centrar">Generador de Fichas BBCode</h1> <h2 class="centrar">˚。⋆🎬🎧📚⋆。˚</h2> <p>🛠️ Crea fichas informativas para tu mĂşsica, libros, pelĂculas y series favoritas. ¡Pega el enlace y obtĂ©n el cĂłdigo BBCode listo para compartir!</p> <p>Plataformas admitidas (vendrán más, dame tu sugerencia 🙏):</p> <ul> <li>âś… GoodReads</li> <li>âś… FilmAffinity</li> <li>âś… Discogs</li> </ul> </header> <main> <form id="generar-ficha" hx-post="/generar" hx-trigger="submit" hx-target="#ficha" hx-swap="innerHTML" hx-disabled-elt="#generar"> <label> <input name="url" id="url" type="url" required placeholder="URL..."> </label> <button id="generar" type="submit">Generar</button> <p class="centrar"><svg class="htmx-indicator cargando" width="24" height="24" viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <style> .spinner_V8m1 { transform-origin: center; animation: spinner_zKoa 2s linear infinite } .spinner_V8m1 circle { stroke-linecap: round; animation: spinner_YpZS 1.5s ease-in-out infinite } @keyframes spinner_zKoa { 100% { transform: rotate(360deg) } } @keyframes spinner_YpZS { 0% { stroke-dasharray: 0 150; stroke-dashoffset: 0 } 47.5% { stroke-dasharray: 42 150; stroke-dashoffset: -16 } 95%, 100% { stroke-dasharray: 42 150; stroke-dashoffset: -59 } } </style> <g class="spinner_V8m1"> <circle cx="12" cy="12" r="9.5" fill="none" stroke-width="3"></circle> </g> </svg></p> </form> <div id="ficha"></div> </main> <footer> <p> ¡AquĂ no hay cookies ni espĂas! Este sitio web respeta tu privacidad al 100%. No usamos analĂticas ni mĂ©tricas de ningĂşn tipo. </p> <p> ÂżTe interesa el cĂłdigo? ¡Échale un vistazo en GitHub! <a href="URL_DEL_REPOSITORIO">Ver cĂłdigo fuente</a> </p> </footer> <script> function copiarFichaPortapapeles() { const textarea = document.querySelector("#ficha textarea").select(); document.execCommand("copy"); alert("Ficha copiada al portapapeles"); } </script> </body> </html>`;
9// FIN INDEX HTML
10
35}
36
37function generarTextAreaFicha(bc: string): string {
38 return `<h1>¡Ficha generada!</h1><textarea>${bc}</textarea>
39 <button id="ficha-copiar" onclick="copiarFichaPortapapeles()">Copiar</button>`;
40}
41
42async function realizarGetParsearTexto(url: string): Promise<GetParseado> {
43 try {
44 const r = await fetch(url, {
338}
339
340function determinarPlataformaWeb(url: string): PlataformasWeb {
341 try {
342 const u = new URL(url);
4import { DateTime } from "https://esm.sh/luxon@3.4.4";
5
6export async function testDailyBrief() {
7 try {
8 const testChatId = Deno.env.get("TEST_TELEGRAM_CHAT_ID");
2// Run this script manually to create the database table
3
4export default async function setupTelegramChatDb() {
5 try {
6 // Import SQLite module
13} from "../memoryUtils.ts";
14
15async function generateBriefingContent(anthropic, memories, today, isSunday) {
16 try {
17 const weekdaysHelp = generateWeekDays(today);
96}
97
98export async function sendDailyBriefing(chatId?: string, today?: DateTime) {
99 // Get API keys from environment
100 const apiKey = Deno.env.get("ANTHROPIC_API_KEY");
135 const lastSunday = today.startOf("week").minus({ days: 1 });
136
137 // Fetch relevant memories using the utility function
138 const memories = await getRelevantMemories();
139
216}
217
218function generateWeekDays(today) {
219 let output = [];
220
239// console.log(weekDays);
240
241// Export a function that calls sendDailyBriefing with no parameters
242// This maintains backward compatibility with existing cron jobs
243export default async function (overrideToday?: DateTime) {
244 return await sendDailyBriefing(undefined, overrideToday);
245}
A helper function to build a file's email
Simple functional CSS library for Val Town
import { OpenAI } from "https://esm.town/v/std/openai";
export default async function(req: Request): Promise<Response> {
if (req.method === "OPTIONS") {
return new Response(null, {
headers: {
"Access-Control-Allow-Origin": "*",
LangChain (https://langchain.com) Ambassador, KubeSphere (https://kubesphere.io) Ambassador, CNCF OpenFunction (https://openfunction.dev) TOC Member.