86 lines
3.1 KiB
JavaScript
86 lines
3.1 KiB
JavaScript
import db from "../sql.mjs";
|
|
|
|
import lib from "../lib.mjs";
|
|
|
|
export default (router, tpl) => {
|
|
|
|
// Admin View
|
|
router.get(/^\/admin\/emojis\/?$/, lib.auth, async (req, res) => {
|
|
res.reply({
|
|
body: tpl.render("admin/emojis", { session: req.session, tmp: null }, req)
|
|
});
|
|
});
|
|
|
|
// List all emojis (Public)
|
|
router.get('/api/v2/emojis', async (req, res) => {
|
|
try {
|
|
const emojis = await db`SELECT id, name, url FROM custom_emojis ORDER BY name ASC`;
|
|
return res.reply({
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ success: true, emojis })
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
return res.reply({ code: 500, body: JSON.stringify({ success: false, message: "Database error" }) });
|
|
}
|
|
});
|
|
|
|
// Add emoji (Admin only)
|
|
router.post('/api/v2/admin/emojis', async (req, res) => {
|
|
if (!req.session || !req.session.admin) {
|
|
return res.reply({ code: 403, body: JSON.stringify({ success: false, message: "Forbidden" }) });
|
|
}
|
|
|
|
const body = req.post || {};
|
|
const name = body.name ? body.name.trim().toLowerCase() : '';
|
|
const url = body.url ? body.url.trim() : '';
|
|
|
|
if (!name || !url) {
|
|
return res.reply({ body: JSON.stringify({ success: false, message: "Name and URL required" }) });
|
|
}
|
|
|
|
// Basic name validation (alphanumeric)
|
|
if (!/^[a-z0-9_]+$/.test(name)) {
|
|
return res.reply({ body: JSON.stringify({ success: false, message: "Invalid name. Use lowercase a-z, 0-9, _ only." }) });
|
|
}
|
|
|
|
try {
|
|
const newEmoji = await db`
|
|
INSERT INTO custom_emojis (name, url) VALUES (${name}, ${url})
|
|
RETURNING id, name, url
|
|
`;
|
|
return res.reply({
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ success: true, emoji: newEmoji[0] })
|
|
});
|
|
} catch (e) {
|
|
if (e.code === '23505') { // Unique violation
|
|
return res.reply({ body: JSON.stringify({ success: false, message: "Emoji name already exists" }) });
|
|
}
|
|
console.error(e);
|
|
return res.reply({ code: 500, body: JSON.stringify({ success: false, message: "Database error" }) });
|
|
}
|
|
});
|
|
|
|
// Delete emoji (Admin only)
|
|
router.post(/\/api\/v2\/admin\/emojis\/(?<id>\d+)\/delete/, async (req, res) => {
|
|
if (!req.session || !req.session.admin) {
|
|
return res.reply({ code: 403, body: JSON.stringify({ success: false, message: "Forbidden" }) });
|
|
}
|
|
const id = req.params.id;
|
|
|
|
try {
|
|
await db`DELETE FROM custom_emojis WHERE id = ${id}`;
|
|
return res.reply({
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ success: true })
|
|
});
|
|
} catch (e) {
|
|
console.error(e);
|
|
return res.reply({ code: 500, body: JSON.stringify({ success: false, message: "Database error" }) });
|
|
}
|
|
});
|
|
|
|
return router;
|
|
};
|