mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Merge branch 'master' into master
This commit is contained in:
79
.github/workflows/update-nightly.yml
vendored
Normal file
79
.github/workflows/update-nightly.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
name: Update Nightly
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
update-nightly:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Fetching tags
|
||||
run: git fetch --tags -f || true
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn
|
||||
|
||||
- name: Update version to alpha
|
||||
run: yarn version --prerelease --preid=alpha --no-git --no-git-tag-version
|
||||
|
||||
- name: Build NPM package
|
||||
run: yarn pack && mv whiskeysockets-baileys-*.tgz whiskeysockets-baileys-nightly.tgz
|
||||
|
||||
- name: Generate Changelog
|
||||
id: generate_changelog
|
||||
run: |
|
||||
changelog=$(yarn run --silent changelog:preview)
|
||||
echo "changelog<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "${changelog}" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Update Nightly TAG
|
||||
uses: richardsimko/update-tag@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: nightly
|
||||
|
||||
- name: Update Nightly Release
|
||||
uses: meeDamian/github-release@2.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
tag: nightly
|
||||
commitish: ${{ github.sha }}
|
||||
name: Nightly Release
|
||||
body: ${{ steps.generate_changelog.outputs.changelog }}
|
||||
draft: false
|
||||
prerelease: true
|
||||
files: >
|
||||
whiskeysockets-baileys-nightly.tgz
|
||||
gzip: folders
|
||||
allow_override: true
|
||||
@@ -1,4 +1,9 @@
|
||||
# 6.0.0 (2023-05-10)
|
||||
## 6.0.1 (2023-05-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* In memory store: normalize user when asserting message list to update messages ([#49](https://github.com/WhiskeySockets/Baileys/issues/49)) ([7b4abcd](https://github.com/WhiskeySockets/Baileys/commit/7b4abcdb231434c08c14dbb5879cd1fd4939fc41))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,12 +5,8 @@ import P from 'pino'
|
||||
import readline from 'readline'
|
||||
import makeWASocket, { AnyMessageContent, delay, DisconnectReason, fetchLatestBaileysVersion, getAggregateVotesInPollMessage, makeCacheableSignalKeyStore, makeInMemoryStore, PHONENUMBER_MCC, proto, useMultiFileAuthState, WAMessageContent, WAMessageKey } from '../src'
|
||||
|
||||
const logger = P({
|
||||
transport: {
|
||||
target: 'pino-pretty'
|
||||
},
|
||||
level: 'trace'
|
||||
})
|
||||
const logger = MAIN_LOGGER.child({})
|
||||
logger.level = 'trace'
|
||||
|
||||
const useStore = !process.argv.includes('--no-store')
|
||||
const doReplies = !process.argv.includes('--no-reply')
|
||||
@@ -159,6 +155,15 @@ const startSock = async() => {
|
||||
await saveCreds()
|
||||
}
|
||||
|
||||
if(events['labels.association']) {
|
||||
console.log(events['labels.association'])
|
||||
}
|
||||
|
||||
|
||||
if(events['labels.edit']) {
|
||||
console.log(events['labels.edit'])
|
||||
}
|
||||
|
||||
if(events.call) {
|
||||
console.log('recv call event', events.call)
|
||||
}
|
||||
|
||||
@@ -240,6 +240,8 @@ export type BaileysEventMap = {
|
||||
'chats.update': Partial<Chat>[]
|
||||
/** delete chats with given ID */
|
||||
'chats.delete': string[]
|
||||
'labels.association': LabelAssociation
|
||||
'labels.edit': Label
|
||||
/** presence of contact in a chat updated */
|
||||
'presence.update': { id: string, presences: { [participant: string]: PresenceData } }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@whiskeysockets/baileys",
|
||||
"version": "6.0.0",
|
||||
"version": "6.0.1",
|
||||
"description": "WhatsApp API",
|
||||
"keywords": [
|
||||
"whatsapp",
|
||||
@@ -71,7 +71,7 @@
|
||||
"sharp": "^0.30.5",
|
||||
"ts-jest": "^27.0.3",
|
||||
"ts-node": "^10.8.1",
|
||||
"typedoc": "^0.22.0",
|
||||
"typedoc": "^0.24.7",
|
||||
"typescript": "^4.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -52,7 +52,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
type: 'get'
|
||||
},
|
||||
content: [
|
||||
{ tag: 'privacy', attrs: { } }
|
||||
{ tag: 'privacy', attrs: {} }
|
||||
]
|
||||
})
|
||||
privacySettings = reduceBinaryNodeToDictionary(content?.[0] as BinaryNode, 'category')
|
||||
@@ -118,7 +118,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [{
|
||||
tag: 'disappearing_mode',
|
||||
attrs: {
|
||||
duration : duration.toString()
|
||||
duration: duration.toString()
|
||||
}
|
||||
}]
|
||||
})
|
||||
@@ -146,12 +146,12 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [
|
||||
{
|
||||
tag: 'query',
|
||||
attrs: { },
|
||||
content: [ queryNode ]
|
||||
attrs: {},
|
||||
content: [queryNode]
|
||||
},
|
||||
{
|
||||
tag: 'list',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: userNodes
|
||||
}
|
||||
]
|
||||
@@ -171,17 +171,17 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
[
|
||||
{
|
||||
tag: 'user',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: jids.map(
|
||||
jid => ({
|
||||
tag: 'contact',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: `+${jid}`
|
||||
})
|
||||
)
|
||||
}
|
||||
],
|
||||
{ tag: 'contact', attrs: { } }
|
||||
{ tag: 'contact', attrs: {} }
|
||||
)
|
||||
|
||||
return results.map(user => {
|
||||
@@ -193,7 +193,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
const fetchStatus = async(jid: string) => {
|
||||
const [result] = await interactiveQuery(
|
||||
[{ tag: 'user', attrs: { jid } }],
|
||||
{ tag: 'status', attrs: { } }
|
||||
{ tag: 'status', attrs: {} }
|
||||
)
|
||||
if(result) {
|
||||
const status = getBinaryNodeChild(result, 'status')
|
||||
@@ -248,7 +248,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [
|
||||
{
|
||||
tag: 'status',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: Buffer.from(status, 'utf-8')
|
||||
}
|
||||
]
|
||||
@@ -379,19 +379,19 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
const resyncAppState = ev.createBufferedFunction(async(collections: readonly WAPatchName[], isInitialSync: boolean) => {
|
||||
// we use this to determine which events to fire
|
||||
// otherwise when we resync from scratch -- all notifications will fire
|
||||
const initialVersionMap: { [T in WAPatchName]?: number } = { }
|
||||
const globalMutationMap: ChatMutationMap = { }
|
||||
const initialVersionMap: { [T in WAPatchName]?: number } = {}
|
||||
const globalMutationMap: ChatMutationMap = {}
|
||||
|
||||
await authState.keys.transaction(
|
||||
async() => {
|
||||
const collectionsToHandle = new Set<string>(collections)
|
||||
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
||||
const attemptsMap: { [T in WAPatchName]?: number } = { }
|
||||
const attemptsMap: { [T in WAPatchName]?: number } = {}
|
||||
// keep executing till all collections are done
|
||||
// sometimes a single patch request will not return all the patches (God knows why)
|
||||
// so we fetch till they're all done (this is determined by the "has_more_patches" flag)
|
||||
while(collectionsToHandle.size) {
|
||||
const states = { } as { [T in WAPatchName]: LTHashState }
|
||||
const states = {} as { [T in WAPatchName]: LTHashState }
|
||||
const nodes: BinaryNode[] = []
|
||||
|
||||
for(const name of collectionsToHandle) {
|
||||
@@ -412,7 +412,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
|
||||
nodes.push({
|
||||
tag: 'collection',
|
||||
attrs: {
|
||||
attrs: {
|
||||
name,
|
||||
version: state.version.toString(),
|
||||
// return snapshot if being synced from scratch
|
||||
@@ -431,7 +431,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [
|
||||
{
|
||||
tag: 'sync',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: nodes
|
||||
}
|
||||
]
|
||||
@@ -516,10 +516,10 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
})
|
||||
|
||||
/**
|
||||
* fetch the profile picture of a user/group
|
||||
* type = "preview" for a low res picture
|
||||
* type = "image for the high res picture"
|
||||
*/
|
||||
* fetch the profile picture of a user/group
|
||||
* type = "preview" for a low res picture
|
||||
* type = "image for the high res picture"
|
||||
*/
|
||||
const profilePictureUrl = async(jid: string, type: 'preview' | 'image' = 'preview', timeoutMs?: number) => {
|
||||
jid = jidNormalizedUser(jid)
|
||||
const result = await query({
|
||||
@@ -564,7 +564,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [
|
||||
{
|
||||
tag: type === 'recording' ? 'composing' : type,
|
||||
attrs: type === 'recording' ? { media : 'audio' } : {}
|
||||
attrs: type === 'recording' ? { media: 'audio' } : {}
|
||||
}
|
||||
]
|
||||
})
|
||||
@@ -587,7 +587,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
? [
|
||||
{
|
||||
tag: 'tctoken',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: tcToken
|
||||
}
|
||||
]
|
||||
@@ -669,7 +669,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [
|
||||
{
|
||||
tag: 'sync',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: [
|
||||
{
|
||||
tag: 'collection',
|
||||
@@ -681,7 +681,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
content: [
|
||||
{
|
||||
tag: 'patch',
|
||||
attrs: { },
|
||||
attrs: {},
|
||||
content: proto.SyncdPatch.encode(patch).finish()
|
||||
}
|
||||
]
|
||||
@@ -731,7 +731,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
|
||||
const propsNode = getBinaryNodeChild(abtNode, 'props')
|
||||
|
||||
let props: { [_: string]: string } = { }
|
||||
let props: { [_: string]: string } = {}
|
||||
if(propsNode) {
|
||||
props = reduceBinaryNodeToDictionary(propsNode, 'prop')
|
||||
}
|
||||
@@ -751,13 +751,13 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
type: 'get',
|
||||
},
|
||||
content: [
|
||||
{ tag: 'props', attrs: { } }
|
||||
{ tag: 'props', attrs: {} }
|
||||
]
|
||||
})
|
||||
|
||||
const propsNode = getBinaryNodeChild(resultNode, 'props')
|
||||
|
||||
let props: { [_: string]: string } = { }
|
||||
let props: { [_: string]: string } = {}
|
||||
if(propsNode) {
|
||||
props = reduceBinaryNodeToDictionary(propsNode, 'prop')
|
||||
}
|
||||
@@ -768,15 +768,61 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/**
|
||||
* modify a chat -- mark unread, read etc.
|
||||
* lastMessages must be sorted in reverse chronologically
|
||||
* requires the last messages till the last message received; required for archive & unread
|
||||
*/
|
||||
* modify a chat -- mark unread, read etc.
|
||||
* lastMessages must be sorted in reverse chronologically
|
||||
* requires the last messages till the last message received; required for archive & unread
|
||||
*/
|
||||
const chatModify = (mod: ChatModification, jid: string) => {
|
||||
const patch = chatModificationToAppPatch(mod, jid)
|
||||
return appPatch(patch)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds label for the chats
|
||||
*/
|
||||
const addChatLabel = (jid: string, labelId: string) => {
|
||||
return chatModify({
|
||||
addChatLabel: {
|
||||
labelId
|
||||
}
|
||||
}, jid)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes label for the chat
|
||||
*/
|
||||
const removeChatLabel = (jid: string, labelId: string) => {
|
||||
return chatModify({
|
||||
removeChatLabel: {
|
||||
labelId
|
||||
}
|
||||
}, jid)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds label for the message
|
||||
*/
|
||||
const addMessageLabel = (jid: string, messageId: string, labelId: string) => {
|
||||
return chatModify({
|
||||
addMessageLabel: {
|
||||
messageId,
|
||||
labelId
|
||||
}
|
||||
}, jid)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes label for the message
|
||||
*/
|
||||
const removeMessageLabel = (jid: string, messageId: string, labelId: string) => {
|
||||
return chatModify({
|
||||
removeMessageLabel: {
|
||||
messageId,
|
||||
labelId
|
||||
}
|
||||
}, jid)
|
||||
}
|
||||
|
||||
/**
|
||||
* queries need to be fired on connection open
|
||||
* help ensure parity with WA Web
|
||||
@@ -949,6 +995,10 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
getBusinessProfile,
|
||||
resyncAppState,
|
||||
chatModify,
|
||||
cleanDirtyBits
|
||||
cleanDirtyBits,
|
||||
addChatLabel,
|
||||
removeChatLabel,
|
||||
addMessageLabel,
|
||||
removeMessageLabel
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,94 @@
|
||||
import type KeyedDB from '@adiwajshing/keyed-db'
|
||||
import KeyedDB from '@adiwajshing/keyed-db'
|
||||
import type { Comparable } from '@adiwajshing/keyed-db/lib/Types'
|
||||
import type { Logger } from 'pino'
|
||||
import { proto } from '../../WAProto'
|
||||
import { DEFAULT_CONNECTION_CONFIG } from '../Defaults'
|
||||
import type makeMDSocket from '../Socket'
|
||||
import type { BaileysEventEmitter, Chat, ConnectionState, Contact, GroupMetadata, PresenceData, WAMessage, WAMessageCursor, WAMessageKey } from '../Types'
|
||||
import { Label } from '../Types/Label'
|
||||
import { LabelAssociation, LabelAssociationType, MessageLabelAssociation } from '../Types/LabelAssociation'
|
||||
import { toNumber, updateMessageWithReaction, updateMessageWithReceipt } from '../Utils'
|
||||
import { jidNormalizedUser } from '../WABinary'
|
||||
import makeOrderedDictionary from './make-ordered-dictionary'
|
||||
import { ObjectRepository } from './object-repository'
|
||||
|
||||
type WASocket = ReturnType<typeof makeMDSocket>
|
||||
|
||||
export const waChatKey = (pin: boolean) => ({
|
||||
key: (c: Chat) => (pin ? (c.pinned ? '1' : '0') : '') + (c.archived ? '0' : '1') + (c.conversationTimestamp ? c.conversationTimestamp.toString(16).padStart(8, '0') : '') + c.id,
|
||||
compare: (k1: string, k2: string) => k2.localeCompare (k1)
|
||||
compare: (k1: string, k2: string) => k2.localeCompare(k1)
|
||||
})
|
||||
|
||||
export const waMessageID = (m: WAMessage) => m.key.id || ''
|
||||
|
||||
export const waLabelAssociationKey: Comparable<LabelAssociation, string> = {
|
||||
key: (la: LabelAssociation) => (la.type === LabelAssociationType.Chat ? la.chatId + la.labelId : la.chatId + la.messageId + la.labelId),
|
||||
compare: (k1: string, k2: string) => k2.localeCompare(k1)
|
||||
}
|
||||
|
||||
export type BaileysInMemoryStoreConfig = {
|
||||
chatKey?: Comparable<Chat, string>
|
||||
labelAssociationKey?: Comparable<LabelAssociation, string>
|
||||
logger?: Logger
|
||||
}
|
||||
|
||||
const makeMessagesDictionary = () => makeOrderedDictionary(waMessageID)
|
||||
|
||||
export default (
|
||||
{ logger: _logger, chatKey }: BaileysInMemoryStoreConfig
|
||||
) => {
|
||||
const logger = _logger || DEFAULT_CONNECTION_CONFIG.logger.child({ stream: 'in-mem-store' })
|
||||
chatKey = chatKey || waChatKey(true)
|
||||
const KeyedDB = require('@adiwajshing/keyed-db').default as new (...args: any[]) => KeyedDB<Chat, string>
|
||||
const predefinedLabels = Object.freeze<Record<string, Label>>({
|
||||
'0': {
|
||||
id: '0',
|
||||
name: 'New customer',
|
||||
predefinedId: '0',
|
||||
color: 0,
|
||||
deleted: false
|
||||
},
|
||||
'1': {
|
||||
id: '1',
|
||||
name: 'New order',
|
||||
predefinedId: '1',
|
||||
color: 1,
|
||||
deleted: false
|
||||
},
|
||||
'2': {
|
||||
id: '2',
|
||||
name: 'Pending payment',
|
||||
predefinedId: '2',
|
||||
color: 2,
|
||||
deleted: false
|
||||
},
|
||||
'3': {
|
||||
id: '3',
|
||||
name: 'Paid',
|
||||
predefinedId: '3',
|
||||
color: 3,
|
||||
deleted: false
|
||||
},
|
||||
'4': {
|
||||
id: '4',
|
||||
name: 'Order completed',
|
||||
predefinedId: '4',
|
||||
color: 4,
|
||||
deleted: false
|
||||
}
|
||||
})
|
||||
|
||||
const chats = new KeyedDB(chatKey, c => c.id)
|
||||
const messages: { [_: string]: ReturnType<typeof makeMessagesDictionary> } = { }
|
||||
const contacts: { [_: string]: Contact } = { }
|
||||
const groupMetadata: { [_: string]: GroupMetadata } = { }
|
||||
const presences: { [id: string]: { [participant: string]: PresenceData } } = { }
|
||||
export default (
|
||||
{ logger: _logger, chatKey, labelAssociationKey }: BaileysInMemoryStoreConfig
|
||||
) => {
|
||||
// const logger = _logger || DEFAULT_CONNECTION_CONFIG.logger.child({ stream: 'in-mem-store' })
|
||||
chatKey = chatKey || waChatKey(true)
|
||||
labelAssociationKey = labelAssociationKey || waLabelAssociationKey
|
||||
const logger = _logger || DEFAULT_CONNECTION_CONFIG.logger.child({ stream: 'in-mem-store' })
|
||||
// const KeyedDB = require('@adiwajshing/keyed-db').default as new (...args: any[]) => KeyedDB<Chat, string>
|
||||
|
||||
const chats = new KeyedDB<Chat, string>(chatKey, c => c.id)
|
||||
const messages: { [_: string]: ReturnType<typeof makeMessagesDictionary> } = {}
|
||||
const contacts: { [_: string]: Contact } = {}
|
||||
const groupMetadata: { [_: string]: GroupMetadata } = {}
|
||||
const presences: { [id: string]: { [participant: string]: PresenceData } } = {}
|
||||
const state: ConnectionState = { connection: 'close' }
|
||||
const labels = new ObjectRepository<Label>(predefinedLabels)
|
||||
const labelAssociations = new KeyedDB<LabelAssociation, string>(labelAssociationKey, labelAssociationKey.key)
|
||||
|
||||
const assertMessageList = (jid: string) => {
|
||||
if(!messages[jid]) {
|
||||
@@ -60,6 +111,12 @@ export default (
|
||||
return oldContacts
|
||||
}
|
||||
|
||||
const labelsUpsert = (newLabels: Label[]) => {
|
||||
for(const label of newLabels) {
|
||||
labels.upsertById(label.id, label)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* binds to a BaileysEventEmitter.
|
||||
* It listens to all events and constructs a state that you can query accurate data from.
|
||||
@@ -131,6 +188,33 @@ export default (
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ev.on('labels.edit', (label: Label) => {
|
||||
if(label.deleted) {
|
||||
return labels.deleteById(label.id)
|
||||
}
|
||||
|
||||
// WhatsApp can store only up to 20 labels
|
||||
if(labels.count() < 20) {
|
||||
return labels.upsertById(label.id, label)
|
||||
}
|
||||
|
||||
logger.error('Labels count exceed')
|
||||
})
|
||||
|
||||
ev.on('labels.association', ({ type, association }) => {
|
||||
switch (type) {
|
||||
case 'add':
|
||||
labelAssociations.upsert(association)
|
||||
break
|
||||
case 'remove':
|
||||
labelAssociations.delete(association)
|
||||
break
|
||||
default:
|
||||
console.error(`unknown operation type [${type}]`)
|
||||
}
|
||||
})
|
||||
|
||||
ev.on('presence.update', ({ id, presences: update }) => {
|
||||
presences[id] = presences[id] || {}
|
||||
Object.assign(presences[id], update)
|
||||
@@ -167,7 +251,16 @@ export default (
|
||||
})
|
||||
ev.on('messages.update', updates => {
|
||||
for(const { update, key } of updates) {
|
||||
const list = assertMessageList(key.remoteJid!)
|
||||
const list = assertMessageList(jidNormalizedUser(key.remoteJid!))
|
||||
if(update?.status) {
|
||||
const listStatus = list.get(key.id!)?.status
|
||||
if(listStatus && update?.status <= listStatus) {
|
||||
logger.debug({ update, storedStatus: listStatus }, 'status stored newer then update')
|
||||
delete update.status
|
||||
logger.debug({ update }, 'new update object')
|
||||
}
|
||||
}
|
||||
|
||||
const result = list.updateAssign(key.id!, update)
|
||||
if(!result) {
|
||||
logger.debug({ update }, 'got update for non-existent message')
|
||||
@@ -246,12 +339,16 @@ export default (
|
||||
const toJSON = () => ({
|
||||
chats,
|
||||
contacts,
|
||||
messages
|
||||
messages,
|
||||
labels,
|
||||
labelAssociations
|
||||
})
|
||||
|
||||
const fromJSON = (json: { chats: Chat[], contacts: { [id: string]: Contact }, messages: { [id: string]: WAMessage[] } }) => {
|
||||
const fromJSON = (json: {chats: Chat[], contacts: { [id: string]: Contact }, messages: { [id: string]: WAMessage[] }, labels: { [labelId: string]: Label }, labelAssociations: LabelAssociation[]}) => {
|
||||
chats.upsert(...json.chats)
|
||||
labelAssociations.upsert(...json.labelAssociations || [])
|
||||
contactsUpsert(Object.values(json.contacts))
|
||||
labelsUpsert(Object.values(json.labels || {}))
|
||||
for(const jid in json.messages) {
|
||||
const list = assertMessageList(jid)
|
||||
for(const msg of json.messages[jid]) {
|
||||
@@ -268,6 +365,8 @@ export default (
|
||||
groupMetadata,
|
||||
state,
|
||||
presences,
|
||||
labels,
|
||||
labelAssociations,
|
||||
bind,
|
||||
/** loads messages from the store, if not found -- uses the legacy connection */
|
||||
loadMessages: async(jid: string, count: number, cursor: WAMessageCursor) => {
|
||||
@@ -295,6 +394,38 @@ export default (
|
||||
|
||||
return messages
|
||||
},
|
||||
/**
|
||||
* Get all available labels for profile
|
||||
*
|
||||
* Keep in mind that the list is formed from predefined tags and tags
|
||||
* that were "caught" during their editing.
|
||||
*/
|
||||
getLabels: () => {
|
||||
return labels
|
||||
},
|
||||
|
||||
/**
|
||||
* Get labels for chat
|
||||
*
|
||||
* @returns Label IDs
|
||||
**/
|
||||
getChatLabels: (chatId: string) => {
|
||||
return labelAssociations.filter((la) => la.chatId === chatId).all()
|
||||
},
|
||||
|
||||
/**
|
||||
* Get labels for message
|
||||
*
|
||||
* @returns Label IDs
|
||||
**/
|
||||
getMessageLabels: (messageId: string) => {
|
||||
const associations = labelAssociations
|
||||
.filter((la: MessageLabelAssociation) => la.messageId === messageId)
|
||||
.all()
|
||||
|
||||
return associations.map(({ labelId }) => labelId)
|
||||
|
||||
},
|
||||
loadMessage: async(jid: string, id: string) => messages[jid]?.get(id),
|
||||
mostRecentMessage: async(jid: string) => {
|
||||
const message: WAMessage | undefined = messages[jid]?.array.slice(-1)[0]
|
||||
|
||||
32
src/Store/object-repository.ts
Normal file
32
src/Store/object-repository.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
export class ObjectRepository<T extends object> {
|
||||
readonly entityMap: Map<string, T>
|
||||
|
||||
constructor(entities: Record<string, T> = {}) {
|
||||
this.entityMap = new Map(Object.entries(entities))
|
||||
}
|
||||
|
||||
findById(id: string) {
|
||||
return this.entityMap.get(id)
|
||||
}
|
||||
|
||||
findAll() {
|
||||
return Array.from(this.entityMap.values())
|
||||
}
|
||||
|
||||
upsertById(id: string, entity: T) {
|
||||
return this.entityMap.set(id, { ...entity })
|
||||
}
|
||||
|
||||
deleteById(id: string) {
|
||||
return this.entityMap.delete(id)
|
||||
}
|
||||
|
||||
count() {
|
||||
return this.entityMap.size
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.findAll()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { proto } from '../../WAProto'
|
||||
import type { AccountSettings } from './Auth'
|
||||
import type { BufferedEventData } from './Events'
|
||||
import type { ChatLabelAssociationActionBody } from './LabelAssociation'
|
||||
import type { MessageLabelAssociationActionBody } from './LabelAssociation'
|
||||
import type { MinimalMessage } from './Message'
|
||||
|
||||
/** privacy settings in WhatsApp Web */
|
||||
@@ -13,13 +15,7 @@ export type WAReadReceiptsValue = 'all' | 'none'
|
||||
/** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
|
||||
export type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused'
|
||||
|
||||
export const ALL_WA_PATCH_NAMES = [
|
||||
'critical_block',
|
||||
'critical_unblock_low',
|
||||
'regular_high',
|
||||
'regular_low',
|
||||
'regular'
|
||||
] as const
|
||||
export const ALL_WA_PATCH_NAMES = ['critical_block', 'critical_unblock_low', 'regular_high', 'regular_low', 'regular'] as const
|
||||
|
||||
export type WAPatchName = typeof ALL_WA_PATCH_NAMES[number]
|
||||
|
||||
@@ -77,7 +73,7 @@ export type ChatModification =
|
||||
mute: number | null
|
||||
}
|
||||
| {
|
||||
clear: 'all' | { messages: {id: string, fromMe?: boolean, timestamp: number}[] }
|
||||
clear: 'all' | { messages: { id: string, fromMe?: boolean, timestamp: number }[] }
|
||||
}
|
||||
| {
|
||||
star: {
|
||||
@@ -90,6 +86,11 @@ export type ChatModification =
|
||||
lastMessages: LastMessageList
|
||||
}
|
||||
| { delete: true, lastMessages: LastMessageList }
|
||||
// Label assosiation
|
||||
| { addChatLabel: ChatLabelAssociationActionBody }
|
||||
| { removeChatLabel: ChatLabelAssociationActionBody }
|
||||
| { addMessageLabel: MessageLabelAssociationActionBody }
|
||||
| { removeMessageLabel: MessageLabelAssociationActionBody }
|
||||
|
||||
export type InitialReceivedChatsState = {
|
||||
[jid: string]: {
|
||||
|
||||
@@ -5,6 +5,8 @@ import { WACallEvent } from './Call'
|
||||
import { Chat, ChatUpdate, PresenceData } from './Chat'
|
||||
import { Contact } from './Contact'
|
||||
import { GroupMetadata, ParticipantAction } from './GroupMetadata'
|
||||
import { Label } from './Label'
|
||||
import { LabelAssociation } from './LabelAssociation'
|
||||
import { MessageUpsertType, MessageUserReceiptUpdate, WAMessage, WAMessageKey, WAMessageUpdate } from './Message'
|
||||
import { ConnectionState } from './State'
|
||||
|
||||
@@ -54,6 +56,8 @@ export type BaileysEventMap = {
|
||||
'blocklist.update': { blocklist: string[], type: 'add' | 'remove' }
|
||||
/** Receive an update on a call, including when the call was received, rejected, accepted */
|
||||
'call': WACallEvent[]
|
||||
'labels.edit': Label
|
||||
'labels.association': { association: LabelAssociation, type: 'add' | 'remove' }
|
||||
}
|
||||
|
||||
export type BufferedEventData = {
|
||||
|
||||
36
src/Types/Label.ts
Normal file
36
src/Types/Label.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
export interface Label {
|
||||
/** Label uniq ID */
|
||||
id: string
|
||||
/** Label name */
|
||||
name: string
|
||||
/** Label color ID */
|
||||
color: number
|
||||
/** Is label has been deleted */
|
||||
deleted: boolean
|
||||
/** WhatsApp has 5 predefined labels (New customer, New order & etc) */
|
||||
predefinedId?: string
|
||||
}
|
||||
|
||||
/** WhatsApp has 20 predefined colors */
|
||||
export enum LabelColor {
|
||||
Color1 = 0,
|
||||
Color2,
|
||||
Color3,
|
||||
Color4,
|
||||
Color5,
|
||||
Color6,
|
||||
Color7,
|
||||
Color8,
|
||||
Color9,
|
||||
Color10,
|
||||
Color11,
|
||||
Color12,
|
||||
Color13,
|
||||
Color14,
|
||||
Color15,
|
||||
Color16,
|
||||
Color17,
|
||||
Color18,
|
||||
Color19,
|
||||
Color20,
|
||||
}
|
||||
35
src/Types/LabelAssociation.ts
Normal file
35
src/Types/LabelAssociation.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/** Association type */
|
||||
export enum LabelAssociationType {
|
||||
Chat = 'label_jid',
|
||||
Message = 'label_message'
|
||||
}
|
||||
|
||||
export type LabelAssociationTypes = `${LabelAssociationType}`
|
||||
|
||||
/** Association for chat */
|
||||
export interface ChatLabelAssociation {
|
||||
type: LabelAssociationType.Chat
|
||||
chatId: string
|
||||
labelId: string
|
||||
}
|
||||
|
||||
/** Association for message */
|
||||
export interface MessageLabelAssociation {
|
||||
type: LabelAssociationType.Message
|
||||
chatId: string
|
||||
messageId: string
|
||||
labelId: string
|
||||
}
|
||||
|
||||
export type LabelAssociation = ChatLabelAssociation | MessageLabelAssociation
|
||||
|
||||
/** Body for add/remove chat label association action */
|
||||
export interface ChatLabelAssociationActionBody {
|
||||
labelId: string
|
||||
}
|
||||
|
||||
/** body for add/remove message label association action */
|
||||
export interface MessageLabelAssociationActionBody {
|
||||
labelId: string
|
||||
messageId: string
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import { AxiosRequestConfig } from 'axios'
|
||||
import type { Logger } from 'pino'
|
||||
import { proto } from '../../WAProto'
|
||||
import { BaileysEventEmitter, Chat, ChatModification, ChatMutation, ChatUpdate, Contact, InitialAppStateSyncOptions, LastMessageList, LTHashState, WAPatchCreate, WAPatchName } from '../Types'
|
||||
import { ChatLabelAssociation, LabelAssociationType, MessageLabelAssociation } from '../Types/LabelAssociation'
|
||||
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidNormalizedUser } from '../WABinary'
|
||||
import { aesDecrypt, aesEncrypt, hkdf, hmacSign } from './crypto'
|
||||
import { toNumber } from './generics'
|
||||
@@ -37,15 +38,15 @@ const generateMac = (operation: proto.SyncdMutation.SyncdOperation, data: Buffer
|
||||
}
|
||||
|
||||
const buff = Buffer.from([r])
|
||||
return Buffer.concat([ buff, Buffer.from(keyId as any, 'base64') ])
|
||||
return Buffer.concat([buff, Buffer.from(keyId as any, 'base64')])
|
||||
}
|
||||
|
||||
const keyData = getKeyData()
|
||||
|
||||
const last = Buffer.alloc(8) // 8 bytes
|
||||
last.set([ keyData.length ], last.length - 1)
|
||||
last.set([keyData.length], last.length - 1)
|
||||
|
||||
const total = Buffer.concat([ keyData, data, last ])
|
||||
const total = Buffer.concat([keyData, data, last])
|
||||
const hmac = hmacSign(total, key, 'sha512')
|
||||
|
||||
return hmac.slice(0, 32)
|
||||
@@ -170,7 +171,7 @@ export const encodeSyncdPatch = async(
|
||||
blob: indexMac
|
||||
},
|
||||
value: {
|
||||
blob: Buffer.concat([ encValue, valueMac ])
|
||||
blob: Buffer.concat([encValue, valueMac])
|
||||
},
|
||||
keyId: { id: encKeyId }
|
||||
}
|
||||
@@ -280,7 +281,7 @@ export const extractSyncdPatches = async(
|
||||
const syncNode = getBinaryNodeChild(result, 'sync')
|
||||
const collectionNodes = getBinaryNodeChildren(syncNode, 'collection')
|
||||
|
||||
const final = { } as { [T in WAPatchName]: { patches: proto.ISyncdPatch[], hasMorePatches: boolean, snapshot?: proto.ISyncdSnapshot } }
|
||||
const final = {} as { [T in WAPatchName]: { patches: proto.ISyncdPatch[], hasMorePatches: boolean, snapshot?: proto.ISyncdSnapshot } }
|
||||
await Promise.all(
|
||||
collectionNodes.map(
|
||||
async collectionNode => {
|
||||
@@ -301,7 +302,7 @@ export const extractSyncdPatches = async(
|
||||
}
|
||||
|
||||
const blobRef = proto.ExternalBlobReference.decode(
|
||||
snapshotNode.content! as Buffer
|
||||
snapshotNode.content! as Buffer
|
||||
)
|
||||
const data = await downloadExternalBlob(blobRef, options)
|
||||
snapshot = proto.SyncdSnapshot.decode(data)
|
||||
@@ -417,9 +418,9 @@ export const decodePatches = async(
|
||||
indexValueMap: { ...initial.indexValueMap }
|
||||
}
|
||||
|
||||
const mutationMap: ChatMutationMap = { }
|
||||
const mutationMap: ChatMutationMap = {}
|
||||
|
||||
for(let i = 0;i < syncds.length;i++) {
|
||||
for(let i = 0; i < syncds.length; i++) {
|
||||
const syncd = syncds[i]
|
||||
const { version, keyId, snapshotMac } = syncd
|
||||
if(syncd.externalMutations) {
|
||||
@@ -606,6 +607,68 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 1,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if('addChatLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
labeled: true,
|
||||
}
|
||||
},
|
||||
index: [LabelAssociationType.Chat, mod.addChatLabel.labelId, jid],
|
||||
type: 'regular',
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if('removeChatLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
labeled: false,
|
||||
}
|
||||
},
|
||||
index: [LabelAssociationType.Chat, mod.removeChatLabel.labelId, jid],
|
||||
type: 'regular',
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if('addMessageLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
labeled: true,
|
||||
}
|
||||
},
|
||||
index: [
|
||||
LabelAssociationType.Message,
|
||||
mod.addMessageLabel.labelId,
|
||||
jid,
|
||||
mod.addMessageLabel.messageId,
|
||||
'0',
|
||||
'0'
|
||||
],
|
||||
type: 'regular',
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if('removeMessageLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
labeled: false,
|
||||
}
|
||||
},
|
||||
index: [
|
||||
LabelAssociationType.Message,
|
||||
mod.removeMessageLabel.labelId,
|
||||
jid,
|
||||
mod.removeMessageLabel.messageId,
|
||||
'0',
|
||||
'0'
|
||||
],
|
||||
type: 'regular',
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else {
|
||||
throw new Boom('not supported')
|
||||
}
|
||||
@@ -659,7 +722,7 @@ export const processSyncAction = (
|
||||
const archiveAction = action?.archiveChatAction
|
||||
const isArchived = archiveAction
|
||||
? archiveAction.archived
|
||||
: type === 'archive'
|
||||
: type === 'archive'
|
||||
// // basically we don't need to fire an "archive" update if the chat is being marked unarchvied
|
||||
// // this only applies for the initial sync
|
||||
// if(isInitialSync && !isArchived) {
|
||||
@@ -687,13 +750,15 @@ export const processSyncAction = (
|
||||
conditional: getChatUpdateConditional(id, markReadAction?.messageRange)
|
||||
}])
|
||||
} else if(action?.deleteMessageForMeAction || type === 'deleteMessageForMe') {
|
||||
ev.emit('messages.delete', { keys: [
|
||||
{
|
||||
remoteJid: id,
|
||||
id: msgId,
|
||||
fromMe: fromMe === '1'
|
||||
}
|
||||
] })
|
||||
ev.emit('messages.delete', {
|
||||
keys: [
|
||||
{
|
||||
remoteJid: id,
|
||||
id: msgId,
|
||||
fromMe: fromMe === '1'
|
||||
}
|
||||
]
|
||||
})
|
||||
} else if(action?.contactAction) {
|
||||
ev.emit('contacts.upsert', [{ id, name: action.contactAction!.fullName! }])
|
||||
} else if(action?.pushNameSetting) {
|
||||
@@ -731,6 +796,34 @@ export const processSyncAction = (
|
||||
if(!isInitialSync) {
|
||||
ev.emit('chats.delete', [id])
|
||||
}
|
||||
} else if(action?.labelEditAction) {
|
||||
const { name, color, deleted, predefinedId } = action.labelEditAction!
|
||||
|
||||
ev.emit('labels.edit', {
|
||||
id,
|
||||
name: name!,
|
||||
color: color!,
|
||||
deleted: deleted!,
|
||||
predefinedId: predefinedId ? String(predefinedId) : undefined
|
||||
})
|
||||
} else if(action?.labelAssociationAction) {
|
||||
ev.emit('labels.association', {
|
||||
type: action.labelAssociationAction.labeled
|
||||
? 'add'
|
||||
: 'remove',
|
||||
association: type === LabelAssociationType.Chat
|
||||
? {
|
||||
type: LabelAssociationType.Chat,
|
||||
chatId: syncAction.index[2],
|
||||
labelId: syncAction.index[1]
|
||||
} as ChatLabelAssociation
|
||||
: {
|
||||
type: LabelAssociationType.Message,
|
||||
chatId: syncAction.index[2],
|
||||
messageId: syncAction.index[3],
|
||||
labelId: syncAction.index[1]
|
||||
} as MessageLabelAssociation
|
||||
})
|
||||
} else {
|
||||
logger?.debug({ syncAction, id }, 'unprocessable update')
|
||||
}
|
||||
|
||||
77
yarn.lock
77
yarn.lock
@@ -1522,6 +1522,11 @@ ansi-regex@^6.0.1:
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
|
||||
integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
|
||||
|
||||
ansi-sequence-parser@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz#4d790f31236ac20366b23b3916b789e1bde39aed"
|
||||
integrity sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==
|
||||
|
||||
ansi-styles@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz"
|
||||
@@ -3484,7 +3489,7 @@ glob-parent@^6.0.1:
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0:
|
||||
glob@^7.0.0, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
@@ -4767,10 +4772,10 @@ json5@2.x, json5@^2.2.1:
|
||||
resolved "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz"
|
||||
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
|
||||
|
||||
jsonc-parser@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz"
|
||||
integrity sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==
|
||||
jsonc-parser@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
|
||||
integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==
|
||||
|
||||
jsonfile@^4.0.0:
|
||||
version "4.0.0"
|
||||
@@ -5026,10 +5031,10 @@ map-obj@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a"
|
||||
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
|
||||
|
||||
marked@^4.0.12:
|
||||
version "4.0.16"
|
||||
resolved "https://registry.npmjs.org/marked/-/marked-4.0.16.tgz"
|
||||
integrity sha512-wahonIQ5Jnyatt2fn8KqF/nIqZM8mh3oRu2+l5EANGMhu6RFjiSG52QNE2eWzFMI94HqYSgN184NurgNG6CztA==
|
||||
marked@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3"
|
||||
integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==
|
||||
|
||||
media-typer@^1.1.0:
|
||||
version "1.1.0"
|
||||
@@ -5127,10 +5132,10 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimatch@^5.0.1:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz"
|
||||
integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
|
||||
minimatch@^9.0.0:
|
||||
version "9.0.0"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.0.tgz#bfc8e88a1c40ffd40c172ddac3decb8451503b56"
|
||||
integrity sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==
|
||||
dependencies:
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
@@ -6482,14 +6487,15 @@ shelljs@0.8.5:
|
||||
interpret "^1.0.0"
|
||||
rechoir "^0.6.2"
|
||||
|
||||
shiki@^0.10.1:
|
||||
version "0.10.1"
|
||||
resolved "https://registry.npmjs.org/shiki/-/shiki-0.10.1.tgz"
|
||||
integrity sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng==
|
||||
shiki@^0.14.1:
|
||||
version "0.14.2"
|
||||
resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.14.2.tgz#d51440800b701392b31ce2336036058e338247a1"
|
||||
integrity sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==
|
||||
dependencies:
|
||||
jsonc-parser "^3.0.0"
|
||||
vscode-oniguruma "^1.6.1"
|
||||
vscode-textmate "5.2.0"
|
||||
ansi-sequence-parser "^1.1.0"
|
||||
jsonc-parser "^3.2.0"
|
||||
vscode-oniguruma "^1.7.0"
|
||||
vscode-textmate "^8.0.0"
|
||||
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.4"
|
||||
@@ -7184,16 +7190,15 @@ typedarray-to-buffer@^3.1.5:
|
||||
dependencies:
|
||||
is-typedarray "^1.0.0"
|
||||
|
||||
typedoc@^0.22.0:
|
||||
version "0.22.15"
|
||||
resolved "https://registry.npmjs.org/typedoc/-/typedoc-0.22.15.tgz"
|
||||
integrity sha512-CMd1lrqQbFvbx6S9G6fL4HKp3GoIuhujJReWqlIvSb2T26vGai+8Os3Mde7Pn832pXYemd9BMuuYWhFpL5st0Q==
|
||||
typedoc@^0.24.7:
|
||||
version "0.24.7"
|
||||
resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.24.7.tgz#7eeb272a1894b3789acc1a94b3f2ae8e7330ee39"
|
||||
integrity sha512-zzfKDFIZADA+XRIp2rMzLe9xZ6pt12yQOhCr7cD7/PBTjhPmMyMvGrkZ2lPNJitg3Hj1SeiYFNzCsSDrlpxpKw==
|
||||
dependencies:
|
||||
glob "^7.2.0"
|
||||
lunr "^2.3.9"
|
||||
marked "^4.0.12"
|
||||
minimatch "^5.0.1"
|
||||
shiki "^0.10.1"
|
||||
marked "^4.3.0"
|
||||
minimatch "^9.0.0"
|
||||
shiki "^0.14.1"
|
||||
|
||||
typescript@^4.0.0:
|
||||
version "4.6.4"
|
||||
@@ -7334,15 +7339,15 @@ vm2@^3.9.17:
|
||||
acorn "^8.7.0"
|
||||
acorn-walk "^8.2.0"
|
||||
|
||||
vscode-oniguruma@^1.6.1:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz"
|
||||
integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==
|
||||
vscode-oniguruma@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b"
|
||||
integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==
|
||||
|
||||
vscode-textmate@5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz"
|
||||
integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==
|
||||
vscode-textmate@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz#2c7a3b1163ef0441097e0b5d6389cd5504b59e5d"
|
||||
integrity sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==
|
||||
|
||||
w3c-hr-time@^1.0.2:
|
||||
version "1.0.2"
|
||||
|
||||
Reference in New Issue
Block a user