190600
This commit is contained in:
0
scripts/change_post_banner.js
Normal file
0
scripts/change_post_banner.js
Normal file
173
scripts/db_to_md.js
Normal file
173
scripts/db_to_md.js
Normal file
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* Load all posts from my blog database and write them to Markdown file
|
||||
*
|
||||
* usage:
|
||||
*
|
||||
* node db_to_md.js db_username db_password
|
||||
*/
|
||||
|
||||
import { dirname, join } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import * as fs from 'node:fs'
|
||||
import mysql from 'mysql2/promise'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = dirname(__filename)
|
||||
|
||||
class BlogToMarkdown {
|
||||
databaseName = 'godruoyi'
|
||||
|
||||
host = '127.0.0.1'
|
||||
|
||||
port = 13306
|
||||
|
||||
constructor() {
|
||||
const { username, password } = this.parseProcessArgs()
|
||||
|
||||
this.username = username
|
||||
this.password = password
|
||||
}
|
||||
|
||||
async run() {
|
||||
this.connection = await this.connectMySQL(this.username, this.password)
|
||||
|
||||
const categoryMap = await this.fetchCategories()
|
||||
const posts = await this.fetchPosts()
|
||||
|
||||
const formatedPosts = this.formatPosts(categoryMap, posts)
|
||||
|
||||
for (const p of formatedPosts) {
|
||||
// this.writePostToMarkdown(p)
|
||||
await this.savePostBanner(p)
|
||||
}
|
||||
|
||||
console.log('All done')
|
||||
}
|
||||
|
||||
async savePostBanner(post) {
|
||||
const filePath = this.postBannerFilePath(post)
|
||||
console.log('savePostBanner', filePath)
|
||||
|
||||
const response = await fetch(post.banner)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('download image failed')
|
||||
}
|
||||
|
||||
const arrayBuffer = await response.arrayBuffer()
|
||||
fs.writeFileSync(filePath, Buffer.from(arrayBuffer))
|
||||
}
|
||||
|
||||
async fetchPosts() {
|
||||
const query = 'SELECT * FROM posts ORDER BY id ASC'
|
||||
|
||||
const [rows] = await this.connection.execute(query)
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
async fetchCategories() {
|
||||
const query = 'SELECT * FROM categories ORDER BY id ASC'
|
||||
|
||||
const [rows] = await this.connection.execute(query)
|
||||
|
||||
return rows.reduce((map, obj) => map.set(obj.id, obj), new Map())
|
||||
}
|
||||
|
||||
writePostToMarkdown(post) {
|
||||
console.log(`saving post to markdown: ${post.title}`)
|
||||
|
||||
const file = this.postToMarkdownFilePath(post)
|
||||
const content = this.convertPostToMarkdown(post)
|
||||
|
||||
fs.writeFileSync(file, content, 'utf-8')
|
||||
}
|
||||
|
||||
postToMarkdownFilePath(p) {
|
||||
return join(__dirname, `./../src/content/posts/${p.slug}.md`)
|
||||
}
|
||||
|
||||
postBannerFilePath(p) {
|
||||
const name = new URL(p.banner).pathname.split('/').pop()
|
||||
return join(__dirname, `./../src/images/posts/${name}`)
|
||||
}
|
||||
|
||||
convertPostToMarkdown(post) {
|
||||
return `---
|
||||
title: "${post.title}"
|
||||
description: "${post.description}"
|
||||
pubDate: "${this.formatDate(post.pubDate)}"
|
||||
category: "${post.category.slug}"
|
||||
cardImage: "${post.banner}"
|
||||
tags: ["${post.category.slug}"]
|
||||
oldViewCount: ${post.viewCount}
|
||||
oldKeywords: ["${post.keyword}"]
|
||||
---
|
||||
|
||||
${post.content}
|
||||
`
|
||||
}
|
||||
|
||||
formatPosts(categoryMap, posts) {
|
||||
return posts.map((p) => {
|
||||
return {
|
||||
title: p.title,
|
||||
description: p.excerpt,
|
||||
pubDate: p.created_at,
|
||||
banner: p.banner,
|
||||
category_id: p.category_id,
|
||||
category: categoryMap.get(p.category_id),
|
||||
slug: p.slug,
|
||||
viewCount: p.view_count,
|
||||
content: p.content,
|
||||
id: p.id,
|
||||
keyword: p.keyword,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async connectMySQL(username, password) {
|
||||
return mysql.createConnection({
|
||||
host: this.host,
|
||||
port: this.port,
|
||||
user: username,
|
||||
password,
|
||||
database: this.databaseName,
|
||||
})
|
||||
}
|
||||
|
||||
closeConnection() {
|
||||
if (this.connection) {
|
||||
this.connection.close()
|
||||
}
|
||||
}
|
||||
|
||||
parseProcessArgs() {
|
||||
const username = process.argv[2]
|
||||
const password = process.argv[3]
|
||||
|
||||
if (!username || !password) {
|
||||
throw new Error('Missing username or password')
|
||||
}
|
||||
|
||||
return { username, password }
|
||||
}
|
||||
|
||||
formatDate(date) {
|
||||
const newDate = new Date(date.getTime() + 8 * 60 * 60 * 1000) // Date object uses milliseconds
|
||||
|
||||
const yyyy = newDate.getUTCFullYear()
|
||||
const mm = String(newDate.getUTCMonth() + 1).padStart(2, '0') // Months are zero based
|
||||
const dd = String(newDate.getUTCDate()).padStart(2, '0')
|
||||
|
||||
const hh = String(newDate.getUTCHours()).padStart(2, '0')
|
||||
const mi = String(newDate.getUTCMinutes()).padStart(2, '0')
|
||||
const ss = String(newDate.getUTCSeconds()).padStart(2, '0')
|
||||
|
||||
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
|
||||
}
|
||||
}
|
||||
|
||||
const x = new BlogToMarkdown()
|
||||
await x.run()
|
||||
await process.exit(0)
|
||||
Reference in New Issue
Block a user