119 lines
4.0 KiB
TypeScript
119 lines
4.0 KiB
TypeScript
import { z } from 'zod';
|
|
|
|
const newsletterSchema = z.object({
|
|
email: z.string().email(),
|
|
agreedToTerms: z.boolean()
|
|
});
|
|
|
|
// Mailchimp integration
|
|
async function subscribeToMailchimp(email: string, env: any) {
|
|
const API_KEY = env.MAILCHIMP_API_KEY;
|
|
const SERVER_PREFIX = env.MAILCHIMP_SERVER_PREFIX;
|
|
const LIST_ID = env.MAILCHIMP_LIST_ID;
|
|
|
|
if (!API_KEY || !SERVER_PREFIX || !LIST_ID) {
|
|
throw new Error('Mailchimp configuration missing. Please check your environment variables.');
|
|
}
|
|
|
|
try {
|
|
// Create MD5 hash of lowercase email for Mailchimp
|
|
const emailHash = crypto.createHash('md5').update(email.toLowerCase()).digest('hex');
|
|
|
|
// Set up the request
|
|
const url = `https://${SERVER_PREFIX}.api.mailchimp.com/3.0/lists/${LIST_ID}/members`;
|
|
const data = {
|
|
email_address: email,
|
|
status: 'subscribed'
|
|
};
|
|
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Authorization': `Basic ${btoa(`apikey:${API_KEY}`)}`
|
|
},
|
|
body: JSON.stringify(data)
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const errorData = await response.json();
|
|
if (response.status === 400 && errorData.title === 'Member Exists') {
|
|
return { status: 'already_subscribed', message: 'This email is already subscribed to our newsletter.' };
|
|
}
|
|
throw new Error(`Mailchimp API error: ${errorData.detail || 'Unknown error'}`);
|
|
}
|
|
|
|
return await response.json();
|
|
} catch (error: any) {
|
|
throw new Error(`Failed to subscribe to newsletter: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
export const onRequest: PagesFunction = async (context) => {
|
|
const { request, env } = context;
|
|
|
|
if (request.method === 'POST') {
|
|
try {
|
|
const body = await request.json();
|
|
const newsletterData = newsletterSchema.parse(body);
|
|
|
|
// Check if email already exists in KV storage
|
|
const existingNewsletter = await env.STORAGE.get(`newsletter:${newsletterData.email}`);
|
|
|
|
// Store in KV storage
|
|
if (!existingNewsletter) {
|
|
const newsletterRecord = {
|
|
email: newsletterData.email,
|
|
agreedToTerms: newsletterData.agreedToTerms,
|
|
createdAt: new Date().toISOString()
|
|
};
|
|
await env.STORAGE.put(`newsletter:${newsletterData.email}`, JSON.stringify(newsletterRecord));
|
|
}
|
|
|
|
// Subscribe to Mailchimp
|
|
try {
|
|
const mailchimpResponse = await subscribeToMailchimp(newsletterData.email, env);
|
|
|
|
if (mailchimpResponse && mailchimpResponse.status === 'already_subscribed') {
|
|
return new Response(JSON.stringify({ message: mailchimpResponse.message }), {
|
|
status: 200,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
}
|
|
|
|
return new Response(JSON.stringify({ message: "Successfully subscribed to the newsletter" }), {
|
|
status: 201,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
} catch (mailchimpError: any) {
|
|
console.error('Mailchimp error:', mailchimpError.message);
|
|
// Still return success if we stored in KV but Mailchimp failed
|
|
return new Response(JSON.stringify({ message: "Successfully subscribed to the newsletter" }), {
|
|
status: 201,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
}
|
|
} catch (error) {
|
|
if (error instanceof z.ZodError) {
|
|
return new Response(JSON.stringify({
|
|
message: "Invalid newsletter data",
|
|
errors: error.errors
|
|
}), {
|
|
status: 400,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
}
|
|
console.error('Newsletter subscription error:', error);
|
|
return new Response(JSON.stringify({ message: "Failed to subscribe to newsletter" }), {
|
|
status: 500,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
}
|
|
}
|
|
|
|
return new Response(JSON.stringify({ message: "Method not allowed" }), {
|
|
status: 405,
|
|
headers: { 'Content-Type': 'application/json' }
|
|
});
|
|
};
|