Initial commit
This commit is contained in:
173
backend/src/routes/paywalls.js
Normal file
173
backend/src/routes/paywalls.js
Normal file
@@ -0,0 +1,173 @@
|
||||
import { Router } from 'express';
|
||||
import { paywallService } from '../services/paywall.js';
|
||||
import { authenticate, requireCreator } from '../middleware/auth.js';
|
||||
import { validateBody, createPaywallSchema, updatePaywallSchema } from '../utils/validation.js';
|
||||
import { prisma } from '../config/database.js';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// All routes require authentication
|
||||
router.use(authenticate);
|
||||
router.use(requireCreator);
|
||||
|
||||
// Create paywall
|
||||
router.post('/', validateBody(createPaywallSchema), async (req, res, next) => {
|
||||
try {
|
||||
const paywall = await paywallService.create(req.user.id, req.body);
|
||||
res.status(201).json({ paywall });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// List paywalls
|
||||
router.get('/', async (req, res, next) => {
|
||||
try {
|
||||
const { status, page = 1, limit = 20 } = req.query;
|
||||
const result = await paywallService.listByCreator(req.user.id, {
|
||||
status,
|
||||
page: parseInt(page),
|
||||
limit: parseInt(limit),
|
||||
});
|
||||
res.json(result);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Get paywall stats
|
||||
router.get('/stats', async (req, res, next) => {
|
||||
try {
|
||||
const stats = await paywallService.getStats(req.user.id);
|
||||
res.json(stats);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Fetch URL metadata
|
||||
router.post('/fetch-metadata', async (req, res, next) => {
|
||||
try {
|
||||
const { url } = req.body;
|
||||
if (!url) {
|
||||
return res.status(400).json({ error: 'URL is required' });
|
||||
}
|
||||
const metadata = await paywallService.fetchUrlMetadata(url);
|
||||
res.json(metadata);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Get single paywall
|
||||
router.get('/:id', async (req, res, next) => {
|
||||
try {
|
||||
const paywall = await paywallService.findByIdAndCreator(req.params.id, req.user.id);
|
||||
|
||||
// Get additional stats
|
||||
const [salesCount, totalRevenue] = await Promise.all([
|
||||
prisma.sale.count({ where: { paywallId: paywall.id } }),
|
||||
prisma.sale.aggregate({
|
||||
where: { paywallId: paywall.id },
|
||||
_sum: { netSats: true },
|
||||
}),
|
||||
]);
|
||||
|
||||
res.json({
|
||||
paywall,
|
||||
stats: {
|
||||
salesCount,
|
||||
totalRevenue: totalRevenue._sum.netSats || 0,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Update paywall
|
||||
router.patch('/:id', validateBody(updatePaywallSchema), async (req, res, next) => {
|
||||
try {
|
||||
const paywall = await paywallService.update(req.user.id, req.params.id, req.body);
|
||||
res.json({ paywall });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Archive paywall
|
||||
router.post('/:id/archive', async (req, res, next) => {
|
||||
try {
|
||||
const paywall = await paywallService.archive(req.user.id, req.params.id);
|
||||
res.json({ paywall });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Activate paywall
|
||||
router.post('/:id/activate', async (req, res, next) => {
|
||||
try {
|
||||
await paywallService.findByIdAndCreator(req.params.id, req.user.id);
|
||||
|
||||
const paywall = await prisma.paywall.update({
|
||||
where: { id: req.params.id },
|
||||
data: { status: 'ACTIVE' },
|
||||
});
|
||||
|
||||
res.json({ paywall });
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Get paywall sales
|
||||
router.get('/:id/sales', async (req, res, next) => {
|
||||
try {
|
||||
await paywallService.findByIdAndCreator(req.params.id, req.user.id);
|
||||
|
||||
const { page = 1, limit = 20 } = req.query;
|
||||
const skip = (parseInt(page) - 1) * parseInt(limit);
|
||||
|
||||
const [sales, total] = await Promise.all([
|
||||
prisma.sale.findMany({
|
||||
where: { paywallId: req.params.id },
|
||||
orderBy: { createdAt: 'desc' },
|
||||
skip,
|
||||
take: parseInt(limit),
|
||||
}),
|
||||
prisma.sale.count({ where: { paywallId: req.params.id } }),
|
||||
]);
|
||||
|
||||
res.json({
|
||||
sales,
|
||||
total,
|
||||
page: parseInt(page),
|
||||
totalPages: Math.ceil(total / parseInt(limit)),
|
||||
});
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Get embed code
|
||||
router.get('/:id/embed', async (req, res, next) => {
|
||||
try {
|
||||
const paywall = await paywallService.findByIdAndCreator(req.params.id, req.user.id);
|
||||
const baseUrl = process.env.FRONTEND_URL || 'http://localhost:5173';
|
||||
const apiUrl = process.env.API_URL || 'http://localhost:3001';
|
||||
|
||||
const embedCode = {
|
||||
iframe: `<iframe src="${baseUrl}/embed/${paywall.id}" width="100%" height="400" frameborder="0" style="border-radius: 12px; max-width: 400px;"></iframe>`,
|
||||
button: `<script src="${apiUrl}/js/paywall.js" data-paywall="${paywall.id}" data-theme="auto"></script>`,
|
||||
link: `${baseUrl}/p/${paywall.slug || paywall.id}`,
|
||||
};
|
||||
|
||||
res.json(embedCode);
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
export default router;
|
||||
|
||||
Reference in New Issue
Block a user