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.');
 | 
						|
  }
 | 
						|
}
 |