mirror of
https://github.com/beilunyang/moemail.git
synced 2026-07-09 14:41:23 +08:00
feat: profile page & webhook notification
This commit is contained in:
@@ -66,4 +66,19 @@ export const messages = sqliteTable("message", {
|
||||
receivedAt: integer("received_at", { mode: "timestamp_ms" })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
})
|
||||
|
||||
export const webhooks = sqliteTable('webhook', {
|
||||
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
|
||||
userId: text('user_id')
|
||||
.notNull()
|
||||
.references(() => users.id, { onDelete: "cascade" }),
|
||||
url: text('url').notNull(),
|
||||
enabled: integer('enabled', { mode: 'boolean' }).notNull().default(true),
|
||||
createdAt: integer('created_at', { mode: 'timestamp_ms' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
updatedAt: integer('updated_at', { mode: 'timestamp_ms' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
})
|
||||
54
app/lib/webhook.ts
Normal file
54
app/lib/webhook.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { WEBHOOK_CONFIG } from "@/config"
|
||||
|
||||
export interface EmailMessage {
|
||||
emailId: string
|
||||
messageId: string
|
||||
fromAddress: string
|
||||
subject: string
|
||||
content: string
|
||||
html: string
|
||||
receivedAt: string
|
||||
toAddress: string
|
||||
}
|
||||
|
||||
export interface WebhookPayload {
|
||||
event: typeof WEBHOOK_CONFIG.EVENTS[keyof typeof WEBHOOK_CONFIG.EVENTS]
|
||||
data: EmailMessage
|
||||
}
|
||||
|
||||
export async function callWebhook(url: string, payload: WebhookPayload) {
|
||||
let lastError: Error | null = null
|
||||
|
||||
for (let i = 0; i < WEBHOOK_CONFIG.MAX_RETRIES; i++) {
|
||||
try {
|
||||
const controller = new AbortController()
|
||||
const timeoutId = setTimeout(() => controller.abort(), WEBHOOK_CONFIG.TIMEOUT)
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Webhook-Event": payload.event,
|
||||
},
|
||||
body: JSON.stringify(payload.data),
|
||||
signal: controller.signal,
|
||||
})
|
||||
|
||||
clearTimeout(timeoutId)
|
||||
|
||||
if (response.ok) {
|
||||
return true
|
||||
}
|
||||
|
||||
lastError = new Error(`HTTP error! status: ${response.status}`)
|
||||
} catch (error) {
|
||||
lastError = error as Error
|
||||
|
||||
if (i < WEBHOOK_CONFIG.MAX_RETRIES - 1) {
|
||||
await new Promise(resolve => setTimeout(resolve, WEBHOOK_CONFIG.RETRY_DELAY))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError
|
||||
}
|
||||
Reference in New Issue
Block a user