mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Added link previews
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import WAConnection from '../WAConnection/WAConnection'
|
||||
import { MessageStatus, MessageStatusUpdate, PresenceUpdate, Presence, ChatModification, WABroadcastListInfo, WAUrlInfo } from './Constants'
|
||||
import { MessageStatusUpdate, PresenceUpdate, Presence, WABroadcastListInfo } from './Constants'
|
||||
import {
|
||||
WAMessage,
|
||||
WANode,
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
WAFlag,
|
||||
MessageLogLevel,
|
||||
} from '../WAConnection/Constants'
|
||||
import { proto } from '../../WAMessage/WAMessage'
|
||||
|
||||
export default class WhatsAppWebBase extends WAConnection {
|
||||
/** Set the callback for message status updates (when a message is delivered, read etc.) */
|
||||
@@ -186,13 +185,4 @@ export default class WhatsAppWebBase extends WAConnection {
|
||||
const json = ['action', {epoch: this.msgCount.toString(), type: 'set'}, nodes]
|
||||
return this.queryExpecting200(json, [WAMetric.group, WAFlag.ignore]) as Promise<{status: number}>
|
||||
}
|
||||
/** Query a string to check if it has a url, if it does, return required info */
|
||||
async urlQuery (text: string) {
|
||||
const query = ['query', {type: 'url', url: text, epoch: this.msgCount.toString()}, null]
|
||||
const response = await this.queryExpecting200 (query, [26, WAFlag.ignore])
|
||||
if (response[1]) {
|
||||
response[1].jpegThumbnail = response[2]
|
||||
}
|
||||
return response[1] as WAUrlInfo
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,3 +136,4 @@ export interface WALocationMessage {
|
||||
}
|
||||
export type WAContactMessage = proto.ContactMessage
|
||||
export type WAMessageKey = proto.IMessageKey
|
||||
export type WATextMessage = proto.ExtendedTextMessage
|
||||
|
||||
@@ -12,9 +12,11 @@ import {
|
||||
WAMessageKey,
|
||||
ChatModification,
|
||||
MessageInfo,
|
||||
WATextMessage,
|
||||
WAUrlInfo,
|
||||
} from './Constants'
|
||||
import { generateMessageID, sha256, hmacSign, aesEncrypWithIV, randomBytes } from '../WAConnection/Utils'
|
||||
import { WAMessageContent, WAMetric, WAFlag, WANode, WAMessage } from '../WAConnection/Constants'
|
||||
import { WAMessageContent, WAMetric, WAFlag, WANode, WAMessage, WAMessageProto } from '../WAConnection/Constants'
|
||||
import { validateJIDForSending, generateThumbnail, getMediaKeys } from './Utils'
|
||||
import { proto } from '../../WAMessage/WAMessage'
|
||||
|
||||
@@ -100,6 +102,23 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
const actual = await this.loadConversation (jid, 1, index)
|
||||
return actual[0]
|
||||
}
|
||||
/** Query a string to check if it has a url, if it does, return required extended text message */
|
||||
async generateLinkPreview (text: string) {
|
||||
const query = ['query', {type: 'url', url: text, epoch: this.msgCount.toString()}, null]
|
||||
const response = await this.queryExpecting200 (query, [26, WAFlag.ignore])
|
||||
|
||||
if (response[1]) response[1].jpegThumbnail = response[2]
|
||||
const data = response[1] as WAUrlInfo
|
||||
|
||||
const content = {text} as WATextMessage
|
||||
content.canonicalUrl = data['canonical-url']
|
||||
content.matchedText = data['matched-text']
|
||||
content.jpegThumbnail = data.jpegThumbnail
|
||||
content.description = data.description
|
||||
content.title = data.title
|
||||
content.previewType = 0
|
||||
return content
|
||||
}
|
||||
/**
|
||||
* Search WhatsApp messages with a given text string
|
||||
* @param txt the search string
|
||||
@@ -170,21 +189,24 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
}
|
||||
async sendMessage(
|
||||
id: string,
|
||||
message: string | WALocationMessage | WAContactMessage | Buffer,
|
||||
message: string | WATextMessage | WALocationMessage | WAContactMessage | Buffer,
|
||||
type: MessageType,
|
||||
options: MessageOptions = {},
|
||||
) {
|
||||
if (options.validateID === true || !('validateID' in options)) {
|
||||
validateJIDForSending (id)
|
||||
}
|
||||
let m: any = {}
|
||||
let m: WAMessageContent = {}
|
||||
switch (type) {
|
||||
case MessageType.text:
|
||||
case MessageType.extendedText:
|
||||
if (typeof message !== 'string') {
|
||||
throw new Error('expected message to be a string')
|
||||
if (typeof message === 'string') {
|
||||
m.extendedTextMessage = {text: message}
|
||||
} else if ('text' in message) {
|
||||
m.extendedTextMessage = message as WATextMessage
|
||||
} else {
|
||||
throw new Error ('message needs to be a string or object with property \'text\'')
|
||||
}
|
||||
m.extendedTextMessage = { text: message }
|
||||
break
|
||||
case MessageType.location:
|
||||
case MessageType.liveLocation:
|
||||
@@ -197,7 +219,7 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
m = await this.prepareMediaMessage(message as Buffer, type, options)
|
||||
break
|
||||
}
|
||||
return this.sendGenericMessage(id, m as WAMessageContent, options)
|
||||
return this.sendGenericMessage(id, m, options)
|
||||
}
|
||||
/** Prepare a media message for sending */
|
||||
protected async prepareMediaMessage(buffer: Buffer, mediaType: MessageType, options: MessageOptions = {}) {
|
||||
@@ -283,7 +305,7 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
}
|
||||
}
|
||||
message[key].caption = options?.caption
|
||||
message[key].jpegThumbnail = options?.thumbnail
|
||||
if (!message[key].jpegThumbnail) message[key].jpegThumbnail = options?.thumbnail
|
||||
|
||||
const messageJSON = {
|
||||
key: {
|
||||
@@ -293,7 +315,8 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
},
|
||||
message: message,
|
||||
messageTimestamp: timestamp,
|
||||
participant: id.includes('@g.us') ? this.userMetaData.id : null
|
||||
participant: id.includes('@g.us') ? this.userMetaData.id : null,
|
||||
status: WAMessageProto.proto.WebMessageInfo.WEB_MESSAGE_INFO_STATUS.PENDING
|
||||
}
|
||||
const json = ['action', {epoch: this.msgCount.toString(), type: 'relay'}, [['message', null, messageJSON]]]
|
||||
const response = await this.queryExpecting200(json, [WAMetric.message, WAFlag.ignore], null, messageJSON.key.id)
|
||||
|
||||
@@ -33,6 +33,14 @@ WAClientTest('Messages', (client) => {
|
||||
const message = await sendAndRetreiveMessage(client, 'hello fren', MessageType.text)
|
||||
assert.strictEqual(message.message.conversation, 'hello fren')
|
||||
})
|
||||
it('should send a link preview', async () => {
|
||||
const content = await client.generateLinkPreview ('hello this is from https://www.github.com/adiwajshing/Baileys')
|
||||
const message = await sendAndRetreiveMessage(client, content, MessageType.text)
|
||||
const received = message.message.extendedTextMessage
|
||||
assert.strictEqual(received.text, content.text)
|
||||
|
||||
fs.writeFileSync ('Media/received-thumb.jpeg', content.jpegThumbnail)
|
||||
})
|
||||
it('should quote a message', async () => {
|
||||
const messages = await client.loadConversation(testJid, 2)
|
||||
const message = await sendAndRetreiveMessage(client, 'hello fren 2', MessageType.extendedText, {
|
||||
@@ -109,12 +117,6 @@ WAClientTest('Misc', (client) => {
|
||||
it('should return the stories', async () => {
|
||||
await client.getStories()
|
||||
})
|
||||
it('should return a preview', async () => {
|
||||
const info = await client.urlQuery ('fren have you seen https://www.github.com/adiwajshing/Baileys')
|
||||
assert.equal (info["matched-text"], 'https://www.github.com/adiwajshing/Baileys')
|
||||
|
||||
await assert.rejects (() => client.urlQuery('oh hello there'))
|
||||
})
|
||||
it('should return the profile picture', async () => {
|
||||
const response = await client.getProfilePicture(testJid)
|
||||
assert.ok(response)
|
||||
|
||||
@@ -60,8 +60,9 @@ const extractVideoThumb = async (
|
||||
})
|
||||
}) as Promise<void>
|
||||
|
||||
/** generates a thumbnail for a given media, if required */
|
||||
export const compressImage = async (buffer: Buffer) => sharp(buffer).resize(48, 48).jpeg().toBuffer()
|
||||
|
||||
/** generates a thumbnail for a given media, if required */
|
||||
export async function generateThumbnail(buffer: Buffer, mediaType: MessageType, info: MessageOptions) {
|
||||
if (info.thumbnail === null || info.thumbnail) {
|
||||
// don't do anything if the thumbnail is already provided, or is null
|
||||
@@ -69,7 +70,7 @@ export async function generateThumbnail(buffer: Buffer, mediaType: MessageType,
|
||||
throw new Error('audio messages cannot have thumbnails')
|
||||
}
|
||||
} else if (mediaType === MessageType.image || mediaType === MessageType.sticker) {
|
||||
const buff = await sharp(buffer).resize(48, 48).jpeg().toBuffer()
|
||||
const buff = await compressImage (buffer)
|
||||
info.thumbnail = buff.toString('base64')
|
||||
} else if (mediaType === MessageType.video) {
|
||||
const filename = './' + randomBytes(5).toString('hex') + '.mp4'
|
||||
|
||||
Reference in New Issue
Block a user