171 lines
6.1 KiB
JavaScript
171 lines
6.1 KiB
JavaScript
import axios from 'axios';
|
|
import { GoogleGenAI } from '@google/genai';
|
|
import prisma from '../database.js'; // Import Prisma client
|
|
|
|
// --- Environment Variables ---
|
|
const {
|
|
MANTIS_API_KEY,
|
|
MANTIS_API_ENDPOINT,
|
|
GOOGLE_API_KEY
|
|
} = process.env;
|
|
|
|
// --- Mantis Summarizer Setup ---
|
|
const ai = GOOGLE_API_KEY ? new GoogleGenAI({
|
|
apiKey: GOOGLE_API_KEY,
|
|
}) : null;
|
|
|
|
const usernameMap = {
|
|
'credmore': 'Cameron Redmore',
|
|
'dgibson': 'Dane Gibson',
|
|
'egzibovskis': 'Ed Gzibovskis',
|
|
'ascotney': 'Amanda Scotney',
|
|
'gclough': 'Garry Clough',
|
|
'slee': 'Sarah Lee',
|
|
'dwalker': 'Dave Walker',
|
|
'askaith': 'Amy Skaith',
|
|
'dpotter': 'Danny Potter',
|
|
'msmart': 'Michael Smart',
|
|
// Add other usernames as needed
|
|
};
|
|
|
|
async function getMantisTickets() {
|
|
if (!MANTIS_API_ENDPOINT || !MANTIS_API_KEY) {
|
|
throw new Error("Mantis API endpoint or key not configured in environment variables.");
|
|
}
|
|
const url = `${MANTIS_API_ENDPOINT}/issues?project_id=1&page_size=50&select=id,summary,description,created_at,updated_at,reporter,notes`;
|
|
const headers = {
|
|
'Authorization': `${MANTIS_API_KEY}`,
|
|
'Accept': 'application/json',
|
|
'Content-Type': 'application/json',
|
|
};
|
|
|
|
try {
|
|
const response = await axios.get(url, { headers });
|
|
|
|
const tickets = response.data.issues.filter((ticket) => {
|
|
const ticketDate = new Date(ticket.updated_at);
|
|
const thresholdDate = new Date();
|
|
const currentDay = thresholdDate.getDay(); // Sunday = 0, Monday = 1, ...
|
|
|
|
// Go back 4 days if Monday (to include Fri, Sat, Sun), otherwise 2 days
|
|
const daysToSubtract = currentDay === 1 ? 4 : 2;
|
|
thresholdDate.setDate(thresholdDate.getDate() - daysToSubtract);
|
|
thresholdDate.setHours(0, 0, 0, 0); // Start of the day
|
|
|
|
return ticketDate >= thresholdDate;
|
|
}).map((ticket) => {
|
|
return {
|
|
id: ticket.id,
|
|
summary: ticket.summary,
|
|
description: ticket.description,
|
|
created_at: ticket.created_at,
|
|
updated_at: ticket.updated_at,
|
|
reporter: usernameMap[ticket.reporter?.username] || ticket.reporter?.name || 'Unknown Reporter', // Safer access
|
|
notes: (ticket.notes ? ticket.notes.filter((note) => {
|
|
const noteDate = new Date(note.created_at);
|
|
const thresholdDate = new Date();
|
|
const currentDay = thresholdDate.getDay();
|
|
const daysToSubtract = currentDay === 1 ? 4 : 2;
|
|
thresholdDate.setDate(thresholdDate.getDate() - daysToSubtract);
|
|
thresholdDate.setHours(0, 0, 0, 0); // Start of the day
|
|
return noteDate >= thresholdDate;
|
|
}) : []).map((note) => {
|
|
const reporter = usernameMap[note.reporter?.username] || note.reporter?.name || 'Unknown Reporter'; // Safer access
|
|
return {
|
|
reporter,
|
|
created_at: note.created_at,
|
|
text: note.text,
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
|
|
return tickets;
|
|
} catch (error) {
|
|
console.error("Error fetching Mantis tickets:", error.message);
|
|
// Check if it's an Axios error and provide more details
|
|
if (axios.isAxiosError(error)) {
|
|
console.error("Axios error details:", error.response?.status, error.response?.data);
|
|
throw new Error(`Failed to fetch Mantis tickets: ${error.response?.statusText || error.message}`);
|
|
}
|
|
throw new Error(`Failed to fetch Mantis tickets: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
// --- Mantis Summary Logic (Exported) --- //
|
|
|
|
export async function generateAndStoreMantisSummary() {
|
|
console.log('Attempting to generate and store Mantis summary...');
|
|
if (!ai) {
|
|
console.error('Google AI API key not configured. Skipping summary generation.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
// Get the prompt from the database settings using Prisma
|
|
const setting = await prisma.setting.findUnique({
|
|
where: { key: 'mantisPrompt' },
|
|
select: { value: true }
|
|
});
|
|
const promptTemplate = setting?.value;
|
|
|
|
if (!promptTemplate) {
|
|
console.error('Mantis prompt not found in database settings (key: mantisPrompt). Skipping summary generation.');
|
|
return;
|
|
}
|
|
|
|
const tickets = await getMantisTickets();
|
|
|
|
let summaryText;
|
|
if (tickets.length === 0) {
|
|
summaryText = "No Mantis tickets updated recently.";
|
|
console.log('No recent Mantis tickets found.');
|
|
} else {
|
|
console.log(`Found ${tickets.length} recent Mantis tickets. Generating summary...`);
|
|
let prompt = promptTemplate.replaceAll("$DATE", new Date().toISOString().split('T')[0]);
|
|
prompt = prompt.replaceAll("$MANTIS_TICKETS", JSON.stringify(tickets, null, 2));
|
|
|
|
const response = await ai.models.generateContent({
|
|
"model": "gemini-2.5-flash-preview-04-17",
|
|
"contents": prompt,
|
|
config: {
|
|
temperature: 0
|
|
}
|
|
});
|
|
|
|
summaryText = response.text;
|
|
console.log('Mantis summary generated successfully by AI.');
|
|
}
|
|
|
|
// Store the summary in the database using Prisma upsert
|
|
const today = new Date();
|
|
today.setUTCHours(0, 0, 0, 0); // Use UTC start of day for consistency
|
|
|
|
await prisma.mantisSummary.upsert({
|
|
where: { summaryDate: today },
|
|
update: {
|
|
summaryText: summaryText,
|
|
// generatedAt is updated automatically by @default(now())
|
|
},
|
|
create: {
|
|
summaryDate: today,
|
|
summaryText: summaryText,
|
|
},
|
|
});
|
|
console.log(`Mantis summary for ${today.toISOString().split('T')[0]} stored/updated in the database.`);
|
|
|
|
} catch (error) {
|
|
console.error("Error during Mantis summary generation/storage:", error);
|
|
}
|
|
}
|
|
|
|
export async function generateTodaysSummary() {
|
|
console.log('Triggering Mantis summary generation via generateTodaysSummary...');
|
|
try {
|
|
await generateAndStoreMantisSummary();
|
|
return { success: true, message: 'Summary generation process initiated.' };
|
|
} catch (error) {
|
|
console.error('Error occurred within generateTodaysSummary while calling generateAndStoreMantisSummary:', error);
|
|
throw new Error('Failed to initiate Mantis summary generation.');
|
|
}
|
|
}
|