Skip to content

Commit b152841

Browse files
Use user group content for Meetup sync (#84)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent c427277 commit b152841

4 files changed

Lines changed: 25 additions & 25 deletions

File tree

.github/scripts/sync-meetup-events.mjs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
22
import path from 'node:path';
33

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

@@ -105,11 +105,23 @@ function eventFile(event, metadata, groupName) {
105105
}
106106

107107
async function groups() {
108-
const parsed = JSON.parse(await readFile(GROUPS_FILE, 'utf8'));
109-
if (!Array.isArray(parsed) || !parsed.every((group) => group && typeof group === 'object' && typeof group.urlname === 'string' && group.urlname)) {
110-
throw new Error(`${GROUPS_FILE} must be an array of Meetup group objects with a urlname.`);
111-
}
112-
return parsed;
108+
const files = await readdir(USER_GROUPS_DIR, { withFileTypes: true });
109+
const urlnames = new Set();
110+
111+
await Promise.all(files
112+
.filter((file) => file.isFile() && file.name !== '_index.md' && file.name.endsWith('.md'))
113+
.map(async (file) => {
114+
const content = await readFile(path.join(USER_GROUPS_DIR, file.name), 'utf8');
115+
const frontMatter = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
116+
if (!frontMatter) return;
117+
118+
for (const [, url] of frontMatter[1].matchAll(/^\s*url:\s*["']?(https?:\/\/[^\s"']+)["']?\s*$/gmi)) {
119+
const match = url.match(/^https:\/\/(?:www\.)?meetup\.com\/([^\/?#]+)(?:[\/?#]|$)/i);
120+
if (match) urlnames.add(match[1]);
121+
}
122+
}));
123+
124+
return [...urlnames];
113125
}
114126

115127
async function fetchGroupEvents(urlname) {
@@ -141,7 +153,10 @@ async function calendarFiles() {
141153

142154
async function main() {
143155
const configuredGroups = await groups();
144-
const groupEvents = await Promise.all(configuredGroups.map(({ urlname }) => fetchGroupEvents(urlname)));
156+
if (configuredGroups.length === 0) {
157+
throw new Error(`No Meetup group links found in ${USER_GROUPS_DIR}.`);
158+
}
159+
const groupEvents = await Promise.all(configuredGroups.map(fetchGroupEvents));
145160
await mkdir(CALENDAR_DIR, { recursive: true });
146161

147162
const calendar = await calendarFiles();

.github/workflows/meetup-sync.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ jobs:
3333
with:
3434
add-paths: |
3535
content/calendar
36-
data/meetup_groups.json
3736
branch: automation/sync-meetup-events
3837
commit-message: Sync Meetup events
3938
title: Sync Meetup events

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ visible. Save your Markdown file and the browser updates automatically.
3434

3535
### Syncing Meetup user-group events
3636

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

data/meetup_groups.json

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)