122 lines
4.0 KiB
JavaScript
122 lines
4.0 KiB
JavaScript
const express = require('express');
|
|
const cors = require('cors');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
const { parseHSQLDB } = require('./hsqldbParser');
|
|
|
|
const app = express();
|
|
const PORT = 3637;
|
|
const DB_DIR = '/home/paulh/.openclaw/workspace/docs/pauls-blogs/Paul/database';
|
|
const EXPORT_FILE = path.join(__dirname, 'blog-export.json');
|
|
const IMAGE_DIR = '/home/paulh/.openclaw/workspace/docs/pauls-blogs/Paul/1096292361887/web';
|
|
|
|
app.use(cors());
|
|
// Serve blog images statically
|
|
// Assuming image paths in blog posts are relative or absolute within the blog structure
|
|
// We'll serve the specific blog's web folder at the root path or a specific prefix
|
|
// Let's check a sample post content to see how images are referenced first
|
|
app.use('/1096292361887/web', express.static(IMAGE_DIR));
|
|
// Also serve at root just in case paths are relative
|
|
app.use('/', express.static(IMAGE_DIR));
|
|
|
|
let cachedEntries = [];
|
|
let usingExport = false;
|
|
|
|
// Load entries on startup
|
|
try {
|
|
if (fs.existsSync(EXPORT_FILE)) {
|
|
console.log('Loading clean data from blog-export.json...');
|
|
const rawData = fs.readFileSync(EXPORT_FILE, 'utf8');
|
|
cachedEntries = JSON.parse(rawData);
|
|
usingExport = true;
|
|
console.log(`Successfully loaded ${cachedEntries.length} clean entries from JSON export.`);
|
|
} else {
|
|
console.log('No export file found, falling back to HSQLDB parser...');
|
|
cachedEntries = parseHSQLDB(DB_DIR);
|
|
console.log(`Loaded ${cachedEntries.length} entries from HSQLDB (Legacy Parser)`);
|
|
}
|
|
} catch (err) {
|
|
console.error('Failed to load database:', err.message);
|
|
}
|
|
|
|
// List all posts with minimal data
|
|
app.get('/api/posts', (req, res) => {
|
|
const items = cachedEntries.map((e, idx) => {
|
|
if (usingExport) {
|
|
return {
|
|
id: e.id,
|
|
title: e.title || 'Untitled',
|
|
date: e.date || '',
|
|
author: e.author || 'Paul',
|
|
category: e.categories || '',
|
|
};
|
|
} else {
|
|
return {
|
|
id: idx,
|
|
title: e.TITLE || 'Untitled',
|
|
date: e.TIMESTAMP || '',
|
|
author: e.AUTHOR || 'Paul',
|
|
category: e.CATEGORIES || '',
|
|
};
|
|
}
|
|
});
|
|
// Sort by date descending if using export (dates are cleaner)
|
|
if (usingExport) {
|
|
items.sort((a, b) => new Date(b.date) - new Date(a.date));
|
|
}
|
|
res.json(items);
|
|
});
|
|
|
|
// Get full data for one post
|
|
app.get('/api/posts/:id', (req, res) => {
|
|
const id = parseInt(req.params.id);
|
|
let post = null;
|
|
|
|
if (usingExport) {
|
|
post = cachedEntries.find(p => p.id === id);
|
|
} else {
|
|
post = cachedEntries[id];
|
|
}
|
|
|
|
if (!post) return res.status(404).json({error: 'Post not found.'});
|
|
|
|
if (usingExport) {
|
|
// Fix old Windows file paths in image src attributes
|
|
let body = post.content || '';
|
|
|
|
// Match: file:///\\paulspc2\...\Weblogs/FILENAME.jpg
|
|
// Replace with: http://HOSTNAME:3637/FILENAME.jpg (full URL to backend)
|
|
const hostname = req.get('host') || 'localhost:3637';
|
|
const protocol = req.protocol || 'http';
|
|
|
|
body = body.replace(
|
|
/src="file:\/\/\/\\\\[^"]*[\\\/]([^\\\/]+\.(jpg|jpeg|png|gif))"/gi,
|
|
`src="${protocol}://${hostname}/$1"`
|
|
);
|
|
|
|
res.json({
|
|
title: post.title || 'Untitled',
|
|
date: post.date || '',
|
|
author: post.author || 'Paul',
|
|
category: post.categories || '',
|
|
body: body,
|
|
draft: false,
|
|
modified: '',
|
|
});
|
|
} else {
|
|
res.json({
|
|
title: post.TITLE || 'Untitled',
|
|
date: post.TIMESTAMP || '',
|
|
author: post.AUTHOR || 'Paul',
|
|
category: post.CATEGORIES || '',
|
|
body: post.ENTRY || '',
|
|
draft: post.DRAFT || false,
|
|
modified: post.MODIFIED || '',
|
|
});
|
|
}
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`Thingamablog-v2 backend running on port ${PORT}`);
|
|
});
|