import axios from 'axios'
import crypto from 'crypto'
import fs from 'fs'
import path from 'path'
const formatDate = (date = new Date) => {
const year = date.getFullYear ()
const month = (date.getMonth () + 1).toString ().padStart (2, '0')
const day = date.getDate ().toString ().padStart (2, '0')
return `${ year }-${ month }-${ day }`
}
const SITE_TITLE = 'ぼざクリ タグ広場'
const DOMAIN = 'https://hub.nizika.monster'
const API_BASE_URL = 'https://hub.nizika.monster/api'
const fetchPosts = async tagName => (await axios.get (`${ API_BASE_URL }/posts`,
{ params: { ...(tagName && { tags: tagName,
match: 'all',
limit: '20' }) } })).data.posts
const fetchPostIds = async () => (await fetchPosts ()).map (post => post.id)
const fetchTags = async () => (await axios.get (`${ API_BASE_URL }/tags`)).data
const fetchTagNames = async () => (await fetchTags ()).map (tag => tag.name)
const fetchWikiPages = async () => (await axios.get (`${ API_BASE_URL }/wiki`)).data
const fetchWikiTitles = async () => (await fetchWikiPages ()).map (page => page.title)
const createPostListOutlet = async tagName => `
${ (await fetchPosts (tagName)).map (post => `
`).join ('') }
`
const createPostDetailOutlet = post => `
${ ['deerjikist', 'meme', 'character', 'general', 'material', 'meta', 'nico']
.map (cat => '
' + post.tags.filter (tag => tag.category === cat).map (tag => `
-
?
${ tag.name }
${ tag['post_count'] }
`).join ('') + '
').join ('') }
`
const posts = (await fetchPosts ()).map (post => [
`/posts/${ post.id }`,
`${ post.title || post.url } | ${ SITE_TITLE }`,
createPostDetailOutlet (post)])
const tags = []
for (const tag of await fetchTags ())
{
tags.push ([`/posts?${ new URLSearchParams ({ tags: tag.name }) }`,
`${ tag.name } | ${ SITE_TITLE }`,
await createPostListOutlet (tag.name)])
}
const wikiPages = (await fetchWikiPages ()).map (page => [
`/wiki/${ encodeURIComponent (page.title) }`,
`${ page.title } Wiki | ${ SITE_TITLE }`])
const routes = [
['/', `${ SITE_TITLE } 〜 ぼざろクリーチャーシリーズ綜合リンク集`,
await createPostListOutlet (), `
`],
...tags,
...posts,
['/wiki', `Wiki | ${ SITE_TITLE }`],
...wikiPages]
const xml = `
${ routes.map (([route]) => `
${ DOMAIN }${ route }
${ formatDate () }
daily
`).join ('\n') }
`
const rss = `
The Series of Bocchi the Rock! Creatures Hub Feed
${ DOMAIN }/
最新の投稿、タグ、Wiki ページの一覧
ja
${ (new Date).toUTCString () }
${ routes.map (([route, title]) => ` -
${ title }
${ DOMAIN }${ route }
${ DOMAIN }${ route }
${ (new Date).toUTCString () }
`).join ('\n') }
`
fs.writeFileSync (path.resolve ('dist/sitemap.xml'), xml)
fs.writeFileSync (path.resolve ('dist/rss.xml'), rss)
const baseHTML = fs.readFileSync (path.resolve ('dist/index.html'), 'utf8')
let htaccess = fs.readFileSync (path.resolve ('dist/.htaccess'), 'utf8')
routes.forEach (([route, title, outlet, helmet]) => {
const fileName = (
route === '/'
? 'index.html'
: `${ crypto.createHash ('sha256').update (encodeURIComponent (route)).digest ('hex') }.html`)
let html = baseHTML.replace (/(?<=).*?(?=<\/title>)/, title)
html = html.replace ('', outlet || '')
html = html.replace ('', helmet || '')
fs.writeFileSync (path.resolve (`dist/${ fileName }`), html)
const [routeBase, q] = route.split ('?')
if (route !== '/')
{
htaccess = htaccess.replace ('# routes #', `
RewriteCond %{REQUEST_URI} ^${ routeBase }$
${ q ? `RewriteCond %{QUERY_STRING} (^|&)${ q }(&|$)` : '' }
RewriteRule ^ /${ fileName } [L]
# routes #
`)
}
})
fs.writeFileSync (path.resolve ('dist/.htaccess'), htaccess.replace ('# routes #', ''))