Created
March 17, 2023 16:03
-
-
Save autonome/725e88ca044e4444e83197dab30f9333 to your computer and use it in GitHub Desktop.
script to dump IPFS Thing airtable to local toml files ready for a GHA to make a PR w/ those changes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const https = require('https'); | |
const token = process.env.AIRTABLE_TOKEN; | |
const url = 'https://api.airtable.com/v0/apptAzTf0HPbYkCbn/Responses' | |
const options = { | |
headers: { | |
'Authorization': 'Bearer ' + token | |
} | |
}; | |
const fields = { | |
'Title': 'title', | |
'Talk Description': 'desc', | |
'Title & Organization': 'spkrTitle', | |
'What track(s) would be suitable for your session?': 'tracks', | |
'What format(s) are suitable for your talk or workshop?': 'format', | |
'If you are affiliated with an organization and would like your logo to be displayed on our event website as a participating team at IPFS thing, please upload a high res image below.': 'logo', | |
'Headshot': 'headshot', | |
'Last Name': 'lastName', | |
'Archive of Original Tracks Submission': 'tracksSubmittedFor', | |
'Talk Status': 'status', | |
'Track Description': 'trackDesc', | |
'Email Address': 'email', | |
'Talk or Track?': 'type', | |
'First Name': 'firstName', | |
'Created': 'createdDate', | |
'Last Modified By': 'lastModifiedBy', | |
'Last Modified': 'lastModifiedDate' | |
}; | |
// add some error handling jeez | |
const getAirtableData = (url, options, callback) => { | |
https.get(url, options, res => { | |
let data = []; | |
res.on('data', chunk => { | |
data.push(chunk); | |
}); | |
res.on('end', () => { | |
const bc = Buffer.concat(data); | |
const str = bc.toString(); | |
const obj = JSON.parse(str); | |
const records = cleanDump(obj.records); | |
callback(records); | |
}); | |
}).on('error', err => { | |
console.log('Error: ', err.message); | |
}); | |
}; | |
const onRecordsReady = records => { | |
const talks = getTalks(records); | |
const tracks = getTracks(records); | |
const grouped = groupTracks(tracks, talks); | |
const trackTOMLs = Object.keys(grouped) | |
.map(k => grouped[k]) | |
.filter(t => t.talks.length > 0) | |
.map(trackToTOML); | |
// TODO: write each string of track toml data to | |
// local fs, ready for use by GHA which makes the PR | |
console.log(trackTOMLs[0]); | |
}; | |
const cleanDump = records => { | |
return records | |
.map(r => r.fields) | |
.map(r => { | |
let o = {}; | |
Object.keys(fields).forEach(f => { | |
o[ fields[f] ] = r[f]; | |
}); | |
// TODO | |
o.startTime = '00:00'; | |
return o; | |
}); | |
}; | |
const getTalks = records => { | |
return records | |
.filter(r => r.type == 'Talk') | |
.filter(r => r.status == 'Accepted by track lead'); | |
}; | |
const getTracks = records => records.filter(r => r.type == 'Track'); | |
const groupTracks = (tracks, talks) => { | |
// array of track titles | |
const trackTitles = tracks.map(t => t.title); | |
// create map of track title => track data | |
const trackList = tracks.reduce((obj, t) => { | |
t.talks = []; | |
obj[t.title] = t; | |
return obj; | |
}, {}); | |
// add each talk to its track | |
talks.forEach(talk => { | |
trackList[ talk.tracks[0] ].talks.push(talk); | |
}); | |
return trackList; | |
}; | |
const trackToTOML = track => { | |
return trackDetailsToTOML(track) | |
+ '\n\n' | |
+ track.talks.map(talkToTOML).join('\n'); | |
}; | |
const talkToTOML = talk => { | |
//console.log('talkToTOML', talk); | |
return [ | |
'[[timeslots]]', | |
`startTime="${talk.startTime}"`, | |
`speaker="${talk.firstName + ' ' + talk.lastName}"`, | |
`title="${talk.title}"`, | |
`description="${talk.desc}"`, | |
'\n' | |
].join('\n'); | |
} | |
const trackDetailsToTOML = track => { | |
return ` | |
# the name of your track or event | |
name = "${track.title}" | |
# the name handle of the directly responsible individual for this event | |
# (this person will coordinate with devent organizers) | |
dri = "${track.firstName} ${track.lastName}" | |
# the start date of the event | |
date = "2023-10-29" | |
# how many days the event lasts (1 - N) | |
days = 1 | |
# the event venue name (will show up on the event card - TODO) | |
venueName = "Hypatia" | |
# the event times (shows up in the event card) | |
times = "10:00 - 13:00" | |
# the "difficulty" of the event -- one of: | |
# ["Beginner", "Intermediate", "Advanced", "All Welcome"] | |
difficulty = "All Welcome" | |
# tags for the event, will show up as labels. | |
# pick 1-4 | |
tags = ["Talks"] | |
# a color, to group key events visually. use sparingly | |
# color="purple" | |
# the priority in the schedule table, leave commented if you don't need to control this | |
# 1 will appear at the top, higher numbers appear closer to bottom | |
# priority = 1 | |
# a description of the track. | |
# will show up when the user clicks the event card. | |
description = """ | |
${track.desc} | |
""" | |
# schedule is an array of timeslots objects | |
# schema: | |
# startTime - string for starting time | |
# speakers - array of string speaker names. please to use consistent naming across timeslots | |
# title - string for talk or timeslot title, should be short | |
# description - string describing the timeslot. 1-3 sentences. | |
# | |
# Notes: | |
# - recommended start: 10:00 | |
# - recommended lunch: 13:00 | |
# - recommended end: 16:00 (On 30 Oct, 1h Camp wrapup begins at 16:00) | |
# - use 15m, 20m, 30m, 45m, or 60m session slots | |
# - use 15m breaks, one in the morning, one or two in the afternoon | |
`; | |
}; | |
getAirtableData(url, options, onRecordsReady); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment