chore: minor post update and script changes
02253b5d
2 file(s) · +70 −19
| 86 | 86 | .replace(/\s+/g, "-"); |
|
| 87 | 87 | } |
|
| 88 | 88 | ||
| 89 | - | async function getRecentPosts(limit: number = 5): Promise<BlogPost[]> { |
|
| 89 | + | async function getRecentPosts(limit: number = 1): Promise<BlogPost[]> { |
|
| 90 | 90 | const files = fs.readdirSync(CONTENT_DIR); |
|
| 91 | 91 | const posts: BlogPost[] = []; |
|
| 92 | 92 | ||
| 184 | 184 | return response.data.uri; |
|
| 185 | 185 | } |
|
| 186 | 186 | ||
| 187 | + | async function updateAtProtoDocument( |
|
| 188 | + | agent: AtpAgent, |
|
| 189 | + | post: BlogPost, |
|
| 190 | + | atUri: string, |
|
| 191 | + | ): Promise<void> { |
|
| 192 | + | // Parse the atUri to get the repo, collection, and rkey |
|
| 193 | + | // Format: at://did:plc:xxx/collection/rkey |
|
| 194 | + | const uriMatch = atUri.match(/^at:\/\/([^/]+)\/([^/]+)\/(.+)$/); |
|
| 195 | + | if (!uriMatch) { |
|
| 196 | + | throw new Error(`Invalid atUri format: ${atUri}`); |
|
| 197 | + | } |
|
| 198 | + | ||
| 199 | + | const [, repo, collection, rkey] = uriMatch; |
|
| 200 | + | ||
| 201 | + | const postPath = `/posts/${post.slug}`; |
|
| 202 | + | const markdownContent = { |
|
| 203 | + | $type: "site.standard.content.markdown", |
|
| 204 | + | markdown: post.content.trim(), |
|
| 205 | + | }; |
|
| 206 | + | ||
| 207 | + | const textContent = stripMarkdownForText(post.content); |
|
| 208 | + | ||
| 209 | + | // Parse the publish date |
|
| 210 | + | const publishDate = new Date(post.frontmatter.publishDate); |
|
| 211 | + | ||
| 212 | + | const record = { |
|
| 213 | + | $type: "site.standard.document", |
|
| 214 | + | title: post.frontmatter.title, |
|
| 215 | + | site: PUBLICATION_URI, |
|
| 216 | + | path: postPath, |
|
| 217 | + | content: markdownContent, |
|
| 218 | + | textContent: textContent.slice(0, 10000), // Limit text content length |
|
| 219 | + | publishedAt: publishDate.toISOString(), |
|
| 220 | + | canonicalUrl: `${SITE_URL}${postPath}`, |
|
| 221 | + | location: "main-blog", |
|
| 222 | + | }; |
|
| 223 | + | ||
| 224 | + | await agent.com.atproto.repo.putRecord({ |
|
| 225 | + | repo: agent.session!.did, |
|
| 226 | + | collection, |
|
| 227 | + | rkey, |
|
| 228 | + | record, |
|
| 229 | + | }); |
|
| 230 | + | } |
|
| 231 | + | ||
| 187 | 232 | async function main() { |
|
| 188 | 233 | // Check for required environment variables |
|
| 189 | 234 | const identifier = process.env.ATP_IDENTIFIER; |
|
| 214 | 259 | } |
|
| 215 | 260 | ||
| 216 | 261 | console.log("\nFetching recent posts..."); |
|
| 217 | - | const posts = await getRecentPosts(5); |
|
| 262 | + | const posts = await getRecentPosts(1); |
|
| 218 | 263 | ||
| 219 | 264 | console.log(`Found ${posts.length} recent posts\n`); |
|
| 220 | 265 | ||
| 221 | 266 | let publishedCount = 0; |
|
| 267 | + | let updatedCount = 0; |
|
| 222 | 268 | let skippedCount = 0; |
|
| 223 | 269 | ||
| 224 | 270 | for (const post of posts) { |
|
| 225 | 271 | console.log(`Processing: ${post.frontmatter.title}`); |
|
| 226 | 272 | ||
| 227 | - | if (post.frontmatter.atUri) { |
|
| 228 | - | console.log(` - Already has atUri, skipping\n`); |
|
| 229 | - | skippedCount++; |
|
| 230 | - | continue; |
|
| 231 | - | } |
|
| 232 | - | ||
| 233 | 273 | if (post.frontmatter.hidden) { |
|
| 234 | 274 | console.log(` - Post is hidden, skipping\n`); |
|
| 235 | 275 | skippedCount++; |
|
| 237 | 277 | } |
|
| 238 | 278 | ||
| 239 | 279 | try { |
|
| 240 | - | console.log(` - Creating ATProto document...`); |
|
| 241 | - | const atUri = await createAtProtoDocument(agent, post); |
|
| 242 | - | console.log(` - Created: ${atUri}`); |
|
| 280 | + | if (post.frontmatter.atUri) { |
|
| 281 | + | console.log(` - Found existing atUri, updating document...`); |
|
| 282 | + | await updateAtProtoDocument(agent, post, post.frontmatter.atUri); |
|
| 283 | + | console.log(` - Updated: ${post.frontmatter.atUri}\n`); |
|
| 284 | + | updatedCount++; |
|
| 285 | + | } else { |
|
| 286 | + | console.log(` - Creating ATProto document...`); |
|
| 287 | + | const atUri = await createAtProtoDocument(agent, post); |
|
| 288 | + | console.log(` - Created: ${atUri}`); |
|
| 243 | 289 | ||
| 244 | - | // Update the file with the new atUri |
|
| 245 | - | const updatedContent = updateFrontmatterWithAtUri(post.rawContent, atUri); |
|
| 246 | - | fs.writeFileSync(post.filePath, updatedContent); |
|
| 247 | - | console.log( |
|
| 248 | - | ` - Updated frontmatter in ${path.basename(post.filePath)}\n`, |
|
| 249 | - | ); |
|
| 290 | + | // Update the file with the new atUri |
|
| 291 | + | const updatedContent = updateFrontmatterWithAtUri( |
|
| 292 | + | post.rawContent, |
|
| 293 | + | atUri, |
|
| 294 | + | ); |
|
| 295 | + | fs.writeFileSync(post.filePath, updatedContent); |
|
| 296 | + | console.log( |
|
| 297 | + | ` - Updated frontmatter in ${path.basename(post.filePath)}\n`, |
|
| 298 | + | ); |
|
| 250 | 299 | ||
| 251 | - | publishedCount++; |
|
| 300 | + | publishedCount++; |
|
| 301 | + | } |
|
| 252 | 302 | } catch (error) { |
|
| 253 | 303 | console.error(` - Error publishing: ${error}\n`); |
|
| 254 | 304 | } |
|
| 256 | 306 | ||
| 257 | 307 | console.log("---"); |
|
| 258 | 308 | console.log(`Published: ${publishedCount}`); |
|
| 309 | + | console.log(`Updated: ${updatedCount}`); |
|
| 259 | 310 | console.log(`Skipped: ${skippedCount}`); |
|
| 260 | 311 | } |
|
| 261 | 312 | ||
| 104 | 104 | ||
| 105 | 105 | I also plan to include a link to this post as an update on my [/now](/now) page if you want to check out the implementation and leave a comment! While my main blog doesn't have comments I did write a script that will now create documents on ATProto so they should be indexed as well. |
|
| 106 | 106 | ||
| 107 | - | Wrapping up, this experience has been a great culmination of everything I've been prioritizing with the web, that being content publishing and sharing that content through open channels like RSS. Standard.site opens up a whole new world of possibilities for that this could look like in the near future, and takes us a step closer to a truly open web that I long to see. |
|
| 107 | + | Wrapping up, this experience has been a great culmination of everything I've been prioritizing with the web, that being content publishing and sharing that content through open channels like RSS. Standard.site opens up a whole new world of possibilities for what this could look like in the near future, and takes us a step closer to a truly open web that I long to see. |