mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
remove in-memory-store
This commit is contained in:
@@ -63,6 +63,8 @@ import makeWASocket, { WASocket, AuthenticationState, DisconnectReason, AnyMessa
|
|||||||
await delay(2000)
|
await delay(2000)
|
||||||
|
|
||||||
await sock.sendPresenceUpdate('paused', jid)
|
await sock.sendPresenceUpdate('paused', jid)
|
||||||
|
|
||||||
|
await sock.sendMessage(jid, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
sock = startSock()
|
sock = startSock()
|
||||||
|
|||||||
@@ -1,293 +0,0 @@
|
|||||||
import type KeyedDB from "@adiwajshing/keyed-db"
|
|
||||||
import type { Comparable } from "@adiwajshing/keyed-db/lib/Types"
|
|
||||||
import type { Logger } from "pino"
|
|
||||||
import type { Connection } from "../Socket"
|
|
||||||
import type { BaileysEventEmitter, Chat, ConnectionState, Contact, GroupMetadata, MessageInfo, PresenceData, WAMessage, WAMessageCursor, WAMessageKey } from "../Types"
|
|
||||||
import { toNumber } from "../Utils"
|
|
||||||
import makeOrderedDictionary from "./ordered-dictionary"
|
|
||||||
|
|
||||||
export const waChatKey = (pin: boolean) => ({
|
|
||||||
key: (c: Chat) => (pin ? (c.pin ? '1' : '0') : '') + (c.archive ? '0' : '1') + toNumber(c.conversationTimestamp).toString(16).padStart(8, '0') + c.id,
|
|
||||||
compare: (k1: string, k2: string) => k2.localeCompare (k1)
|
|
||||||
})
|
|
||||||
|
|
||||||
export const waMessageID = (m: WAMessage) => m.key.id
|
|
||||||
|
|
||||||
export type BaileysInMemoryStoreConfig = {
|
|
||||||
chatKey: Comparable<Chat, string>
|
|
||||||
logger: Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
const makeMessagesDictionary = () => makeOrderedDictionary(waMessageID)
|
|
||||||
|
|
||||||
export default(
|
|
||||||
{ logger, chatKey }: BaileysInMemoryStoreConfig
|
|
||||||
) => {
|
|
||||||
const KeyedDBConstructor = require('@adiwajshing/keyed-db').default as new (...args: any[]) => KeyedDB<Chat, string>
|
|
||||||
const chats = new KeyedDBConstructor(chatKey, c => c.jid)
|
|
||||||
const messages: { [_: string]: ReturnType<typeof makeMessagesDictionary> } = { }
|
|
||||||
const contacts: { [_: string]: Contact } = { }
|
|
||||||
const groupMetadata: { [_: string]: GroupMetadata } = { }
|
|
||||||
const messageInfos: { [id: string]: MessageInfo } = { }
|
|
||||||
const presences: { [id: string]: { [participant: string]: PresenceData } } = { }
|
|
||||||
const state: ConnectionState = { connection: 'close' }
|
|
||||||
|
|
||||||
const assertMessageList = (jid: string) => {
|
|
||||||
if(!messages[jid]) messages[jid] = makeMessagesDictionary()
|
|
||||||
return messages[jid]
|
|
||||||
}
|
|
||||||
|
|
||||||
const listen = (ev: BaileysEventEmitter) => {
|
|
||||||
|
|
||||||
const contactsUpsert = (newContacts: Contact[]) => {
|
|
||||||
const oldContacts = new Set(Object.keys(contacts))
|
|
||||||
for(const contact of newContacts) {
|
|
||||||
oldContacts.delete(contact.jid)
|
|
||||||
contacts[contact.jid] = Object.assign(
|
|
||||||
contacts[contact.jid] || {},
|
|
||||||
contact
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return oldContacts
|
|
||||||
}
|
|
||||||
|
|
||||||
ev.on('connection.update', update => {
|
|
||||||
Object.assign(state, update)
|
|
||||||
})
|
|
||||||
ev.on('contacts.set', ({ contacts: newContacts }) => {
|
|
||||||
const oldContacts = contactsUpsert(newContacts)
|
|
||||||
for(const jid of oldContacts) {
|
|
||||||
delete contacts[jid]
|
|
||||||
}
|
|
||||||
logger.debug({ deletedContacts: oldContacts.size }, 'synced contacts')
|
|
||||||
})
|
|
||||||
ev.on('contacts.update', updates => {
|
|
||||||
for(const update of updates) {
|
|
||||||
if(contacts[update.jid!]) {
|
|
||||||
Object.assign(contacts[update.jid!], update)
|
|
||||||
} else {
|
|
||||||
logger.debug({ update }, `got update for non-existant contact`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ev.on('chats.upsert', newChats => {
|
|
||||||
chats.upsert(...newChats)
|
|
||||||
})
|
|
||||||
ev.on('chats.set', ({ chats: newChats }) => {
|
|
||||||
chats.upsert(...newChats)
|
|
||||||
})
|
|
||||||
ev.on('chats.update', updates => {
|
|
||||||
for(const update of updates) {
|
|
||||||
const result = chats.update(update.jid!, chat => {
|
|
||||||
Object.assign(chat, update)
|
|
||||||
})
|
|
||||||
if(!result) {
|
|
||||||
logger.debug({ update }, `got update for non-existant chat`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ev.on('presence.update', ({ jid, presences: update }) => {
|
|
||||||
presences[jid] = presences[jid] || {}
|
|
||||||
Object.assign(presences[jid], update)
|
|
||||||
})
|
|
||||||
ev.on('chats.delete', deletions => {
|
|
||||||
for(const item of deletions) {
|
|
||||||
chats.deleteById(item)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ev.on('messages.upsert', ({ messages: newMessages, type }) => {
|
|
||||||
switch(type) {
|
|
||||||
case 'append':
|
|
||||||
case 'notify':
|
|
||||||
for(const msg of newMessages) {
|
|
||||||
const jid = msg.key.remoteJid!
|
|
||||||
const list = assertMessageList(jid)
|
|
||||||
list.upsert(msg, 'append')
|
|
||||||
|
|
||||||
if(type === 'notify') {
|
|
||||||
if(!chats.get(jid)) {
|
|
||||||
ev.emit('chats.upsert', [
|
|
||||||
{ jid, t: toNumber(msg.messageTimestamp), count: 1 }
|
|
||||||
])
|
|
||||||
}
|
|
||||||
// add message infos if required
|
|
||||||
messageInfos[msg.key.id!] = messageInfos[msg.key.id!] || { reads: {}, deliveries: {} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'last':
|
|
||||||
logger.info('recv last message on all chats')
|
|
||||||
for(const msg of newMessages) {
|
|
||||||
const jid = msg.key.remoteJid!
|
|
||||||
const list = assertMessageList(jid)
|
|
||||||
const [lastItem] = list.array.slice(-1)
|
|
||||||
// reset message list
|
|
||||||
if(lastItem?.key.id !== msg.key.id) {
|
|
||||||
list.clear()
|
|
||||||
list.upsert(msg, 'append')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'prepend':
|
|
||||||
for(const msg of newMessages) {
|
|
||||||
const jid = msg.key.remoteJid!
|
|
||||||
const list = assertMessageList(jid)
|
|
||||||
list.upsert(msg, 'prepend')
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ev.on('messages.update', updates => {
|
|
||||||
for(const { update, key } of updates) {
|
|
||||||
const list = assertMessageList(key.remoteJid)
|
|
||||||
const result = list.updateAssign(key.id, update)
|
|
||||||
if(!result) {
|
|
||||||
logger.debug({ update }, `got update for non-existent message`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ev.on('messages.delete', item => {
|
|
||||||
const list = assertMessageList(item.jid)
|
|
||||||
if('all' in item) {
|
|
||||||
list.clear()
|
|
||||||
} else {
|
|
||||||
const idSet = new Set(item.ids)
|
|
||||||
list.filter(m => !idSet.has(m.key.id))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ev.on('groups.update', updates => {
|
|
||||||
for(const update of updates) {
|
|
||||||
if(groupMetadata[update.id]) {
|
|
||||||
Object.assign(groupMetadata[update.id!], update)
|
|
||||||
} else {
|
|
||||||
logger.debug({ update }, `got update for non-existant group metadata`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ev.on('group-participants.update', ({ jid, participants, action }) => {
|
|
||||||
const metadata = groupMetadata[jid]
|
|
||||||
if(metadata) {
|
|
||||||
switch(action) {
|
|
||||||
case 'add':
|
|
||||||
metadata.participants.push(...participants.map(jid => ({ jid, isAdmin: false, isSuperAdmin: false })))
|
|
||||||
break
|
|
||||||
case 'demote':
|
|
||||||
case 'promote':
|
|
||||||
for(const participant of metadata.participants) {
|
|
||||||
if(participants.includes(participant.jid)) {
|
|
||||||
participant.isAdmin = action === 'promote'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'remove':
|
|
||||||
metadata.participants = metadata.participants.filter(p => !participants.includes(p.jid))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
ev.on('message-info.update', updates => {
|
|
||||||
for(const { key, update } of updates) {
|
|
||||||
const obj = messageInfos[key.id!]
|
|
||||||
if(obj) {
|
|
||||||
// add reads/deliveries
|
|
||||||
for(const key in update) {
|
|
||||||
Object.assign(obj[key], update[key])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return {
|
|
||||||
chats,
|
|
||||||
contacts,
|
|
||||||
messages,
|
|
||||||
groupMetadata,
|
|
||||||
messageInfos,
|
|
||||||
state,
|
|
||||||
presences,
|
|
||||||
listen,
|
|
||||||
/*loadMessages: async(jid: string, count: number, cursor: WAMessageCursor, sock: Connection | undefined) => {
|
|
||||||
const list = assertMessageList(jid)
|
|
||||||
const retrieve = async(count: number, cursor: WAMessageCursor) => {
|
|
||||||
const result = await sock?.fetchMessagesFromWA(jid, count, cursor)
|
|
||||||
return result || []
|
|
||||||
}
|
|
||||||
const mode = !cursor || 'before' in cursor ? 'before' : 'after'
|
|
||||||
const cursorKey = !!cursor ? ('before' in cursor ? cursor.before : cursor.after) : undefined
|
|
||||||
const cursorValue = cursorKey ? list.get(cursorKey.id) : undefined
|
|
||||||
|
|
||||||
let messages: WAMessage[]
|
|
||||||
if(list && mode === 'before' && (!cursorKey || cursorValue)) {
|
|
||||||
if(cursorValue) {
|
|
||||||
const msgIdx = list.array.findIndex(m => m.key.id === cursorKey.id)
|
|
||||||
messages = list.array.slice(0, msgIdx)
|
|
||||||
} else {
|
|
||||||
messages = list.array
|
|
||||||
}
|
|
||||||
const diff = count - messages.length
|
|
||||||
if (diff < 0) {
|
|
||||||
messages = messages.slice(-count) // get the last X messages
|
|
||||||
} else if (diff > 0) {
|
|
||||||
const [fMessage] = messages
|
|
||||||
const cursor = { before: fMessage?.key || cursorKey }
|
|
||||||
const extra = await retrieve (diff, cursor)
|
|
||||||
// add to DB
|
|
||||||
for(let i = extra.length-1; i >= 0;i--) {
|
|
||||||
list.upsert(extra[i], 'prepend')
|
|
||||||
}
|
|
||||||
messages.splice(0, 0, ...extra)
|
|
||||||
}
|
|
||||||
} else messages = await retrieve(count, cursor)
|
|
||||||
|
|
||||||
return messages
|
|
||||||
},
|
|
||||||
loadMessage: async(jid: string, id: string, sock: Connection | undefined) => {
|
|
||||||
let message = messages[jid]?.get(id)
|
|
||||||
if(!message) {
|
|
||||||
message = await sock?.loadMessageFromWA(jid, id)
|
|
||||||
}
|
|
||||||
return message
|
|
||||||
},
|
|
||||||
mostRecentMessage: async(jid: string, sock: Connection | undefined) => {
|
|
||||||
let message = messages[jid]?.array.slice(-1)[0]
|
|
||||||
if(!message) {
|
|
||||||
const [result] = await sock?.fetchMessagesFromWA(jid, 1, undefined)
|
|
||||||
message = result
|
|
||||||
}
|
|
||||||
return message
|
|
||||||
},
|
|
||||||
fetchImageUrl: async(jid: string, sock: Connection | undefined) => {
|
|
||||||
const contact = contacts[jid]
|
|
||||||
if(!contact) {
|
|
||||||
return sock?.fetchImageUrl(jid)
|
|
||||||
}
|
|
||||||
if(typeof contact.imgUrl === 'undefined') {
|
|
||||||
contact.imgUrl = await sock?.fetchImageUrl(jid)
|
|
||||||
}
|
|
||||||
return contact.imgUrl
|
|
||||||
},
|
|
||||||
fetchGroupMetadata: async(jid: string, sock: Connection | undefined) => {
|
|
||||||
if(!groupMetadata[jid]) {
|
|
||||||
groupMetadata[jid] = await sock?.groupMetadata(jid, chats.get(jid)?.read_only === 'true')
|
|
||||||
}
|
|
||||||
return groupMetadata[jid]
|
|
||||||
},
|
|
||||||
fetchBroadcastListInfo: async(jid: string, sock: Connection | undefined) => {
|
|
||||||
if(!groupMetadata[jid]) {
|
|
||||||
groupMetadata[jid] = await sock?.getBroadcastListInfo(jid)
|
|
||||||
}
|
|
||||||
return groupMetadata[jid]
|
|
||||||
},
|
|
||||||
fetchMessageInfo: async({remoteJid, id}: WAMessageKey, sock: Connection | undefined) => {
|
|
||||||
if(!messageInfos[id!]) {
|
|
||||||
messageInfos[id!] = await sock?.messageInfo(remoteJid, id)
|
|
||||||
}
|
|
||||||
return messageInfos[id!]
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
import makeInMemoryStore from './in-memory-store'
|
|
||||||
export { makeInMemoryStore }
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
|
|
||||||
const makeOrderedDictionary = function<T>(idGetter: (item: T) => string) {
|
|
||||||
const array: T[] = []
|
|
||||||
const dict: { [_: string]: T } = { }
|
|
||||||
|
|
||||||
const get = (id: string) => dict[id]
|
|
||||||
|
|
||||||
const update = (item: T) => {
|
|
||||||
const id = idGetter(item)
|
|
||||||
const idx = array.findIndex(i => idGetter(i) === id)
|
|
||||||
if(idx >= 0) {
|
|
||||||
array[idx] = item
|
|
||||||
dict[id] = item
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
const upsert = (item: T, mode: 'append' | 'prepend') => {
|
|
||||||
const id = idGetter(item)
|
|
||||||
if(get(id)) {
|
|
||||||
update(item)
|
|
||||||
} else {
|
|
||||||
if(mode === 'append') {
|
|
||||||
array.push(item)
|
|
||||||
} else {
|
|
||||||
array.splice(0, 0, item)
|
|
||||||
}
|
|
||||||
dict[id] = item
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const remove = (item: T) => {
|
|
||||||
const id = idGetter(item)
|
|
||||||
const idx = array.findIndex(i => idGetter(i) === id)
|
|
||||||
if(idx >= 0) {
|
|
||||||
array.splice(idx, 1)
|
|
||||||
delete dict[id]
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
array,
|
|
||||||
get,
|
|
||||||
upsert,
|
|
||||||
update,
|
|
||||||
remove,
|
|
||||||
updateAssign: (id: string, update: Partial<T>) => {
|
|
||||||
const item = get(id)
|
|
||||||
if(item) {
|
|
||||||
Object.assign(item, update)
|
|
||||||
delete dict[id]
|
|
||||||
dict[idGetter(item)] = item
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
clear: () => {
|
|
||||||
array.splice(0, array.length)
|
|
||||||
Object.keys(dict).forEach(key => { delete dict[key] })
|
|
||||||
},
|
|
||||||
filter: (contain: (item: T) => boolean) => {
|
|
||||||
let i = 0
|
|
||||||
while(i < array.length) {
|
|
||||||
if(!contain(array[i])) {
|
|
||||||
delete dict[idGetter(array[i])]
|
|
||||||
array.splice(i, 1)
|
|
||||||
} else {
|
|
||||||
i += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default makeOrderedDictionary
|
|
||||||
//export type OrderedDictionary<T> = ReturnType<typeof makeOrderedDictionary>
|
|
||||||
Reference in New Issue
Block a user