You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
373 lines
14 KiB
JavaScript
373 lines
14 KiB
JavaScript
import * as srtparsejs from "srtparsejs";
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
// import db from '@/db';
|
|
|
|
import { extractFromXml } from '@extractus/feed-extractor'
|
|
|
|
export const PAGE_SIZE = 15;
|
|
|
|
const episodeExtra = {
|
|
'Buzzsprout-13794893': {
|
|
slug: 'my-favorite-new-front-end-developer-tool-mighty-meld-with-steven-schkolne',
|
|
youtube: 'https://www.youtube.com/embed/f7f5dhiU62c?si=n0FXB10NBfVHnu5z'
|
|
},
|
|
'Buzzsprout-13762534': {
|
|
slug: 'successfully-earning-over-200k-as-a-freelancer-with-tim-noetzel',
|
|
youtube: 'https://www.youtube.com/embed/VcyyFBHDN7w?si=dxhG92YmekRR2Fw-'
|
|
},
|
|
'Buzzsprout-13704812': {
|
|
slug: 'launching-a-bootstrapped-paas-stormkit-with-savas-vedova',
|
|
youtube: 'https://www.youtube.com/embed/u7eZd6tw_CM?si=9ZoIkx2DJF150aXM'
|
|
},
|
|
'Buzzsprout-13457465': {
|
|
slug: 'dvorak-vs-qwerty-vim-vs-vscode-Rust-and-design-by-contract',
|
|
youtube: 'https://www.youtube.com/embed/GaVYYO71Y_0?si=vuQAj-X3r_fB2KVl'
|
|
},
|
|
'Buzzsprout-13345885': {
|
|
slug: 'spark-joy-panda-css-zag-with-chakra-creator-segun-adebayo',
|
|
youtube: 'https://www.youtube.com/embed/J3j6Gkeg_oI'
|
|
},
|
|
'Buzzsprout-13214296': {
|
|
slug: 'how-to-build-secure-react-apps',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '095-mixed.srt')).toString())
|
|
},
|
|
'Buzzsprout-13105870': {
|
|
slug: 'the-impossible-challenge-of-writing-good-code-in-tech',
|
|
youtube: 'https://www.youtube.com/embed/2wTI2lh2T0k'
|
|
},
|
|
'Buzzsprout-13054901': {
|
|
slug: 'What-Actually-Happens-When-You-Call-A-Function-',
|
|
youtube: 'https://www.youtube.com/embed/-RVWS27op_k'
|
|
},
|
|
'Buzzsprout-12865769': {
|
|
slug: 'eric-meier-on-successfully-starting-software-projects',
|
|
youtube: 'https://www.youtube.com/embed/0lnEpttUlUk'
|
|
},
|
|
'Buzzsprout-12694669': {
|
|
slug: 'how-to-keep-your-software-job-if-ai-takes-over',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '091-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/Cwb-vjJTGCU'
|
|
},
|
|
'Buzzsprout-12631045': {
|
|
slug: 'how-to-use-ai-to-write-react-programs',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '089-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/PLJgHwnxpdk'
|
|
},
|
|
'Buzzsprout-12604013': {
|
|
slug: 'unhinged-rant-ai-wont-make-being-a-react-programmer-better',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '088-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/o65qhiyBlL8'
|
|
},
|
|
'Buzzsprout-12552230': {
|
|
slug: 'mechanics-of-react-a-beginners-intro-to-react',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '087-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/GXE8XFBro0s'
|
|
},
|
|
'Buzzsprout-12490659': {
|
|
slug: 'profitable-open-source-with-react-admin-founder-francois-zaninotto',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '086-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/XnQWumbYxio'
|
|
},
|
|
'Buzzsprout-12458395': {
|
|
slug: 'when-should-you-use-react-in-2023',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '085-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/TvCnpy-Qq_8'
|
|
},
|
|
'Buzzsprout-12413556': {
|
|
slug: 'i-broke-the-rules-of-react-the-results-surprised-me',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '084-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/xc5vwGrs4IY'
|
|
},
|
|
'Buzzsprout-12354761': {
|
|
slug: 'less-stress-and-exploitation-why-we-should-unionize',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '083-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/I4rxbc0EWIc'
|
|
},
|
|
'Buzzsprout-12342672': {
|
|
slug: 'i-made-a-huge-mistake-reflections-on-the-react-js-documentary',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '082-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/nC9dtO0pVbE'
|
|
},
|
|
'Buzzsprout-12260917': {
|
|
slug: 'my-secret-to-successfully-working-in-react-with-a-mental-illness-mental-illness-in-software-part-2',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '081-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/T8kWqE3x3_k'
|
|
},
|
|
'Buzzsprout-12258802': {
|
|
slug: 'boss-what-meds-are-you-on-mental-illness-in-the-software-industry-part-1',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '080-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/nz45jIY4vAg'
|
|
},
|
|
'Buzzsprout-12228273': {
|
|
slug: 'moving-past-failure-learning-react-on-three-hours-per-week-janes-story',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '079-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/uSpm2anwPnI'
|
|
},
|
|
'Buzzsprout-12220716': {
|
|
slug: 'dropping-out-of-college-to-sell-my-first-saas-app',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '078-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/cmT4okpCSrk'
|
|
},
|
|
'Buzzsprout-12207725': {
|
|
slug: 'the-truth-about-react-server-components',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '077-mixed.srt')).toString()),
|
|
youtube: 'https://www.youtube.com/embed/aO9MrsK0Mos'
|
|
},
|
|
'Buzzsprout-12158608': {
|
|
slug: 'how-using-typescript-actually-makes-your-program-worse',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '076-mixed.srt')).toString())
|
|
},
|
|
'Buzzsprout-12157221': {
|
|
slug: 'flying-in-a-private-jet-my-first-programming-job'
|
|
},
|
|
'Buzzsprout-12142504': {
|
|
slug: 'from-a-career-in-logic-gates-to-react-with-evan-walter',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', '074-mixed.srt')).toString())
|
|
},
|
|
'Buzzsprout-12076221': {
|
|
slug: 'a-fundamentally-new-react-my-journey-with-react-server-components',
|
|
transcript: srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', 'Buzzsprout-12076221.srt')).toString())
|
|
},
|
|
'Buzzsprout-12033274': {
|
|
slug: 'learning-react-on-only-3-hours-per-week-while-working-full-time'
|
|
},
|
|
'Buzzsprout-11941927': {
|
|
slug: 'testing-useeffect-porting-rn-app-to-web'
|
|
},
|
|
'Buzzsprout-11918765': {
|
|
slug: 'react-2022-year-in-review-foundational-changes'
|
|
},
|
|
'Buzzsprout-11912454': {
|
|
slug: 'news-dec-21st-chatgpt-swr-20-wasp-mfa-ci-react-visual-cms-flash-in-2022'
|
|
},
|
|
'Buzzsprout-11879575': {
|
|
slug: 'how-i-built-my-own-react'
|
|
},
|
|
'Buzzsprout-11802072': {
|
|
slug: 'faq-typescript-svelte'
|
|
},
|
|
'Buzzsprout-11802002': {
|
|
slug: 'thinking-in-react'
|
|
},
|
|
'Buzzsprout-11757420': {
|
|
slug: 'how-decentralized-is-crypto-really'
|
|
},
|
|
'Buzzsprout-11683392': {
|
|
slug: 'concise-ish-beginners-guide-to-learning-react' // TODO extra content
|
|
},
|
|
'Buzzsprout-11586984': {
|
|
slug: 'its-not-your-fault-you-dont-understand-the-code'
|
|
},
|
|
'Buzzsprout-11533367': {
|
|
slug: 'your-boss-is-wrong-and-how-slow-is-react'
|
|
},
|
|
'Buzzsprout-11500932': {
|
|
slug: 'the-reality-of-micro-frontends-and-why-i-dont-recommend-them'
|
|
},
|
|
'Buzzsprout-11235167': {
|
|
slug: 'react-faq'
|
|
},
|
|
'Buzzsprout-11235154': {
|
|
slug: 'remix-as-fast-as-instant'
|
|
},
|
|
'Buzzsprout-11193020': {
|
|
slug: 'noobs-vs-experts-with-kyle-verhoef'
|
|
},
|
|
'Buzzsprout-11130436': {
|
|
slug: 'oops-i-built-the-wrong-thing'
|
|
},
|
|
'Buzzsprout-11086813': {
|
|
slug: 'a-new-react-compiler'
|
|
},
|
|
'Buzzsprout-10735883': {
|
|
slug: 'forms-still-suck-can-we-design-something-better'
|
|
},
|
|
'Buzzsprout-10402825': {
|
|
slug: 'how-to-build-react-features-right-the-first-time'
|
|
},
|
|
'Buzzsprout-10365089': {
|
|
slug: 'why-react-should-die'
|
|
},
|
|
'Buzzsprout-10317720': {
|
|
slug: 'how-javascript-actually-executes'
|
|
},
|
|
'Buzzsprout-10278986': {
|
|
slug: 'whats-the-hype-about-shopify-hydrogen'
|
|
},
|
|
'Buzzsprout-10229771': {
|
|
slug: 'preventing-startup-burnout-with-brian-wetzel-part-2'
|
|
},
|
|
'Buzzsprout-10181548': {
|
|
slug: 'preventing-startup-burnout-with-brian-wetzel-part-1'
|
|
},
|
|
'Buzzsprout-10138345': {
|
|
slug: 'taking-the-pain-out-of-forms-in-react'
|
|
},
|
|
'Buzzsprout-10037837': {
|
|
slug: 'what-are-react-server-components-and-why-theyre-awesome'
|
|
},
|
|
'Buzzsprout-10037718': {
|
|
slug: 'react-fibers-how-your-app-actually-executes'
|
|
},
|
|
'Buzzsprout-10011866': {
|
|
slug: 'how-to-successfully-test-react-apps-using-cypress'
|
|
},
|
|
'Buzzsprout-9935994': {
|
|
slug: 'chris-keen-on-succeeding-as-a-react-contractor'
|
|
},
|
|
'Buzzsprout-9926848': {
|
|
slug: 'query-caching-why-you-must-use-it-with-react-using-react-query'
|
|
},
|
|
'Buzzsprout-9886172': {
|
|
slug: 'where-and-how-to-store-data-from-your-react-application'
|
|
},
|
|
'Buzzsprout-9842114': {
|
|
slug: 'how-to-stop-wasting-your-time'
|
|
},
|
|
'Buzzsprout-9811470': {
|
|
slug: 'react-component-lifecycle-what-is-a-component'
|
|
},
|
|
'Buzzsprout-9781457': {
|
|
slug: 'why-you-need-to-check-software-licenses'
|
|
},
|
|
'Buzzsprout-9740045': {
|
|
slug: 'alternatives-to-the-software-interview-getting-a-react-job'
|
|
},
|
|
'Buzzsprout-9698201': {
|
|
slug: 'what-do-you-think-of-react-and-other-qa'
|
|
},
|
|
'Buzzsprout-9656919': {
|
|
slug: 'refactoring-quickly-safely-and-easily'
|
|
},
|
|
'Buzzsprout-9608790': {
|
|
slug: 'how-to-diagnose-react-app-bottlenecks-with-the-profiler'
|
|
},
|
|
'Buzzsprout-9545960': {
|
|
slug: 'so-where-do-you-host-your-react-app'
|
|
},
|
|
'Buzzsprout-9502941': {
|
|
slug: 'is-your-react-app-killing-the-planet'
|
|
},
|
|
'Buzzsprout-9464470': {
|
|
slug: 'better-routing-in-react-with-nextjs'
|
|
},
|
|
'Buzzsprout-9451117': {
|
|
slug: 'debug-smarter-in-your-react-apps'
|
|
},
|
|
}
|
|
|
|
const slugToEpisode = {}
|
|
Object.entries(episodeExtra).forEach(([id, { slug }]) => {
|
|
slugToEpisode[slug] = id
|
|
})
|
|
|
|
export async function getEpisodes() {
|
|
const feedRes = await fetch('https://feeds.buzzsprout.com/1764837.rss', { next: { revalidate: 60 * 10 } });
|
|
|
|
const feedString = await feedRes.text()
|
|
// const feedString = fs.readFileSync('./feed.rss').toString()
|
|
|
|
let feed = await extractFromXml(feedString,
|
|
{
|
|
getExtraEntryFields: (feedEntry) => {
|
|
const {
|
|
enclosure
|
|
} = feedEntry
|
|
return {
|
|
enclosure: {
|
|
url: enclosure['@_url'],
|
|
type: enclosure['@_type'],
|
|
length: enclosure['@_length']
|
|
},
|
|
content: feedEntry['content:encoded'],
|
|
chapters: feedEntry['podcast:chapters'] && feedEntry['podcast:chapters']['@_url'],
|
|
duration: feedEntry['itunes:duration']
|
|
}
|
|
}
|
|
})
|
|
|
|
const numEpisodes = feed.entries.length;
|
|
console.log('---------------- numepisodes: ', numEpisodes);
|
|
const feedEntries = feed.entries.map(
|
|
({ id, title, description, enclosure , published, content, chapters, duration }, i) => ({
|
|
num: numEpisodes - i,
|
|
id,
|
|
title,
|
|
published,
|
|
description,
|
|
content,
|
|
chapters,
|
|
youtube: episodeExtra[id]?.youtube,
|
|
slug: episodeExtra[id]?.slug || title.replace(/[\W_]/g, '-'),
|
|
transcript: episodeExtra[id]?.transcript,
|
|
audio: [enclosure].map((enclosure) => ({
|
|
src: enclosure.url,
|
|
type: enclosure.type,
|
|
length: enclosure.length,
|
|
duration
|
|
}))[0],
|
|
})
|
|
);
|
|
// Should be episodes not published yet so they aren't in the feed.
|
|
const missingEntries = Object.keys(episodeExtra).map((id) => id).filter((idFromExtra) => !feedEntries.find(({ id }) => id === idFromExtra));
|
|
console.log(missingEntries)
|
|
return process.env.NODE_ENV === 'development' ?
|
|
[...missingEntries.map((id, i) => ({
|
|
num: numEpisodes + missingEntries.length - i,
|
|
id,
|
|
title: `UNPUBLISHED: ${episodeExtra[id].slug}`,
|
|
published: 'Fri, 20 Jan 2023 07:00:00 -0800',
|
|
description: 'UNPUBLISHED',
|
|
content: 'UNPUBLISHED',
|
|
chapters: undefined,
|
|
slug: episodeExtra[id].slug,
|
|
transcript: episodeExtra[id]?.transcript,
|
|
audio: {
|
|
src: `https://pdcn.co/e/www.buzzsprout.com/1764837/${id.split('Buzzsprout-')[1]}.mp3`,
|
|
type: 'audio/mpeg',
|
|
},
|
|
})),
|
|
...feedEntries]
|
|
: feedEntries;
|
|
}
|
|
|
|
|
|
/* export async function getEpisodesLocal() {
|
|
* const dbEpisodes = await db.all('select * from episodes order by number desc;');
|
|
* return dbEpisodes.map(({ title, pub_date, summary: description, content, slug, duration, filename, number, episode_type, buzzsprout_id, buzzsprout_url, youtube_url, transcript_filename }) => {
|
|
* const filepath = path.join(process.cwd(), 'public', 'files', 'episodes', filename);
|
|
* return {
|
|
* num: number,
|
|
* id: buzzsprout_id,
|
|
* title,
|
|
* description,
|
|
* content,
|
|
* published: pub_date,
|
|
* chapters: [`https://feeds.buzzsprout.com/1764837/${buzzsprout_id}/chapters.json`],
|
|
* youtube: youtube_url,
|
|
* slug,
|
|
* transcript: transcript_filename ? srtparsejs.parse(fs.readFileSync(path.join(process.cwd(), 'src', 'data', transcript_filename)).toString()) : undefined,
|
|
* audio: {
|
|
* src: buzzsprout_url,
|
|
* type: 'audio/mpeg'
|
|
* },
|
|
* };
|
|
* });
|
|
* } */
|
|
|
|
export async function getEpisode({ episodeSlug }) {
|
|
const episodes = await getEpisodes()
|
|
const episodeId = slugToEpisode[episodeSlug] || episodeSlug
|
|
let episode = episodes.find(({ id }) => id === episodeId) ||
|
|
episodes.find(({ title }) => title.replace(/[\W_]/g, '-') === episodeId)
|
|
if (!episode) {
|
|
return {
|
|
notFound: true,
|
|
}
|
|
}
|
|
|
|
return episode
|
|
}
|