mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Set Status + Set Group Description + Better Message Tags
This commit is contained in:
@@ -74,6 +74,15 @@ export default class WhatsAppWebBase extends WAConnection {
|
||||
async getStatus (jid?: string) {
|
||||
return this.query(['query', 'Status', jid || this.userMetaData.id]) as Promise<{ status: string }>
|
||||
}
|
||||
async setStatus (status: string) {
|
||||
return this.setQuery ([
|
||||
[
|
||||
'status',
|
||||
null,
|
||||
Buffer.from (status, 'utf-8')
|
||||
]
|
||||
])
|
||||
}
|
||||
/** Get the URL to download the profile picture of a person/group */
|
||||
async getProfilePicture(jid: string | null) {
|
||||
const response = await this.queryExpecting200(['query', 'ProfilePicThumb', jid || this.userMetaData.id])
|
||||
@@ -204,6 +213,7 @@ export default class WhatsAppWebBase extends WAConnection {
|
||||
/** Generic function for action, set queries */
|
||||
async setQuery (nodes: WANode[], binaryTags: WATag = [WAMetric.group, WAFlag.ignore], tag?: string) {
|
||||
const json = ['action', {epoch: this.msgCount.toString(), type: 'set'}, nodes]
|
||||
return this.queryExpecting200(json, binaryTags, null, tag) as Promise<{status: number}>
|
||||
const result = await this.queryExpecting200(json, binaryTags, null, tag) as Promise<{status: number}>
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import WhatsAppWebBase from './Base'
|
||||
import { WAMessage, WAMetric, WAFlag, WANode, WAGroupMetadata, WAGroupCreateResponse, WAGroupModification } from '../WAConnection/Constants'
|
||||
import { GroupSettingChange } from './Constants'
|
||||
import { generateMessageID } from '../WAConnection/Utils'
|
||||
|
||||
export default class WhatsAppWebGroups extends WhatsAppWebBase {
|
||||
/** Generic function for group queries */
|
||||
@@ -17,7 +18,8 @@ export default class WhatsAppWebGroups extends WhatsAppWebBase {
|
||||
},
|
||||
participants ? participants.map(str => ['participant', { jid: str }, null]) : additionalNodes,
|
||||
]
|
||||
return this.setQuery ([json], [WAMetric.group, WAFlag.ignore], tag)
|
||||
const result = await this.setQuery ([json], [WAMetric.group, WAFlag.ignore], tag)
|
||||
return result
|
||||
}
|
||||
/** Get the metadata of the group */
|
||||
groupMetadata = (jid: string) => this.queryExpecting200(['query', 'GroupMetadata', jid]) as Promise<WAGroupMetadata>
|
||||
@@ -58,6 +60,20 @@ export default class WhatsAppWebGroups extends WhatsAppWebBase {
|
||||
*/
|
||||
groupUpdateSubject = (jid: string, title: string) =>
|
||||
this.groupQuery('subject', jid, title) as Promise<{ status: number }>
|
||||
/**
|
||||
* Update the group description
|
||||
* @param {string} jid the ID of the group
|
||||
* @param {string} title the new title of the group
|
||||
*/
|
||||
groupUpdateDescription = async (jid: string, description: string) => {
|
||||
const metadata = await this.groupMetadata (jid)
|
||||
const node: WANode = [
|
||||
'description',
|
||||
{id: generateMessageID(), prev: metadata?.descId},
|
||||
Buffer.from (description, 'utf-8')
|
||||
]
|
||||
return this.groupQuery ('description', jid, null, null, [node])
|
||||
}
|
||||
/**
|
||||
* Add somebody to the group
|
||||
* @param jid the ID of the group
|
||||
|
||||
@@ -254,7 +254,7 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
return this.sendGenericMessage(id, m, options)
|
||||
}
|
||||
/** Prepare a media message for sending */
|
||||
protected async prepareMediaMessage(buffer: Buffer, mediaType: MessageType, options: MessageOptions = {}) {
|
||||
async prepareMediaMessage(buffer: Buffer, mediaType: MessageType, options: MessageOptions = {}) {
|
||||
if (mediaType === MessageType.document && !options.mimetype) {
|
||||
throw new Error('mimetype required to send a document')
|
||||
}
|
||||
@@ -278,10 +278,10 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
const fileSha256 = sha256(buffer)
|
||||
// url safe Base64 encode the SHA256 hash of the body
|
||||
const fileEncSha256B64 = sha256(body)
|
||||
.toString('base64')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/\=+$/, '')
|
||||
.toString('base64')
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/\=+$/, '')
|
||||
|
||||
await generateThumbnail(buffer, mediaType, options)
|
||||
// send a query JSON to obtain the url & auth token to upload our media
|
||||
@@ -311,6 +311,7 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
fileLength: buffer.length,
|
||||
fileName: options.filename || 'file',
|
||||
gifPlayback: isGIF || null,
|
||||
caption: options.caption
|
||||
}
|
||||
return message as WAMessageContent
|
||||
}
|
||||
@@ -332,13 +333,13 @@ export default class WhatsAppWebMessages extends WhatsAppWebGroups {
|
||||
message[key].contextInfo.participant = participant
|
||||
message[key].contextInfo.stanzaId = quoted.key.id
|
||||
message[key].contextInfo.quotedMessage = quoted.message
|
||||
|
||||
// if a participant is quoted, then it must be a group
|
||||
// hence, remoteJid of group must also be entered
|
||||
if (quoted.key.participant) {
|
||||
message[key].contextInfo.remoteJid = quoted.key.remoteJid
|
||||
}
|
||||
}
|
||||
message[key].caption = options?.caption
|
||||
if (!message[key].jpegThumbnail) message[key].jpegThumbnail = options?.thumbnail
|
||||
|
||||
const messageJSON = {
|
||||
|
||||
@@ -5,7 +5,8 @@ import * as assert from 'assert'
|
||||
import fetch from 'node-fetch'
|
||||
|
||||
import { decodeMediaMessage, validateJIDForSending } from './Utils'
|
||||
import { promiseTimeout, createTimeout, Browsers } from '../WAConnection/Utils'
|
||||
import { promiseTimeout, createTimeout, Browsers, generateMessageTag } from '../WAConnection/Utils'
|
||||
import { MessageLogLevel } from '../WAConnection/Constants'
|
||||
|
||||
require ('dotenv').config () // dotenv to load test jid
|
||||
const testJid = process.env.TEST_JID || '1234@s.whatsapp.net' // set TEST_JID=xyz@s.whatsapp.net in a .env file in the root directory
|
||||
@@ -19,6 +20,8 @@ async function sendAndRetreiveMessage(client: WAClient, content, type: MessageTy
|
||||
function WAClientTest(name: string, func: (client: WAClient) => void) {
|
||||
describe(name, () => {
|
||||
const client = new WAClient()
|
||||
client.logLevel = MessageLogLevel.info
|
||||
|
||||
before(async () => {
|
||||
const file = './auth_info.json'
|
||||
await client.connectSlim(file)
|
||||
@@ -121,9 +124,24 @@ WAClientTest('Misc', (client) => {
|
||||
})
|
||||
it('should return the status', async () => {
|
||||
const response = await client.getStatus(testJid)
|
||||
assert.ok(response.status)
|
||||
assert.strictEqual(typeof response.status, 'string')
|
||||
})
|
||||
it('should update status', async () => {
|
||||
const newStatus = 'v cool status'
|
||||
|
||||
const response = await client.getStatus()
|
||||
assert.strictEqual(typeof response.status, 'string')
|
||||
|
||||
await createTimeout (1000)
|
||||
|
||||
await client.setStatus (newStatus)
|
||||
const response2 = await client.getStatus()
|
||||
assert.equal (response2.status, newStatus)
|
||||
|
||||
await createTimeout (1000)
|
||||
|
||||
await client.setStatus (response.status) // update back
|
||||
})
|
||||
it('should return the stories', async () => {
|
||||
await client.getStories()
|
||||
})
|
||||
@@ -195,6 +213,15 @@ WAClientTest('Groups', (client) => {
|
||||
assert.strictEqual(metadata.id, gid)
|
||||
assert.strictEqual(metadata.participants.filter((obj) => obj.id.split('@')[0] === testJid.split('@')[0]).length, 1)
|
||||
})
|
||||
it('should update the group description', async () => {
|
||||
const newDesc = 'Wow this was set from Baileys'
|
||||
|
||||
await client.groupUpdateDescription (gid, newDesc)
|
||||
await createTimeout (1000)
|
||||
|
||||
const metadata = await client.groupMetadata(gid)
|
||||
assert.strictEqual(metadata.desc, newDesc)
|
||||
})
|
||||
it('should send a message on the group', async () => {
|
||||
await client.sendMessage(gid, 'hello', MessageType.text)
|
||||
})
|
||||
|
||||
@@ -326,7 +326,7 @@ export default class WAConnectionBase {
|
||||
}
|
||||
}
|
||||
generateMessageTag () {
|
||||
return `${this.referenceDate.getTime()/1000}.--${this.msgCount}`
|
||||
return `${Math.round(this.referenceDate.getTime())/1000}.--${this.msgCount}`
|
||||
}
|
||||
protected log(text, level: MessageLogLevel) {
|
||||
if (this.logLevel >= level)
|
||||
|
||||
@@ -61,6 +61,7 @@ export interface WAGroupMetadata {
|
||||
creation: number
|
||||
desc?: string
|
||||
descOwner?: string
|
||||
descId?: string
|
||||
participants: [{ id: string; isAdmin: boolean; isSuperAdmin: boolean }]
|
||||
}
|
||||
export interface WAGroupModification {
|
||||
|
||||
@@ -65,15 +65,23 @@ export function randomBytes(length) {
|
||||
return Crypto.randomBytes(length)
|
||||
}
|
||||
export const createTimeout = (timeout) => new Promise(resolve => setTimeout(resolve, timeout))
|
||||
export function promiseTimeout<T>(ms: number, promise: Promise<T>) {
|
||||
export async function promiseTimeout<T>(ms: number, promise: Promise<T>) {
|
||||
if (!ms) return promise
|
||||
// Create a promise that rejects in <ms> milliseconds
|
||||
const timeout = createTimeout (ms).then (() => { throw new BaileysError ('Timed out', promise) })
|
||||
return Promise.race([promise, timeout]) as Promise<T>
|
||||
let timeoutI
|
||||
const timeout = new Promise(
|
||||
(_, reject) => timeoutI = setTimeout(() => reject(new BaileysError ('Timed out', promise)), ms)
|
||||
)
|
||||
try {
|
||||
const content = await Promise.race([promise, timeout])
|
||||
return content as T
|
||||
} finally {
|
||||
clearTimeout (timeoutI)
|
||||
}
|
||||
}
|
||||
// whatsapp requires a message tag for every message, we just use the timestamp as one
|
||||
export function generateMessageTag(epoch?: number) {
|
||||
let tag = new Date().getTime().toString()
|
||||
let tag = Math.round(new Date().getTime()/1000).toString()
|
||||
if (epoch) tag += '.--' + epoch // attach epoch if provided
|
||||
return tag
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user