Public
HTTP (deprecated)
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Readme

Twitch Schedule iCal Proxy

Proxy Twitch's scheduled iCal because by default the timezone's are prefixed with a / and calendars don't like that. Read more.

Optionally, you can set ?raw to change the response content-type to text/plain.

To use, put the URL (https://pinjasaur-twitch.web.val.run/) into your calendar importer along with the ?broadcaster_id of whoever you want to subsribe to. It intentionally doesn't render when viewing on val.town to avoid auto-downloading the feed.

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
const getText = async url => (await fetch(url)).text();
export default async function(req: Request): Promise<Response> {
if (req.headers.get("referer")?.includes("val.")) {
return Response.json({ error: "Cannot access from val.town" }, {
status: 400,
});
}
const params = new URL(req.url).searchParams;
if (!params.has("broadcaster_id")) {
return Response.json({ error: "Missing 'broadcaster_id'" }, {
status: 400,
});
}
try {
// https://api.twitch.tv/helix/schedule/icalendar?broadcaster_id=95536715
const url = new URL("https://api.twitch.tv/helix/schedule/icalendar");
url.searchParams
.set("broadcaster_id", params.get("broadcaster_id"));
const ical = await getText(url.toString());
return new Response(
ical.replaceAll(
";TZID=/",
";TZID=",
),
{
headers: {
"content-type": params.get("raw") ? "text/plain" : "text/calendar",
},
},
);
} catch (err) {
return Response.json({ error: err.message }, {
status: 400,
});
}
}
pinjasaur-twitch.web.val.run
August 19, 2024