15 return {
16 InitialEmbedTitle: "Loading . . .",
17 InitialEmbedDescription: "Due to Discord API rate limits this will take a few minutes.",
18 InitialEmbedWarningFieldTitle: "⚠️ Warning ⚠️",
19 InitialEmbedWarningFieldValue: "Do not send messages while channel is loading!",
47console.log("lol");
48
49await fetch(`https://mastodon.social/api/v1/statuses`, {
50 method: "POST",
51 headers: {
1/**
2 * HTTP API for HN Remote TypeScript + GenAI Jobs
3 * Provides endpoints to view jobs and trigger refreshes
4 */
17 if (path === "/" || path === "/jobs") {
18 return handleJobsPage(req);
19 } else if (path === "/api/jobs") {
20 return handleJobsAPI(req);
21 } else if (path === "/api/refresh" && req.method === "POST") {
22 return handleRefresh(req);
23 } else {
45 <h1>Remote TypeScript + GenAI Jobs</h1>
46 <p>No job data available yet. Please run the job finder first.</p>
47 <form action="/api/refresh" method="post">
48 <button type="submit" style="padding: 8px 16px; background: #0366d6; color: white; border: none; border-radius: 4px; cursor: pointer;">
49 Refresh Data
73 <div style="display: flex; justify-content: space-between; align-items: center;">
74 <h1>Remote TypeScript + GenAI Jobs</h1>
75 <form action="/api/refresh" method="post">
76 <button type="submit" style="padding: 8px 16px; background: #0366d6; color: white; border: none; border-radius: 4px; cursor: pointer;">
77 Refresh Data
88 <footer style="margin-top: 40px; text-align: center; color: #666;">
89 <p>
90 <a href="/api/jobs" target="_blank">JSON API</a> |
91 <a href="${import.meta.url.replace("esm.town", "val.town")}" target="_blank">View Source</a>
92 </p>
102
103/**
104 * Handle the JSON API endpoint
105 */
106async function handleJobsAPI(req: Request): Promise<Response> {
107 // Get the format parameter
108 const url = new URL(req.url);
16 fetchComments,
17 getFallbackThreadId
18} from "./hackerNewsApi.ts";
19import {
20 filterJobListings,
4 */
5
6import { HNItem } from "./hackerNewsApi.ts";
7
8export interface JobListing {
148 "deep learning", "nlp", "computer vision", "cv", "transformers", "bert",
149 "sql", "nosql", "mongodb", "postgresql", "mysql", "redis", "graphql",
150 "rest api", "microservices", "serverless", "lambda", "devops", "sre"
151 ];
152
153 for (const skill of skillKeywords) {
154 if (lowerText.includes(skill)) {
155 // Normalize the skill name (capitalize abbreviations like AWS, GCP, etc.)
156 if (skill.length <= 3 || skill === "ci/cd" || skill === "rest api" || skill === "k8s") {
157 skills.push(skill.toUpperCase());
158 } else {
159 // Proper capitalization for multi-word skills
160 skills.push(
161 skill.split(" ")
1/**
2 * Hacker News API helper functions
3 * Provides utilities to interact with the official Hacker News API
4 */
5
102
103/**
104 * Returns a hardcoded fallback thread ID if the API search fails
105 * This is useful because the thread is typically posted on the first of each month
106 */
17
18- `backend/index.ts` - Main script that orchestrates the entire process
19- `backend/hackerNewsApi.ts` - Functions to interact with the Hacker News API
20- `backend/commentParser.ts` - Functions to parse and filter job listings
21
6 * inputs, perform calculations, and provide outputs. Functions can
7 * be used independently or as steps in workflows.
8 * https://api.slack.com/automation/functions/custom
9 */
10export const SampleFunctionDefinition = DefineFunction({
41 * definition (see above), as well as a function that contains
42 * handler logic that's run when the function is executed.
43 * https://api.slack.com/automation/functions/custom
44 */
45export default SlackFunction(
49
50 // inputs.user is set from the interactivity_context defined in sample_trigger.ts
51 // https://api.slack.com/automation/forms#add-interactivity
52 const updatedMsg = `:wave: ` + `<@${inputs.user}>`
53 + ` submitted the following message: \n\n>${inputs.message}`;
60
61 // Save the sample object to the datastore
62 // https://api.slack.com/automation/datastores
63 const putResponse = await client.apps.datastore.put({
64 datastore: "SampleObjects",
4 * Datastores are a Slack-hosted location to store
5 * and retrieve data for your app.
6 * https://api.slack.com/automation/datastores
7 */
8const SampleObjectDatastore = DefineDatastore({
327
328// ============================================================
329// TELEGRAM API INTERACTION
330// ============================================================
331
332/**
333 * Send a message using the Telegram API
334 */
335async function sendTelegramMessage(chatId, text) {
337 const botToken = process.env.TELEGRAM_BOT_TOKEN;
338
339 const response = await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
340 method: "POST",
341 headers: { "Content-Type": "application/json" },
367 const botToken = process.env.TELEGRAM_BOT_TOKEN;
368
369 const response = await fetch(`https://api.telegram.org/bot${botToken}/setWebhook`, {
370 method: "POST",
371 headers: { "Content-Type": "application/json" },
391 const botToken = process.env.TELEGRAM_BOT_TOKEN;
392
393 const response = await fetch(`https://api.telegram.org/bot${botToken}/getWebhookInfo`);
394 const result = await response.json();
395 return result;