Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions .github/scripts/sync-meetup-events.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
import path from 'node:path';

const GROUPS_FILE = path.join('data', 'meetup_groups.json');
const USER_GROUPS_DIR = path.join('content', 'user-groups');
const CALENDAR_DIR = path.join('content', 'calendar');
const DRY_RUN = process.argv.includes('--dry-run');

Expand Down Expand Up @@ -105,11 +105,23 @@ function eventFile(event, metadata, groupName) {
}

async function groups() {
const parsed = JSON.parse(await readFile(GROUPS_FILE, 'utf8'));
if (!Array.isArray(parsed) || !parsed.every((group) => group && typeof group === 'object' && typeof group.urlname === 'string' && group.urlname)) {
throw new Error(`${GROUPS_FILE} must be an array of Meetup group objects with a urlname.`);
}
return parsed;
const files = await readdir(USER_GROUPS_DIR, { withFileTypes: true });
const urlnames = new Set();

await Promise.all(files
.filter((file) => file.isFile() && file.name !== '_index.md' && file.name.endsWith('.md'))
.map(async (file) => {
const content = await readFile(path.join(USER_GROUPS_DIR, file.name), 'utf8');
const frontMatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
if (!frontMatter) return;

for (const [, url] of frontMatter[1].matchAll(/^\s*url:\s*["']?(https?:\/\/[^\s"']+)["']?\s*$/gmi)) {
const match = url.match(/^https:\/\/(?:www\.)?meetup\.com\/([^\/?#]+)(?:[\/?#]|$)/i);
if (match) urlnames.add(match[1]);
}
}));

return [...urlnames];
}

async function fetchGroupEvents(urlname) {
Expand Down Expand Up @@ -141,7 +153,10 @@ async function calendarFiles() {

async function main() {
const configuredGroups = await groups();
const groupEvents = await Promise.all(configuredGroups.map(({ urlname }) => fetchGroupEvents(urlname)));
if (configuredGroups.length === 0) {
throw new Error(`No Meetup group links found in ${USER_GROUPS_DIR}.`);
}
const groupEvents = await Promise.all(configuredGroups.map(fetchGroupEvents));
await mkdir(CALENDAR_DIR, { recursive: true });
Comment thread
HeyItsGilbert marked this conversation as resolved.

const calendar = await calendarFiles();
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/meetup-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ jobs:
with:
add-paths: |
content/calendar
data/meetup_groups.json
branch: automation/sync-meetup-events
commit-message: Sync Meetup events
title: Sync Meetup events
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ visible. Save your Markdown file and the browser updates automatically.

### Syncing Meetup user-group events

The Community Calendar automatically syncs upcoming events from configured
Meetup groups. Add the group's Meetup URL name to
[`data/meetup_groups.json`](data/meetup_groups.json), then verify its public
The Community Calendar automatically syncs upcoming events from Meetup links
in [`content/user-groups/`](content/user-groups/). Add a group's Meetup URL to
its `links` front matter, then verify its public
`https://www.meetup.com/<urlname>/events/ical/` feed contains the intended
events. The scheduled **Sync Meetup Events** workflow reads that public feed
and its linked event pages; no Meetup API key or OAuth token is required.
Expand Down
14 changes: 0 additions & 14 deletions data/meetup_groups.json

This file was deleted.

Loading