mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
chore: add linting
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { Boom } from '@hapi/boom'
|
||||
import { promises as fs } from "fs"
|
||||
import { promises as fs } from 'fs'
|
||||
import { proto } from '../../WAProto'
|
||||
import { MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from "../Defaults"
|
||||
import { MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults'
|
||||
import {
|
||||
AnyMediaMessageContent,
|
||||
AnyMessageContent,
|
||||
MediaGenerationOptions,
|
||||
MediaType,
|
||||
MessageContentGenerationOptions,
|
||||
MessageGenerationOptions,
|
||||
MessageGenerationOptionsFromContent,
|
||||
@@ -13,13 +14,11 @@ import {
|
||||
WAMediaUpload,
|
||||
WAMessage,
|
||||
WAMessageContent,
|
||||
WAMessageStatus,
|
||||
WAProto,
|
||||
WATextMessage,
|
||||
MediaType,
|
||||
WAMessageStatus
|
||||
} from "../Types"
|
||||
import { generateMessageID, unixTimestampSeconds } from "./generics"
|
||||
import { encryptedStream, generateThumbnail, getAudioDuration } from "./messages-media"
|
||||
WATextMessage } from '../Types'
|
||||
import { generateMessageID, unixTimestampSeconds } from './generics'
|
||||
import { encryptedStream, generateThumbnail, getAudioDuration } from './messages-media'
|
||||
|
||||
type MediaUploadData = {
|
||||
media: WAMediaUpload
|
||||
@@ -33,20 +32,20 @@ type MediaUploadData = {
|
||||
}
|
||||
|
||||
const MIMETYPE_MAP: { [T in MediaType]: string } = {
|
||||
image: 'image/jpeg',
|
||||
video: 'video/mp4',
|
||||
document: 'application/pdf',
|
||||
audio: 'audio/ogg; codecs=opus',
|
||||
sticker: 'image/webp',
|
||||
image: 'image/jpeg',
|
||||
video: 'video/mp4',
|
||||
document: 'application/pdf',
|
||||
audio: 'audio/ogg; codecs=opus',
|
||||
sticker: 'image/webp',
|
||||
history: 'application/x-protobuf',
|
||||
"md-app-state": 'application/x-protobuf',
|
||||
'md-app-state': 'application/x-protobuf',
|
||||
}
|
||||
|
||||
const MessageTypeProto = {
|
||||
'image': WAProto.ImageMessage,
|
||||
'video': WAProto.VideoMessage,
|
||||
'audio': WAProto.AudioMessage,
|
||||
'sticker': WAProto.StickerMessage,
|
||||
'image': WAProto.ImageMessage,
|
||||
'video': WAProto.VideoMessage,
|
||||
'audio': WAProto.AudioMessage,
|
||||
'sticker': WAProto.StickerMessage,
|
||||
'document': WAProto.DocumentMessage,
|
||||
} as const
|
||||
|
||||
@@ -64,6 +63,7 @@ export const prepareWAMessageMedia = async(
|
||||
mediaType = key
|
||||
}
|
||||
}
|
||||
|
||||
const uploadData: MediaUploadData = {
|
||||
...message,
|
||||
media: message[mediaType]
|
||||
@@ -74,13 +74,14 @@ export const prepareWAMessageMedia = async(
|
||||
('url' in uploadData.media) &&
|
||||
!!uploadData.media.url &&
|
||||
!!options.mediaCache && (
|
||||
// generate the key
|
||||
mediaType + ':' + uploadData.media.url!.toString()
|
||||
)
|
||||
// generate the key
|
||||
mediaType + ':' + uploadData.media.url!.toString()
|
||||
)
|
||||
|
||||
if(mediaType === 'document' && !uploadData.fileName) {
|
||||
uploadData.fileName = 'file'
|
||||
}
|
||||
|
||||
if(!uploadData.mimetype) {
|
||||
uploadData.mimetype = MIMETYPE_MAP[mediaType]
|
||||
}
|
||||
@@ -89,7 +90,7 @@ export const prepareWAMessageMedia = async(
|
||||
if(cacheableKey) {
|
||||
const mediaBuff: Buffer = options.mediaCache!.get(cacheableKey)
|
||||
if(mediaBuff) {
|
||||
logger?.debug({ cacheableKey }, `got media cache hit`)
|
||||
logger?.debug({ cacheableKey }, 'got media cache hit')
|
||||
|
||||
const obj = WAProto.Message.decode(mediaBuff)
|
||||
const key = `${mediaType}Message`
|
||||
@@ -117,9 +118,9 @@ export const prepareWAMessageMedia = async(
|
||||
// url safe Base64 encode the SHA256 hash of the body
|
||||
const fileEncSha256B64 = encodeURIComponent(
|
||||
fileEncSha256.toString('base64')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/\=+$/, '')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/\=+$/, '')
|
||||
)
|
||||
|
||||
const [{ mediaUrl, directPath }] = await Promise.all([
|
||||
@@ -128,34 +129,35 @@ export const prepareWAMessageMedia = async(
|
||||
encWriteStream,
|
||||
{ fileEncSha256B64, mediaType, timeoutMs: options.mediaUploadTimeoutMs }
|
||||
)
|
||||
logger?.debug(`uploaded media`)
|
||||
logger?.debug('uploaded media')
|
||||
return result
|
||||
})(),
|
||||
(async() => {
|
||||
try {
|
||||
if(requiresThumbnailComputation) {
|
||||
uploadData.jpegThumbnail = await generateThumbnail(bodyPath, mediaType as any, options)
|
||||
logger?.debug(`generated thumbnail`)
|
||||
logger?.debug('generated thumbnail')
|
||||
}
|
||||
if (requiresDurationComputation) {
|
||||
|
||||
if(requiresDurationComputation) {
|
||||
uploadData.seconds = await getAudioDuration(bodyPath)
|
||||
logger?.debug(`computed audio duration`)
|
||||
logger?.debug('computed audio duration')
|
||||
}
|
||||
} catch (error) {
|
||||
} catch(error) {
|
||||
logger?.warn({ trace: error.stack }, 'failed to obtain extra info')
|
||||
}
|
||||
})(),
|
||||
])
|
||||
.finally(
|
||||
async() => {
|
||||
encWriteStream.destroy()
|
||||
// remove tmp files
|
||||
if(didSaveToTmpPath && bodyPath) {
|
||||
await fs.unlink(bodyPath)
|
||||
logger?.debug('removed tmp files')
|
||||
.finally(
|
||||
async() => {
|
||||
encWriteStream.destroy()
|
||||
// remove tmp files
|
||||
if(didSaveToTmpPath && bodyPath) {
|
||||
await fs.unlink(bodyPath)
|
||||
logger?.debug('removed tmp files')
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
delete uploadData.media
|
||||
|
||||
@@ -175,12 +177,13 @@ export const prepareWAMessageMedia = async(
|
||||
})
|
||||
|
||||
if(cacheableKey) {
|
||||
logger.debug({ cacheableKey }, `set cache`)
|
||||
logger.debug({ cacheableKey }, 'set cache')
|
||||
options.mediaCache!.set(cacheableKey, WAProto.Message.encode(obj).finish())
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
export const prepareDisappearingMessageSettingContent = (ephemeralExpiration?: number) => {
|
||||
ephemeralExpiration = ephemeralExpiration || 0
|
||||
const content: WAMessageContent = {
|
||||
@@ -195,6 +198,7 @@ export const prepareDisappearingMessageSettingContent = (ephemeralExpiration?: n
|
||||
}
|
||||
return WAProto.Message.fromObject(content)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate forwarded message content like WA does
|
||||
* @param message the message to forward
|
||||
@@ -205,7 +209,10 @@ export const generateForwardMessageContent = (
|
||||
forceForward?: boolean
|
||||
) => {
|
||||
let content = message.message
|
||||
if (!content) throw new Boom('no content in message', { statusCode: 400 })
|
||||
if(!content) {
|
||||
throw new Boom('no content in message', { statusCode: 400 })
|
||||
}
|
||||
|
||||
// hacky copy
|
||||
content = proto.Message.decode(proto.Message.encode(message.message).finish())
|
||||
|
||||
@@ -213,17 +220,22 @@ export const generateForwardMessageContent = (
|
||||
|
||||
let score = content[key].contextInfo?.forwardingScore || 0
|
||||
score += message.key.fromMe && !forceForward ? 0 : 1
|
||||
if (key === 'conversation') {
|
||||
if(key === 'conversation') {
|
||||
content.extendedTextMessage = { text: content[key] }
|
||||
delete content.conversation
|
||||
|
||||
key = 'extendedTextMessage'
|
||||
}
|
||||
if (score > 0) content[key].contextInfo = { forwardingScore: score, isForwarded: true }
|
||||
else content[key].contextInfo = {}
|
||||
|
||||
if(score > 0) {
|
||||
content[key].contextInfo = { forwardingScore: score, isForwarded: true }
|
||||
} else {
|
||||
content[key].contextInfo = {}
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
export const generateWAMessageContent = async(
|
||||
message: AnyMessageContent,
|
||||
options: MessageContentGenerationOptions
|
||||
@@ -231,7 +243,7 @@ export const generateWAMessageContent = async(
|
||||
let m: WAMessageContent = {}
|
||||
if('text' in message) {
|
||||
const extContent = { ...message } as WATextMessage
|
||||
if (!!options.getUrlInfo && message.text.match(URL_REGEX)) {
|
||||
if(!!options.getUrlInfo && message.text.match(URL_REGEX)) {
|
||||
try {
|
||||
const data = await options.getUrlInfo(message.text)
|
||||
extContent.canonicalUrl = data['canonical-url']
|
||||
@@ -240,16 +252,18 @@ export const generateWAMessageContent = async(
|
||||
extContent.description = data.description
|
||||
extContent.title = data.title
|
||||
extContent.previewType = 0
|
||||
} catch (error) { // ignore if fails
|
||||
} catch(error) { // ignore if fails
|
||||
options.logger?.warn({ trace: error.stack }, 'url generation failed')
|
||||
}
|
||||
}
|
||||
|
||||
m.extendedTextMessage = extContent
|
||||
} else if('contacts' in message) {
|
||||
const contactLen = message.contacts.contacts.length
|
||||
if(!contactLen) {
|
||||
throw new Boom('require atleast 1 contact', { statusCode: 400 })
|
||||
}
|
||||
}
|
||||
|
||||
if(contactLen === 1) {
|
||||
m.contactMessage = WAProto.ContactMessage.fromObject(message.contacts.contacts[0])
|
||||
} else {
|
||||
@@ -269,8 +283,8 @@ export const generateWAMessageContent = async(
|
||||
)
|
||||
} else if('disappearingMessagesInChat' in message) {
|
||||
const exp = typeof message.disappearingMessagesInChat === 'boolean' ?
|
||||
(message.disappearingMessagesInChat ? WA_DEFAULT_EPHEMERAL : 0) :
|
||||
message.disappearingMessagesInChat
|
||||
(message.disappearingMessagesInChat ? WA_DEFAULT_EPHEMERAL : 0) :
|
||||
message.disappearingMessagesInChat
|
||||
m = prepareDisappearingMessageSettingContent(exp)
|
||||
} else {
|
||||
m = await prepareWAMessageMedia(
|
||||
@@ -278,6 +292,7 @@ export const generateWAMessageContent = async(
|
||||
options
|
||||
)
|
||||
}
|
||||
|
||||
if('buttons' in message && !!message.buttons) {
|
||||
const buttonsMessage: proto.IButtonsMessage = {
|
||||
buttons: message.buttons!.map(b => ({ ...b, type: proto.Button.ButtonType.RESPONSE }))
|
||||
@@ -289,13 +304,14 @@ export const generateWAMessageContent = async(
|
||||
if('caption' in message) {
|
||||
buttonsMessage.contentText = message.caption
|
||||
}
|
||||
|
||||
const type = Object.keys(m)[0].replace('Message', '').toUpperCase()
|
||||
buttonsMessage.headerType = ButtonType[type]
|
||||
|
||||
Object.assign(buttonsMessage, m)
|
||||
}
|
||||
|
||||
if ('footer' in message && !!message.footer) {
|
||||
if('footer' in message && !!message.footer) {
|
||||
buttonsMessage.footerText = message.footer
|
||||
}
|
||||
|
||||
@@ -325,7 +341,7 @@ export const generateWAMessageContent = async(
|
||||
m = { templateMessage }
|
||||
}
|
||||
|
||||
if ('sections' in message && !!message.sections) {
|
||||
if('sections' in message && !!message.sections) {
|
||||
const listMessage: proto.IListMessage = {
|
||||
sections: message.sections,
|
||||
buttonText: message.buttonText,
|
||||
@@ -341,19 +357,24 @@ export const generateWAMessageContent = async(
|
||||
if('viewOnce' in message && !!message.viewOnce) {
|
||||
m = { viewOnceMessage: { message: m } }
|
||||
}
|
||||
|
||||
if('mentions' in message && message.mentions?.length) {
|
||||
const [messageType] = Object.keys(m)
|
||||
m[messageType].contextInfo = m[messageType] || { }
|
||||
m[messageType].contextInfo.mentionedJid = message.mentions
|
||||
}
|
||||
|
||||
return WAProto.Message.fromObject(m)
|
||||
}
|
||||
|
||||
export const generateWAMessageFromContent = (
|
||||
jid: string,
|
||||
message: WAMessageContent,
|
||||
options: MessageGenerationOptionsFromContent
|
||||
) => {
|
||||
if(!options.timestamp) options.timestamp = new Date() // set timestamp to now
|
||||
if(!options.timestamp) {
|
||||
options.timestamp = new Date()
|
||||
} // set timestamp to now
|
||||
|
||||
const key = Object.keys(message)[0]
|
||||
const timestamp = unixTimestampSeconds(options.timestamp)
|
||||
@@ -373,6 +394,7 @@ export const generateWAMessageFromContent = (
|
||||
message[key].contextInfo.remoteJid = quoted.key.remoteJid
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
// if we want to send a disappearing message
|
||||
!!options?.ephemeralExpiration &&
|
||||
@@ -409,6 +431,7 @@ export const generateWAMessageFromContent = (
|
||||
}
|
||||
return WAProto.WebMessageInfo.fromObject(messageJSON)
|
||||
}
|
||||
|
||||
export const generateWAMessage = async(
|
||||
jid: string,
|
||||
content: AnyMessageContent,
|
||||
@@ -434,6 +457,7 @@ export const getContentType = (content: WAProto.IMessage | undefined) => {
|
||||
return key as keyof typeof content
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the true message content from a message
|
||||
* Eg. extracts the inner message from a disappearing message/view once message
|
||||
@@ -447,17 +471,18 @@ export const extractMessageContent = (content: WAMessageContent | undefined | nu
|
||||
if(content?.buttonsMessage) {
|
||||
const { buttonsMessage } = content
|
||||
if(buttonsMessage.imageMessage) {
|
||||
return { imageMessage: buttonsMessage.imageMessage }
|
||||
return { imageMessage: buttonsMessage.imageMessage }
|
||||
} else if(buttonsMessage.documentMessage) {
|
||||
return { documentMessage: buttonsMessage.documentMessage }
|
||||
return { documentMessage: buttonsMessage.documentMessage }
|
||||
} else if(buttonsMessage.videoMessage) {
|
||||
return { videoMessage: buttonsMessage.videoMessage }
|
||||
return { videoMessage: buttonsMessage.videoMessage }
|
||||
} else if(buttonsMessage.locationMessage) {
|
||||
return { locationMessage: buttonsMessage.locationMessage }
|
||||
return { locationMessage: buttonsMessage.locationMessage }
|
||||
} else {
|
||||
return { conversation: buttonsMessage.contentText }
|
||||
return { conversation: buttonsMessage.contentText }
|
||||
}
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
@@ -465,6 +490,6 @@ export const extractMessageContent = (content: WAMessageContent | undefined | nu
|
||||
* Returns the device predicted by message ID
|
||||
*/
|
||||
export const getDevice = (id: string) => {
|
||||
const deviceType = id.length > 21 ? 'android' : id.substring(0, 2) == '3A' ? 'ios' : 'web'
|
||||
return deviceType
|
||||
const deviceType = id.length > 21 ? 'android' : id.substring(0, 2) === '3A' ? 'ios' : 'web'
|
||||
return deviceType
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user