valsindex.html1 match
7<p>
8For when you want to link to a Val Town user's profile pic, but don't want
9to make an API call. <a
10href="https://www.val.town/x/stevekrouse/profile-pics"
11>View source</a>
1# AQI Alerts
23**Note: I recently updated the code for this to the OpenAQ v3 API and there might be bugs.**
45Get email alerts when AQI is unhealthy near you.
10111. Click `Remix`
122. Change `location` (Line 4 in [main.tsx](/main.tsx#L4)) to describe your location. It accepts fairly flexible English descriptions which it turns into locations via [nominatim's geocoder API](https://www.val.town/v/stevekrouse/nominatimSearch).
133. Click `Run`
14
1const TARGET_URL = "https://api.openaq.org";
23export default async function(req: Request): Promise<Response> {
5return fetch(TARGET_URL + url.pathname + url.search, {
6headers: {
7"X-API-Key": Deno.env.get("OpenAQ_API_KEY") as string,
8},
9});
Notion_GCal_SyncREADME.md10 matches
11### 1. Google Calendar Setup
121. Create a Google Cloud project at https://console.cloud.google.com/
132. Enable the Google Calendar API
143. Create OAuth2 credentials (client ID and client secret)
154. Set up OAuth consent screen
165. Use the OAuth playground (https://developers.google.com/oauthplayground/) to:
17- Authorize the Calendar API (https://www.googleapis.com/auth/calendar.readonly)
18- Exchange authorization code for tokens
19- Save the refresh token
21### 2. Notion Setup
221. Create a Notion integration at https://www.notion.so/my-integrations
232. Get your Notion API key
243. Create a database in Notion for meeting pages with these properties:
25- Title (title)
305. Get the database ID from the URL (the part after the workspace name and before the question mark)
3132### 3. SERP API Setup (for better user information)
331. Sign up for a SERP API account at https://serpapi.com/
342. Get your API key
353. Add it as an environment variable
3640- `GOOGLE_CLIENT_SECRET`: Your Google OAuth client secret
41- `GOOGLE_REFRESH_TOKEN`: Refresh token for your Google account
42- `NOTION_API_KEY`: Your Notion API key
43- `NOTION_DATABASE_ID`: ID of the Notion database where meeting pages will be created
44- `TEAM_DOMAIN`: Your team's email domain (e.g., "val.town")
45- `SERP_API_KEY`: Your SERP API key for enhanced user information
4647### 5. Set Cron Schedule
50## Project Structure
51- `index.ts`: Main cron job that runs daily
52- `googleCalendar.ts`: Functions for interacting with Google Calendar API
53- `notion.ts`: Functions for creating and updating Notion pages
54- `userInfo.ts`: Functions for gathering information about meeting participants
593. It identifies meetings with exactly one external participant (not from your team domain)
604. For each user meeting, it:
61- Gathers information about the participant using their email and SERP API
62- Creates a Notion page with meeting details and participant information
63- Adds sections for meeting notes and action items
Notion_GCal_SyncgoogleCalendar.ts2 matches
45}
46
47const tokenResponse = await fetch("https://oauth2.googleapis.com/token", {
48method: "POST",
49headers: {
81
82const calendarId = "primary"; // Use primary calendar
83const url = `https://www.googleapis.com/calendar/v3/calendars/${encodeURIComponent(calendarId)}/events?timeMin=${encodeURIComponent(timeMin)}&timeMax=${encodeURIComponent(timeMax)}&singleEvents=true&orderBy=startTime`;
84
85const response = await fetch(url, {
1import { openapiGenerate } from "npm:openapi";
23export default async (req: Request) => {
5if (url.pathname === "/") {
6return new Response(
7"Turn any OpenAPI spec URL into TS types! Learn more: https://www.val.town/x/stevekrouse/openapi",
8);
9}
12if (url.pathname.startsWith("/types/")) {
13targetURL = httpsify(url.pathname.replace("/types/", ""));
14const { types } = await openapiGenerate({
15file: targetURL,
16});
18}
19targetURL = httpsify(url.pathname.slice(1));
20const { code } = await openapiGenerate({
21file: targetURL,
22});
23return new Response("import { request } from \"npm:openapi/request.js\"\n" + code, {
24headers: {
25"X-TypeScript-Types": `https://${url.hostname}/types/${targetURL}`,
29} catch (e) {
30console.log(e);
31return new Response(`OpenAPI URL not valid: ${targetURL}`, {
32status: 400,
33});
Notion_GCal_SyncuserInfo.ts14 matches
1/**
2* Functions for gathering information about meeting participants using SERP API
3*/
41819/**
20* Try to get user information from SERP API
21*/
22async function tryGetSerpApiInfo(email: string, name?: string): Promise<UserInfo | null> {
23const serpApiKey = Deno.env.get("SERP_API_KEY");
24
25if (!serpApiKey) {
26return null;
27}
38
39const response = await fetch(
40`https://serpapi.com/search.json?engine=google&q=${encodeURIComponent(searchQuery)}&api_key=${serpApiKey}`
41);
42
43if (!response.ok) {
44throw new Error(`SERP API error: ${response.status} ${await response.text()}`);
45}
46
127return null;
128} catch (error) {
129console.error("Error fetching data from SERP API:", error);
130return null;
131}
143
144try {
145// Try to get company information using SERP API
146const serpApiKey = Deno.env.get("SERP_API_KEY");
147
148if (serpApiKey) {
149const response = await fetch(
150`https://serpapi.com/search.json?engine=google&q=${encodeURIComponent(domain)}&api_key=${serpApiKey}`
151);
152
221*/
222export async function getUserInfo(email: string, name?: string): Promise<UserInfo> {
223// Try to get detailed information from SERP API
224const serpInfo = await tryGetSerpApiInfo(email, name);
225if (serpInfo) {
226return serpInfo;
1import { sensorFlags } from "https://openapi.val.run/https://api.openaq.org/openapi.json";
Notion_GCal_Syncnotion.ts5 matches
18*/
19export async function createMeetingPage(data: MeetingPageData): Promise<string> {
20const notionApiKey = Deno.env.get("NOTION_API_KEY");
21const databaseId = Deno.env.get("NOTION_DATABASE_ID");
22
23if (!notionApiKey || !databaseId) {
24throw new Error("Missing Notion API credentials in environment variables");
25}
26
261
262// Create the page in Notion
263const response = await fetch("https://api.notion.com/v1/pages", {
264method: "POST",
265headers: {
266"Authorization": `Bearer ${notionApiKey}`,
267"Notion-Version": "2022-06-28",
268"Content-Type": "application/json"