save work

This commit is contained in:
Ken Yasue
2025-04-01 17:15:51 +02:00
parent 885800a10d
commit 2ee0063eb5
4 changed files with 353 additions and 71 deletions

View File

@ -3,20 +3,132 @@ import { getDataSource } from '../lib/database';
import { Customer } from '../lib/database/entities/Customer';
import { ContactRecord } from '../lib/database/entities/ContactRecord';
import { sendEmail } from '../lib/email';
import axios from 'axios';
// Get command line arguments
const args = process.argv.slice(2);
const emailCountArg = args.find(arg => arg.startsWith('--count='));
const lmStudioUrlArg = args.find(arg => arg.startsWith('--lmstudio-url='));
const modelArg = args.find(arg => arg.startsWith('--model='));
const temperatureArg = args.find(arg => arg.startsWith('--temperature='));
const dryRunArg = args.find(arg => arg.startsWith('--dry-run='));
// Parse arguments with defaults
const defaultEmailCount = 0;
const emailCount = emailCountArg
? parseInt(emailCountArg.split('=')[1], 10)
: defaultEmailCount;
// LMStudio API settings
const lmStudioUrl = lmStudioUrlArg
? lmStudioUrlArg.split('=')[1]
: 'http://localhost:3000/v1/chat/completions'; // Default LMStudio API endpoint
const model = modelArg
? modelArg.split('=')[1]
: 'local-model'; // Default model name
const temperature = temperatureArg
? parseFloat(temperatureArg.split('=')[1])
: 0.7; // Default temperature
// Dry run mode - generate content but don't send emails or create records
const dryRun = dryRunArg
? dryRunArg.split('=')[1].toLowerCase() === 'true'
: false;
if (isNaN(emailCount) || emailCount < 0) {
console.error('Error: Email count must be a non-negative number');
process.exit(1);
}
// Function to generate email content using LMStudio API
async function generateEmailContent(
customer: Customer,
emailCount: number
): Promise<{ subject: string; body: string }> {
try {
console.log(`Generating email content for ${customer.name} using LMStudio API...`);
// Create a prompt based on customer info and email count
let prompt = '';
if (emailCount === 0) {
prompt = `Generate a welcome email for a new customer named ${customer.name} from ${customer.url}.
This is the first contact with them. The email should be professional but friendly.
Return ONLY a JSON object with 'subject' and 'body' fields. The body should be in HTML format.`;
}/* else if (emailCount === 1) {
prompt = `Generate a follow-up email for customer ${customer.name} from ${customer.url}.
This is the second contact with them. The email should reference a previous welcome email and provide more value.
Return ONLY a JSON object with 'subject' and 'body' fields. The body should be in HTML format.`;
} else {
prompt = `Generate a relationship-building email for a regular customer named ${customer.name} from ${customer.url}.
This is contact number ${emailCount + 1} with them. The email should be personalized and provide specific value.
Return ONLY a JSON object with 'subject' and 'body' fields. The body should be in HTML format.`;
} */
// Call LMStudio API
const response = await axios.post(
lmStudioUrl,
{
model: model,
messages: [
{ role: 'system', content: 'You are an expert email copywriter who creates engaging, professional emails.' },
{ role: 'user', content: prompt }
],
temperature: temperature,
max_tokens: 1000
},
{
headers: {
'Content-Type': 'application/json'
}
}
);
// Parse the response to extract the JSON
const assistantMessage = response.data.choices[0].message.content;
// Try to extract JSON from the response
try {
// Look for JSON object in the response
const jsonMatch = assistantMessage.match(/\{[\s\S]*\}/);
if (jsonMatch) {
const jsonStr = jsonMatch[0];
const emailContent = JSON.parse(jsonStr);
if (emailContent.subject && emailContent.body) {
return {
subject: emailContent.subject,
body: emailContent.body
};
}
}
// If we couldn't parse JSON or it doesn't have required fields
throw new Error('Could not parse valid JSON from LMStudio response');
} catch (parseError) {
console.warn('Failed to parse JSON from LMStudio response, using fallback content');
console.warn('LMStudio response:', assistantMessage);
// Fallback content
return {
subject: `Update from Our Company - Contact #${emailCount + 1}`,
body: `<h1>Hello ${customer.name}!</h1><p>Thank you for your continued interest in our services. We appreciate your business.</p>`
};
}
} catch (error) {
const errorMessage = error instanceof Error
? error.message
: 'Unknown error occurred';
console.error('Error calling LMStudio API:', errorMessage);
// Fallback content in case of API error
return {
subject: `Important Update - Contact #${emailCount + 1}`,
body: `<h1>Hello ${customer.name}!</h1><p>Thank you for your interest in our services. We look forward to working with you!</p>`
};
}
}
async function main() {
try {
console.log('Initializing database connection...');
@ -71,39 +183,42 @@ async function main() {
console.log('\nSending emails to customers...');
// Send emails to each customer
let emailSubject = 'Welcome to Our Service';
let emailBody = 'Thank you for your interest in our services. We look forward to working with you!';
// Customize email based on email count
if (emailCount === 0) {
emailSubject = 'Welcome to Our Service';
emailBody = 'Thank you for your interest in our services. We look forward to working with you!';
} else if (emailCount === 1) {
emailSubject = 'Follow-up on Our Services';
emailBody = 'We hope you found our previous information helpful. Here are some additional details about our services.';
} else {
emailSubject = `Important Update - Contact #${emailCount + 1}`;
emailBody = 'We wanted to share some important updates about our services that might interest you.';
}
for (const customer of filteredCustomers) {
console.log(`Sending email to ${customer.name} (${customer.email})...`);
console.log(`Processing email for ${customer.name} (${customer.email})...`);
try {
const result = await sendEmail(
customer.id,
emailSubject,
emailBody,
`<h1>Hello ${customer.name}!</h1><p>${emailBody}</p>`
);
// Generate email content using LMStudio
const emailContent = await generateEmailContent(customer, emailCount);
if (result.success) {
console.log(`✅ Email sent successfully to ${customer.email}`);
console.log(`Generated subject: ${emailContent.subject}`);
if (dryRun) {
console.log(`[DRY RUN] Would send email to ${customer.name} (${customer.email})`);
console.log(`[DRY RUN] Subject: ${emailContent.subject}`);
console.log(`[DRY RUN] Body: ${emailContent.body.replace(/<[^>]*>/g, '')}`);
console.log(`[DRY RUN] No email sent and no contact record created.`);
} else {
console.error(`❌ Failed to send email to ${customer.email}: ${result.error}`);
console.log(`Sending email to ${customer.name}...`);
const result = await sendEmail(
customer.id,
emailContent.subject,
emailContent.body.replace(/<[^>]*>/g, ''), // Plain text version (strip HTML)
emailContent.body // HTML version
);
if (result.success) {
console.log(`✅ Email sent successfully to ${customer.email}`);
} else {
console.error(`❌ Failed to send email to ${customer.email}: ${result.error}`);
}
}
} catch (error) {
console.error(`❌ Error sending email to ${customer.email}:`, error);
const errorMessage = error instanceof Error
? error.message
: 'Unknown error occurred';
console.error(`❌ Error sending email to ${customer.email}:`, errorMessage);
}
// Add a small delay between emails to avoid rate limiting
@ -114,13 +229,21 @@ async function main() {
await dataSource.destroy();
} catch (error) {
console.error('An error occurred:', error);
const errorMessage = error instanceof Error
? error.message
: 'Unknown error occurred';
console.error('An error occurred:', errorMessage);
process.exit(1);
}
}
// Run the main function
main().catch(error => {
console.error('Unhandled error:', error);
const errorMessage = error instanceof Error
? error.message
: 'Unknown error occurred';
console.error('Unhandled error:', errorMessage);
process.exit(1);
});