76// --- Core Lead Generation Logic ---
7778// WARNING: Scraping search engines like DuckDuckGo is fragile and might break.
79async function searchWebsites(searchQuery: string, jobId: string): Promise<{ name: string; url: string }[]> {
80const searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(searchQuery)}`;
125126async function extractEmailsFromWebsite(websiteUrl: string, leadId: string): Promise<string | null> {
127console.log(`Scraping ${websiteUrl} for lead ${leadId}`);
128try {
129// Add http:// if no scheme
139if (!response.ok) {
140console.warn(`Failed to fetch ${properUrl} for lead ${leadId}: ${response.status}`);
141await updateLeadStatus(leadId, "error_scraping_fetch", {}, `HTTP ${response.status} for ${properUrl}`);
142return null;
143}
183return null;
184} catch (error) {
185console.error(`Error scraping ${websiteUrl} (processed as ${websiteUrl}) for lead ${leadId}:`, error);
186await updateLeadStatus(leadId, "error_scraping", {}, `Scrape exception: ${error.message}`);
187return null;
188}
279} catch (error) {
280console.error(`Error drafting email for ${emailAddress} (lead ${leadId}):`, error);
281await updateLeadStatus(leadId, "error_drafting", {}, `OpenAI API error: ${error.message}`);
282return null;
283}
286async function processJob(jobId: string, searchQuery: string) {
287await updateJobStatus(jobId, "processing_search");
288const openaiApiKey = Deno.env.get("openai");
289if (!openaiApiKey) {
290console.error("OpenAI API key secret 'openai' is not set.");
291await updateJobStatus(jobId, "failed_config", "OpenAI API key not configured.");
292return;
293}
294const openai = new OpenAI({ apiKey: openaiApiKey });
295296const websites = await searchWebsites(searchQuery, jobId);
380.status-pending, .status-processing_search, .status-processing_leads { background-color: #ffc107; color: #212529;}
381.status-completed { background-color: #28a745; }
382.status-failed_config, .status-error_searching, .status-completed_no_sites, .status-error_scraping, .status-error_drafting, .status-error_scraping_fetch, .status-error_drafting_empty_response, .status-failed_uncaught_exception { background-color: #dc3545; }
383.status-email_extracted, .status-email_drafted { background-color: #17a2b8; }
384.status-no_email_found, .status-pending_scrape { background-color: #6c757d; }
484metrics.total = leads.length;
485metrics.emailFound = leads.filter(l =>
486l.email_address && l.status !== "error_scraping_fetch" && l.status !== "error_scraping"
487).length;
488metrics.emailDrafted = leads.filter(l => l.drafted_email_body && l.status !== "error_drafting").length;
MiniAppStarterneynar.ts2 matches
1const baseUrl = "https://api.neynar.com/v2/farcaster/";
23export async function fetchNeynarGet(path: string) {
7"Content-Type": "application/json",
8"x-neynar-experimental": "true",
9"x-api-key": "NEYNAR_API_DOCS",
10},
11});
MiniAppStarterindex.tsx2 matches
19}));
2021app.get("/api/counter/get", async c => c.json(await db.get("counter")));
22app.get("/api/counter/increment", async c => c.json(await db.set("counter", (await db.get("counter") || 0) + 1)));
2324app.get("/frontend/**/*", c => serveFile(c.req.path, import.meta.url));
MiniAppStarterimage.tsx3 matches
8485const loadEmoji = (code) => {
86// const api = `https://cdnjs.cloudflare.com/ajax/libs/twemoji/14.0.2/svg/${code.toLowerCase()}.svg`
87const api = `https://cdn.jsdelivr.net/gh/shuding/fluentui-emoji-unicode/assets/${code.toLowerCase()}_color.svg`;
88return fetch(api).then((r) => r.text());
89};
90
MiniAppStarterApp.tsx3 matches
53<div className="">✷ Farcaster mini app manifest + webhook + embed metadata</div>
54<div className="">✷ Farcaster notifications (storing tokens, sending recurring notifications, ...)</div>
55<div className="">✷ Neynar API integration for Farcaster data</div>
56<div className="">✷ Hosted on Val Town (instant deployments on save)</div>
57<div className="">
6768function Database() {
69const queryFn = () => fetch("/api/counter/get").then((r) => r.json());
70const { data, refetch } = useQuery({ queryKey: ["counter"], queryFn });
71return (
73{/* <h2 className="font-semibold">Database Example</h2> */}
74<div className="">Counter value: {data}</div>
75<Button variant="outline" onClick={() => fetch("/api/counter/increment").then(refetch)}>
76Increment
77</Button>
untitled-1240riecotitanMonitor.tsx5 matches
146// In Val.Town, email might be accessed differently
147// Using standard email send function in Val.Town
148await fetch("https://api.val.town/v1/emails", {
149method: "POST",
150headers: {
167async initScheduler() {
168// Create the scheduled check for website monitoring
169// Using Val.Town's cron API
170return await fetch("https://api.val.town/v1/me/schedules", {
171method: "POST",
172headers: {
212// Note: You'll need to store the schedule ID from initScheduler to update it
213// For now, we'll create a new schedule and let Val.Town handle duplicates
214const response = await fetch("https://api.val.town/v1/me/schedules", {
215method: "POST",
216headers: {
230},
231232// ===== API ENDPOINTS =====
233234// Current status endpoint - implement using Val.Town's HTTP handler
StarterPackFeeds.cursorrules10 matches
13- Generate code in TypeScript or TSX
14- Add appropriate TypeScript types and interfaces for all data structures
15- Prefer official SDKs or libraries than writing API calls directly
16- Ask the user to supply API or library documentation if you are at all unsure about it
17- **Never bake in secrets into the code** - always use environment variables
18- Include comments explaining complex logic (avoid commenting obvious operations)
23### 1. HTTP Trigger
2425- Create web APIs and endpoints
26- Handle HTTP requests and responses
27- Example structure:
173However, it's *extremely importing* to note that `parseProject` and other Standard Library utilities ONLY RUN ON THE SERVER.
174If you need access to this data on the client, run it in the server and pass it to the client by splicing it into the HTML page
175or by making an API request for it.
176177## Val Town Platform Specifics
181- **AI Image:** To inline generate an AI image use: `<img src="https://maxm-imggenurl.web.val.run/the-description-of-your-image" />`
182- **Storage:** DO NOT use the Deno KV module for storage
183- **Browser APIs:** DO NOT use the `alert()`, `prompt()`, or `confirm()` methods
184- **Weather Data:** Use open-meteo for weather data (doesn't require API keys) unless otherwise specified
185- **View Source:** Add a view source link by importing & using `import.meta.url.replace("ems.sh", "val.town)"` (or passing this data to the client) and include `target="_top"` attribute
186- **Error Debugging:** Add `<script src="https://esm.town/v/std/catch"></script>` to HTML to capture client-side errors
187- **Error Handling:** Only use try...catch when there's a clear local resolution; Avoid catches that merely log or return 500s. Let errors bubble up with full context
188- **Environment Variables:** Use `Deno.env.get('keyname')` when you need to, but generally prefer APIs that don't require keys
189- **Imports:** Use `https://esm.sh` for npm and Deno dependencies to ensure compatibility on server and browser
190- **Storage Strategy:** Only use backend storage if explicitly required; prefer simple static client-side sites
224### Backend (Hono) Best Practices
225226- Hono is the recommended API framework
227- Main entry point should be `backend/index.ts`
228- **Static asset serving:** Use the utility functions to read and serve project files:
248});
249```
250- Create RESTful API routes for CRUD operations
251- Always include this snippet at the top-level Hono app to re-throwing errors to see full stack traces:
252```ts
285- For files in the project, use `readFile` helpers
2862875. **API Design:**
288- `fetch` handler is the entry point for HTTP vals
289- Run the Hono app with `export default app.fetch // This is the entry point for HTTP vals`
bilibili-bangumi-componentbackend2 matches
56if (!o) return c({ code: 400, message: "uid is required", data: {} });
57let i = p({ type: 1, follow_status: e, pn: r, ps: s, vmid: o }),
58l = await fetch(`https://api.bilibili.com/x/space/bangumi/follow/list?${i}`),
59u = await l.json();
60return !l.ok || u?.code !== 0
87if (!i) return c({ code: 400, message: "uid is required", data: {} });
88let l = p({ subject_type: R[e], type: N[r], limit: o, offset: (Number(s) - 1) * Number(o) }),
89u = await fetch(`https://api.bgm.tv/v0/users/${i}/collections?${l}`, {
90headers: {
91"User-Agent": "yixiaojiu/bilibili-bangumi-component (https://github.com/yixiaojiu/bilibili-bangumi-component)",
5455/* ------------------------------------------------------------------ */
56/* Utility: minimal XML escaping (only for text nodes) */
57function escapeXml(str: string = ""): string {
58return str
getDatagetData.tsx1 match
1// @val-town/api
2export default async function(req: Request): Promise<Response> {
3return Response.json({