159 lines
5.3 KiB
TypeScript
159 lines
5.3 KiB
TypeScript
import { NextResponse } from "next/server"
|
|
import { auth } from "@/auth"
|
|
import { prisma } from "@/lib/prisma"
|
|
import { logger } from "@/lib/logger"
|
|
import { getGmailAccessToken } from "@/lib/gmail"
|
|
|
|
/**
|
|
* POST /api/integrations/gmail/watch
|
|
* Set up Gmail push notifications (watch) for a user's mailbox
|
|
*
|
|
* This creates a watch request that tells Gmail to send push notifications
|
|
* to the webhook endpoint when new emails arrive.
|
|
*
|
|
* Note: Gmail watch requests expire after 7 days and need to be renewed.
|
|
*/
|
|
export async function POST(req: Request) {
|
|
try {
|
|
const session = await auth()
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ message: "Unauthorized" }, { status: 401 })
|
|
}
|
|
|
|
// Get Gmail access token
|
|
const accessToken = await getGmailAccessToken(session.user.id)
|
|
if (!accessToken) {
|
|
return NextResponse.json(
|
|
{ message: "Gmail not connected. Please connect your Gmail account first." },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Get webhook URL
|
|
const baseUrl =
|
|
process.env.AUTH_URL ||
|
|
process.env.NEXTAUTH_URL ||
|
|
process.env.NEXT_PUBLIC_APP_URL ||
|
|
"http://localhost:3000"
|
|
const webhookUrl = `${baseUrl}/api/webhooks/gmail`
|
|
|
|
// Get user's email from integration
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
const integration = await (prisma as any).gmailIntegration.findUnique({
|
|
where: { userId: session.user.id },
|
|
select: { email: true }
|
|
})
|
|
|
|
if (!integration?.email) {
|
|
return NextResponse.json(
|
|
{ message: "Gmail email not found" },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Create watch request
|
|
// Gmail will send push notifications to the webhook URL
|
|
const watchResponse = await fetch(
|
|
"https://gmail.googleapis.com/gmail/v1/users/me/watch",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Bearer ${accessToken}`,
|
|
"Content-Type": "application/json"
|
|
},
|
|
body: JSON.stringify({
|
|
topicName: process.env.GMAIL_PUBSUB_TOPIC || "projects/your-project/topics/gmail-notifications",
|
|
labelIds: ["INBOX"], // Watch for emails in inbox
|
|
})
|
|
}
|
|
)
|
|
|
|
if (!watchResponse.ok) {
|
|
const errorData = await watchResponse.json().catch(() => ({}))
|
|
logger.error("Failed to set up Gmail watch", { error: errorData })
|
|
|
|
// If topic doesn't exist, provide helpful error message
|
|
if (watchResponse.status === 400) {
|
|
return NextResponse.json(
|
|
{
|
|
message: "Gmail Pub/Sub topic not configured. Please set up Google Cloud Pub/Sub first.",
|
|
error: errorData
|
|
},
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
return NextResponse.json(
|
|
{ message: "Failed to set up Gmail watch", error: errorData },
|
|
{ status: watchResponse.status }
|
|
)
|
|
}
|
|
|
|
const watchData = await watchResponse.json()
|
|
const expiration = watchData.expiration ? new Date(parseInt(watchData.expiration)).toISOString() : null
|
|
|
|
logger.info("Gmail watch set up successfully", {
|
|
userId: session.user.id,
|
|
email: integration.email,
|
|
expiration
|
|
})
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
message: "Gmail push notifications enabled",
|
|
expiration,
|
|
webhookUrl
|
|
})
|
|
} catch (error) {
|
|
logger.error("Error setting up Gmail watch", error)
|
|
return NextResponse.json(
|
|
{ message: "Failed to set up Gmail watch" },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* GET /api/integrations/gmail/watch
|
|
* Check watch status
|
|
*/
|
|
export async function GET() {
|
|
try {
|
|
const session = await auth()
|
|
if (!session?.user?.id) {
|
|
return NextResponse.json({ message: "Unauthorized" }, { status: 401 })
|
|
}
|
|
|
|
const accessToken = await getGmailAccessToken(session.user.id)
|
|
if (!accessToken) {
|
|
return NextResponse.json(
|
|
{ message: "Gmail not connected" },
|
|
{ status: 400 }
|
|
)
|
|
}
|
|
|
|
// Stop any existing watch (optional - just to check status)
|
|
const stopResponse = await fetch(
|
|
"https://gmail.googleapis.com/gmail/v1/users/me/stop",
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
Authorization: `Bearer ${accessToken}`,
|
|
"Content-Type": "application/json"
|
|
}
|
|
}
|
|
)
|
|
|
|
return NextResponse.json({
|
|
watchActive: !stopResponse.ok, // If stop fails, watch might be active
|
|
message: stopResponse.ok ? "Watch stopped" : "Watch may be active"
|
|
})
|
|
} catch (error) {
|
|
logger.error("Error checking Gmail watch status", error)
|
|
return NextResponse.json(
|
|
{ message: "Failed to check watch status" },
|
|
{ status: 500 }
|
|
)
|
|
}
|
|
}
|