[READ-ONLY] Mirror of https://github.com/danielroe/roe.dev. This is the code and content for my personal website, built in Nuxt. roe.dev
0

Configure Feed

Select the types of activity you want to include in your feed.

roe.dev / modules / slides.ts
2.5 kB 85 lines
1import { addServerHandler, createResolver, defineNuxtModule, useNuxt, useRuntimeConfig } from 'nuxt/kit' 2import { $fetch } from 'ofetch' 3import { put, head } from '@vercel/blob' 4 5import { listAllRecords } from './shared/atproto-read' 6import type { DevRoeTalk } from '../shared/lex' 7 8export default defineNuxtModule({ 9 meta: { 10 name: 'slides', 11 }, 12 async setup () { 13 const nuxt = useNuxt() 14 const config = useRuntimeConfig() 15 16 if (!config.github.token || nuxt.options._prepare || nuxt.options.test) return 17 18 if (nuxt.options.dev) { 19 const resolver = createResolver(import.meta.url) 20 addServerHandler({ 21 route: '/slides/:id.pdf', 22 handler: resolver.resolve('./runtime/server/slides/[id].pdf'), 23 }) 24 return 25 } 26 27 const $gh = $fetch.create({ 28 baseURL: 'https://api.github.com/repos/danielroe/slides/releases', 29 headers: { 30 Authorization: `token ${config.github.token}`, 31 }, 32 }) 33 34 const token = config.blobReadWriteToken 35 36 const releases = await fetchSlideReleases() 37 38 for (const release of releases) { 39 const pathname = `slides/${release}.pdf` 40 41 const existingBlob = await head(pathname, { token }).catch(() => null) 42 if (!existingBlob) { 43 const ghRelease = await $gh<GitHubRelease>(`/tags/${release}`) 44 const id = ghRelease?.assets.find(a => a.name.endsWith('.pdf'))?.id 45 46 if (!id) continue 47 48 const file = await $gh(`/assets/${id}`, { 49 responseType: 'arrayBuffer', 50 headers: { Accept: 'application/octet-stream' }, 51 }) 52 53 // Upload file to Vercel Blob 54 const blob = await put(pathname, Buffer.from(file), { 55 access: 'public', 56 token, 57 contentType: 'application/pdf', 58 }) 59 60 nuxt.options.routeRules ||= {} 61 nuxt.options.routeRules[`/slides/${release}.pdf`] = { 62 redirect: blob.url, 63 } 64 } 65 else { 66 // File already exists, set up route rule with existing blob URL 67 nuxt.options.routeRules ||= {} 68 nuxt.options.routeRules[`/slides/${release}.pdf`] = { 69 redirect: existingBlob.url, 70 } 71 } 72 } 73 }, 74}) 75 76async function fetchSlideReleases (): Promise<string[]> { 77 const records = await listAllRecords<DevRoeTalk.Record>('dev.roe.talk') 78 return records 79 .map(r => r.value.slides) 80 .filter((s): s is string => Boolean(s)) 81} 82 83interface GitHubRelease { 84 assets: Array<{ id: number, name: string }> 85}