import express from 'express'; import { PrismaClient } from '@prisma/client'; // Import Prisma Client import { getMantisSettings, saveTicketToDatabase } from '../services/mantisDownloader.js'; import axios from 'axios'; import reader from '@kenjiuno/msgreader'; const MsgReader = reader.default; const prisma = new PrismaClient(); // Instantiate Prisma Client const router = express.Router(); // GET /mantis - Fetch multiple Mantis issues with filtering and pagination router.get('/', async(req, res) => { const { page = 1, limit = 10, status, priority, severity, reporterUsername, search } = req.query; const pageNum = parseInt(page, 10); const limitNum = parseInt(limit, 10); const skip = (pageNum - 1) * limitNum; const where = {}; if (status) where.status = status; if (priority) where.priority = priority; if (severity) where.severity = severity; if (reporterUsername) where.reporterUsername = reporterUsername; if (search) { where.OR = [ { title: { contains: search, mode: 'insensitive' } }, { description: { contains: search, mode: 'insensitive' } }, ]; // If the search term is a number, treat it as an ID const searchNum = parseInt(search, 10); if (!isNaN(searchNum)) { where.OR.push({ id: searchNum }); } } try { let [issues, totalCount] = await prisma.$transaction([ prisma.mantisIssue.findMany({ where, skip, take: limitNum, orderBy: { updatedAt: 'desc', // Default sort order }, // You might want to include related data like comments count later // include: { _count: { select: { comments: true } } } }), prisma.mantisIssue.count({ where }), ]); if (!issues || issues.length === 0) { //If it's numeric, try to download the issue from Mantis const searchNum = parseInt(search, 10); if (!isNaN(searchNum)) { let data; try { data = await saveTicketToDatabase(searchNum); } catch (error) { console.error('Error saving ticket to database:', error.message); return res.status(404).json({ error: 'Mantis issue not found' }); } if (!data) { return res.status(404).json({ error: 'Mantis issue not found' }); } // Fetch the issue again from the database issues = await prisma.mantisIssue.findMany({ where, skip, take: limitNum, orderBy: { updatedAt: 'desc', // Default sort order }, }); if (issues.length === 0) { return res.status(404).json({ error: 'Mantis issue not found' }); } totalCount = await prisma.mantisIssue.count({ where }); } } res.json({ data: issues, pagination: { total: totalCount, page: pageNum, limit: limitNum, totalPages: Math.ceil(totalCount / limitNum), }, }); } catch (error) { console.error('Error fetching Mantis issues:', error.message); res.status(500).json({ error: 'Failed to fetch Mantis issues' }); } }); // GET /mantis/:id - Fetch a single Mantis issue by ID router.get('/:id', async(req, res) => { const { id } = req.params; const issueId = parseInt(id, 10); if (isNaN(issueId)) { return res.status(400).json({ error: 'Invalid issue ID format' }); } try { const issue = await prisma.mantisIssue.findUnique({ where: { id: issueId }, include: { comments: { // Include comments include: { attachments: true } // And include attachments for each comment } } }); if (!issue) { //Try to download the issue from Mantis const data = await saveTicketToDatabase(issueId); if (!data) { return res.status(404).json({ error: 'Mantis issue not found' }); } // Fetch the issue again from the database const issue = await prisma.mantisIssue.findUnique({ where: { id: issueId }, include: { comments: { // Include comments include: { attachments: true } // And include attachments for each comment } } }); } res.json(issue); } catch (error) { console.error(`Error fetching Mantis issue ${issueId}:`, error.message); res.status(500).json({ error: 'Failed to fetch Mantis issue' }); } }); router.get('/attachment/:ticketId/:attachmentId', async(req, res) => { const { url, headers } = await getMantisSettings(); const { ticketId, attachmentId } = req.params; const attachmentUrl = `${url}/issues/${ticketId}/files/${attachmentId}`; console.log('Fetching Mantis attachment from URL:', attachmentUrl); try { const response = await axios.get(attachmentUrl, { headers }); const attachment = response.data.files[0]; if (!attachment) { return res.status(404).json({ error: 'Attachment not found' }); } const buffer = Buffer.from(attachment.content, 'base64'); res.setHeader('Content-Type', attachment.content_type); res.setHeader('Content-Disposition', `attachment; filename="${attachment.filename}"`); res.setHeader('Content-Length', buffer.length); res.send(buffer); } catch (error) { console.error('Error fetching Mantis attachment:', error.message); res.status(500).json({ error: 'Failed to fetch Mantis attachment' }); } }); router.get('/msg-extract/:ticketId/:attachmentId', async(req, res) => { const { url, headers } = await getMantisSettings(); const { ticketId, attachmentId } = req.params; const attachmentUrl = `${url}/issues/${ticketId}/files/${attachmentId}`; console.log('Fetching Mantis attachment from URL:', attachmentUrl); try { const response = await axios.get(attachmentUrl, { headers }); const attachment = response.data.files[0]; if (!attachment) { return res.status(404).json({ error: 'Attachment not found' }); } const buffer = Buffer.from(attachment.content, 'base64'); console.log(MsgReader); const reader = new MsgReader(buffer); const msg = reader.getFileData(); res.status(200).json(msg); } catch (error) { console.error('Error fetching Mantis attachment:', error.message); res.status(500).json({ error: 'Failed to fetch Mantis attachment' }); } }); router.get('/msg-extract/:ticketId/:attachmentId/:innerAttachmentId', async(req, res) => { const { url, headers } = await getMantisSettings(); const { ticketId, attachmentId, innerAttachmentId } = req.params; const attachmentUrl = `${url}/issues/${ticketId}/files/${attachmentId}`; console.log('Fetching Mantis attachment from URL:', attachmentUrl); try { const response = await axios.get(attachmentUrl, { headers }); const attachment = response.data.files[0]; if (!attachment) { return res.status(404).json({ error: 'Attachment not found' }); } const buffer = Buffer.from(attachment.content, 'base64'); const reader = new MsgReader(buffer); const msg = reader.getFileData(); // Find the inner attachment const innerAttachment = msg.attachments[innerAttachmentId]; if (!innerAttachment) { return res.status(404).json({ error: 'Inner attachment not found' }); } const attachmentData = reader.getAttachment(innerAttachment); const innerBuffer = Buffer.from(attachmentData.content, 'base64'); res.setHeader('Content-Disposition', `attachment; filename="${innerAttachment.fileName}"`); res.status(200).send(innerBuffer); } catch (error) { console.error('Error fetching Mantis attachment:', error.message); res.status(500).json({ error: 'Failed to fetch Mantis attachment' }); } }); export default router;