Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// This approach uses Google OAuth to authenticate the user and fetch their actual calendar events for the week.
// It requires setting up OAuth credentials in the Google Cloud Console and configuring environment variables in Val Town.
import { encode as encodeBase64 } from "https://deno.land/std@0.190.0/encoding/base64.ts";
const CLIENT_ID = Deno.env.get("GOOGLE_CLIENT_ID");
const CLIENT_SECRET = Deno.env.get("GOOGLE_CLIENT_SECRET");
const REDIRECT_URI = Deno.env.get("REDIRECT_URI"); // Should be set to your Val Town endpoint URL + "/callback"
const SCOPES = ["https://www.googleapis.com/auth/calendar.readonly"];
export default async function server(request: Request): Promise<Response> {
const url = new URL(request.url);
const path = url.pathname;
if (path === "/") {
// Initiate OAuth flow
const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?` +
`client_id=${CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(REDIRECT_URI)}` +
`&response_type=code` +
`&scope=${encodeURIComponent(SCOPES.join(" "))}` +
`&access_type=offline`;
return new Response(`
<html>
<head>
<title>Google Calendar OAuth</title>
</head>
<body>
<h1>Google Calendar OAuth</h1>
<p>Click the button below to authorize access to your Google Calendar:</p>
<a href="${authUrl}"><button>Authorize</button></a>
<p><a href="${import.meta.url.replace("esm.town", "val.town")}">View source</a></p>
</body>
</html>
`, {
headers: { "Content-Type": "text/html" },
});
} else if (path === "/callback") {
// Handle OAuth callback
const code = url.searchParams.get("code");
if (!code) {
return new Response("No code provided", { status: 400 });
}
// Exchange code for tokens
const tokenResponse = await fetch("https://oauth2.googleapis.com/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: `Basic ${encodeBase64(`${CLIENT_ID}:${CLIENT_SECRET}`)}`,
},
body: new URLSearchParams({
code,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: "authorization_code",
}),
});
const tokens = await tokenResponse.json();
// Fetch calendar events for this week
const now = new Date();
const oneWeekLater = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
const calendarResponse = await fetch(
`https://www.googleapis.com/calendar/v3/calendars/primary/events?` +
`timeMin=${now.toISOString()}` +
`&timeMax=${oneWeekLater.toISOString()}` +
`&singleEvents=true` +
`&orderBy=startTime`,
{
headers: {
Authorization: `Bearer ${tokens.access_token}`,
},
}
);
const calendarData = await calendarResponse.json();
return new Response(JSON.stringify(calendarData, null, 2), {
headers: { "Content-Type": "application/json" },
});
} else {
return new Response("Not found", { status: 404 });
}
}
ejfox-googlecalendarweekendpoint.web.val.run
August 27, 2024