Add mantis summaries and start of email summaries... Need to figure out a way to get the emails since MS block IMAP :(
This commit is contained in:
		
							parent
							
								
									2d11d0bd79
								
							
						
					
					
						commit
						2ad9a63582
					
				
					 18 changed files with 1993 additions and 577 deletions
				
			
		
							
								
								
									
										171
									
								
								src-ssr/services/mantisSummarizer.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								src-ssr/services/mantisSummarizer.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,171 @@
 | 
			
		|||
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.');
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue