Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions integrations/gmail/definitions/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ export const configurations = {
.string()
.min(1)
.title('Pub/Sub Webhook Shared Secret')
.describe('Must be set in GCC under Pub/Sub > Subscriptions'),
.describe(
'Must be set in GCC under Pub/Sub > Subscriptions > Details > Push endpoint (in the URL is the shared secret)'
),
pubsubWebhookServiceAccount: z
.string()
.min(1)
.title('Pub/Sub Webhook Service Account')
.describe('Must be set in GCC under Pub/Sub > Subscriptions'),
.describe('Must be set in GCC under Pub/Sub > Subscriptions > Details > Service account'),
}),
},
} as const satisfies sdk.IntegrationDefinitionProps['configurations']
Expand Down
2 changes: 1 addition & 1 deletion integrations/gmail/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

export default new sdk.IntegrationDefinition({
name: 'gmail',
version: '0.6.2',
version: '0.6.3',
title: 'Gmail',
description: "Send, receive, and manage emails directly within your bot's workflow.",
icon: 'icon.svg',
Expand Down
11 changes: 5 additions & 6 deletions integrations/gmail/src/channels/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,21 @@ export const channels = {

const _sendEmailReply = async ({
conversation,
logger,
ack,
textContent,
htmlContent,
inReplyTo,
googleClient,
}: bp.AnyMessageProps & {
logger: bp.Logger
textContent: string
htmlContent?: string
inReplyTo: string
googleClient: GoogleClient
}) => {
const { threadId, email, subject, references, cc } = _getConversationInfo(conversation)
const { threadId, email, subject, references, cc } = _getConversationInfo(conversation, logger)

console.info('Creating mail')
const raw = await composeRawEmail({
to: email,
subject,
Expand All @@ -168,20 +169,18 @@ const _sendEmailReply = async ({
references: references ?? inReplyTo,
cc,
})
console.info('Sending mail', raw)

const res = await googleClient.sendRawEmail(raw, threadId)
console.info('Response', res)

await ack({ tags: { id: `${res.id}` } })
}

const _getConversationInfo = (conversation: bp.AnyMessageProps['conversation']) => {
const _getConversationInfo = (conversation: bp.AnyMessageProps['conversation'], logger: bp.Logger) => {
const { id, tags } = conversation
const { id: threadId, subject, email, references, cc } = tags

if (!(threadId && subject && email)) {
console.info(`No valid information found for conversation ${id}`)
logger.forBot().error(`No valid information found for conversation ${id}`)
throw new Error(`No valid information found for conversation ${id}`)
}

Expand Down
2 changes: 0 additions & 2 deletions integrations/gmail/src/webhook-events/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import { handleOAuthCallback } from './oauth-callback'
import * as bp from '.botpress'

export const handler = async (props: bp.HandlerProps) => {
console.info('handler received a request')

if (props.req.path.startsWith('/oauth')) {
return handleOAuthCallback(props)
}
Expand Down
20 changes: 1 addition & 19 deletions integrations/gmail/src/webhook-events/new-mail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,23 @@ export const handleIncomingEmail = async (props: bp.HandlerProps) => {
const bodyContent = JSON.parse(req.body || '{}')

const data = bodyContent.message?.data
console.info('data', data)

if (!data) {
console.warn('Handler received an invalid body (no data)')
return
}

const messageData = JSON.parse(decodeBase64URL(data))
console.info('messageData', messageData)

const { historyId: historyIdNumber, emailAddress } = messageData
const historyId = `${historyIdNumber}`
console.info('historyId', historyId)

if (!historyId) {
console.warn('Handler received an invalid body (no historyId)')
return
}

// Only proceed if the incoming historyId is greater that the latest processed historyId
console.info('creating gmail client')
const googleClient = await GoogleClient.create({ client, ctx })

const {
Expand All @@ -57,8 +53,6 @@ export const handleIncomingEmail = async (props: bp.HandlerProps) => {

const history = await googleClient.getMyHistory(lastHistoryId)

console.info(JSON.stringify(history, null, 2))

const messageIds = history.history?.reduce((acc, h) => {
h.messagesAdded?.forEach((m) => {
if (m.message?.id) {
Expand Down Expand Up @@ -95,12 +89,8 @@ const _processMessage = async (
googleClient: GoogleClient,
emailAddress: string
) => {
console.info('getting history')
const gmailMessage = await googleClient.getMessageById(messageId)

const message = parseMessage(gmailMessage)
console.info('message', message)

const threadId = message.threadId

if (!threadId) {
Expand All @@ -112,23 +102,19 @@ const _processMessage = async (
const inReplyTo = message.headers['message-id']
const from = message.headers['from']
const { name: senderName, email: userEmail } = _extractNameAndEmailFromSender(replyTo ?? from)
console.info('userEmail', userEmail)

if (userEmail === emailAddress) {
return
}

console.info('threadId', threadId)
const { conversation } = await client.getOrCreateConversation({
channel: 'channel',
tags: {
id: `${threadId}`,
},
})

console.info('conversation', conversation)

const { conversation: updatedConversation } = await client.updateConversation({
await client.updateConversation({
id: conversation.id,
tags: {
subject: message.headers['subject'],
Expand All @@ -138,13 +124,10 @@ const _processMessage = async (
},
})

console.info('updatedConversation', updatedConversation)

if (!userEmail) {
throw new Error('Handler received an empty from id')
}

console.info('userEmail', userEmail)
const { user } = await client.getOrCreateUser({
tags: {
id: `${userEmail}`,
Expand All @@ -171,7 +154,6 @@ const _processMessage = async (
}
}

console.info('getOrCreateMessage', { threadId, userEmail, content, inReplyTo })
await client.getOrCreateMessage({
tags: { id: messageId },
type: 'text',
Expand Down
4 changes: 0 additions & 4 deletions integrations/gmail/src/webhook-events/oauth-callback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,19 @@ export const handleOAuthCallback = async ({ req, client, ctx }: bp.HandlerProps)
return
}

console.info('code', authorizationCode)

const googleClient = await GoogleClient.createFromAuthorizationCode({
client,
ctx,
authorizationCode,
})

const userEmail = await googleClient.getMyEmail()
console.info('userEmail', userEmail)

if (!userEmail) {
console.error('Error extracting email from profile')
return
}

console.info('configureIntegration')
await client.configureIntegration({
identifier: userEmail,
})
Expand Down
7 changes: 6 additions & 1 deletion integrations/whatsapp/integration.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ const defaultBotPhoneNumberId = {
export const INTEGRATION_NAME = 'whatsapp'
export default new IntegrationDefinition({
name: INTEGRATION_NAME,
version: '4.5.16',
version: '4.5.17',
title: 'WhatsApp',
description: 'Send and receive messages through WhatsApp.',
icon: 'icon.svg',
Expand Down Expand Up @@ -190,6 +190,11 @@ export default new IntegrationDefinition({
filename: z.string().optional(),
}),
},
image: {
schema: messages.defaults.image.schema.extend({
caption: z.string().optional(),
}),
},
bloc: {
schema: z.object({
items: z.array(
Expand Down
3 changes: 2 additions & 1 deletion integrations/whatsapp/src/channels/message-types/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export async function generateOutgoingMessage({
function _generateImage(payload: Image, logger: bp.Logger): WhatsappMessages.Image | undefined {
logger.forBot().debug('Sending WhatsApp Image')
const url = payload.imageUrl.trim()
return new WhatsappMessages.Image(url, false)
const caption = payload.caption
return new WhatsappMessages.Image(url, false, caption)
}

async function _generateSticker(payload: Image, logger: bp.Logger): Promise<WhatsappMessages.Sticker | undefined> {
Expand Down
9 changes: 8 additions & 1 deletion integrations/whatsapp/src/webhook/handlers/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,14 @@ async function _handleIncomingMessage(
})
} else if (type === 'image') {
const imageUrl = await _getOrDownloadWhatsappMedia(message.image.id, client, ctx)
await createMessage({ type, payload: { imageUrl }, replyTo })
await createMessage({
type,
payload: {
imageUrl,
...(message.image.caption && { caption: message.image.caption }),
},
replyTo,
})
} else if (type === 'sticker') {
const stickerUrl = await _getOrDownloadWhatsappMedia(message.sticker.id, client, ctx)
await createMessage({ type: 'image', payload: { imageUrl: stickerUrl }, replyTo })
Expand Down
Loading