backend first draft
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const db = require('../db');
|
||||
|
||||
// GET /api/articles?feed_id=&folder_id=&status=unread|starred|all&search=&page=&limit=
|
||||
router.get('/', (req, res) => {
|
||||
const { feed_id, folder_id, status = 'all', search, page = 1, limit = 30 } = req.query;
|
||||
const clauses = [];
|
||||
const params = {};
|
||||
|
||||
if (feed_id) { clauses.push('a.feed_id = @feed_id'); params.feed_id = feed_id; }
|
||||
if (folder_id) { clauses.push('f.folder_id = @folder_id'); params.folder_id = folder_id; }
|
||||
if (status === 'unread') clauses.push('a.is_read = 0');
|
||||
if (status === 'starred') clauses.push('a.is_starred = 1');
|
||||
if (search) { clauses.push('(a.title LIKE @search OR a.summary LIKE @search)'); params.search = `%${search}%`; }
|
||||
|
||||
const where = clauses.length ? `WHERE ${clauses.join(' AND ')}` : '';
|
||||
const offset = (Number(page) - 1) * Number(limit);
|
||||
|
||||
const articles = db.prepare(`
|
||||
SELECT a.id, a.feed_id, a.title, a.link, a.author, a.summary, a.image_url,
|
||||
a.published_at, a.is_read, a.is_starred,
|
||||
f.title AS feed_title, f.favicon AS feed_favicon
|
||||
FROM articles a
|
||||
JOIN feeds f ON f.id = a.feed_id
|
||||
${where}
|
||||
ORDER BY a.published_at DESC
|
||||
LIMIT @limit OFFSET @offset
|
||||
`).all({ ...params, limit: Number(limit), offset });
|
||||
|
||||
const total = db.prepare(`
|
||||
SELECT COUNT(*) AS count FROM articles a JOIN feeds f ON f.id = a.feed_id ${where}
|
||||
`).get(params).count;
|
||||
|
||||
res.json({ articles, total, page: Number(page), limit: Number(limit) });
|
||||
});
|
||||
|
||||
router.get('/:id', (req, res) => {
|
||||
const article = db.prepare(`
|
||||
SELECT a.*, f.title AS feed_title, f.site_url AS feed_site_url, f.favicon AS feed_favicon
|
||||
FROM articles a JOIN feeds f ON f.id = a.feed_id WHERE a.id = ?
|
||||
`).get(req.params.id);
|
||||
if (!article) return res.status(404).json({ error: 'Article not found' });
|
||||
res.json(article);
|
||||
});
|
||||
|
||||
router.patch('/:id', (req, res) => {
|
||||
const { is_read, is_starred } = req.body;
|
||||
const sets = [];
|
||||
const params = { id: req.params.id };
|
||||
if (is_read !== undefined) { sets.push('is_read = @is_read'); params.is_read = is_read ? 1 : 0; }
|
||||
if (is_starred !== undefined) { sets.push('is_starred = @is_starred'); params.is_starred = is_starred ? 1 : 0; }
|
||||
if (!sets.length) return res.status(400).json({ error: 'Nothing to update' });
|
||||
db.prepare(`UPDATE articles SET ${sets.join(', ')} WHERE id = @id`).run(params);
|
||||
res.json(db.prepare('SELECT * FROM articles WHERE id = ?').get(req.params.id));
|
||||
});
|
||||
|
||||
// Bulk mark-as-read for a feed/folder/all
|
||||
router.post('/mark-read', (req, res) => {
|
||||
const { feed_id, folder_id, all } = req.body;
|
||||
if (all) {
|
||||
db.prepare('UPDATE articles SET is_read = 1 WHERE is_read = 0').run();
|
||||
} else if (feed_id) {
|
||||
db.prepare('UPDATE articles SET is_read = 1 WHERE feed_id = ? AND is_read = 0').run(feed_id);
|
||||
} else if (folder_id) {
|
||||
db.prepare(`UPDATE articles SET is_read = 1 WHERE is_read = 0 AND feed_id IN (SELECT id FROM feeds WHERE folder_id = ?)`).run(folder_id);
|
||||
} else {
|
||||
return res.status(400).json({ error: 'Specify feed_id, folder_id, or all' });
|
||||
}
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user