StableBOT / lib /store.js
RamaZyx's picture
Upload folder using huggingface_hub
a2b2aac verified
import { readFileSync, writeFileSync, existsSync } from 'fs'
/**
* @type {import('@adiwajshing/baileys')}
*/
const { initAuthCreds, BufferJSON, proto } = (await import('@adiwajshing/baileys')).default
/**
* @param {import('@adiwajshing/baileys').WASocket | import('@adiwajshing/baileys').WALegacySocket}
*/
function bind(conn) {
if (!conn.chats) conn.chats = {}
/**
*
* @param {import('@adiwajshing/baileys').Contact[]|{contacts:import('@adiwajshing/baileys').Contact[]}} contacts
* @returns
*/
function updateNameToDb(contacts) {
if (!contacts) return
try {
contacts = contacts.contacts || contacts
for (const contact of contacts) {
const id = conn.decodeJid(contact.id)
if (!id || id === 'status@broadcast') continue
let chats = conn.chats[id]
if (!chats) chats = conn.chats[id] = { ...contact, id }
conn.chats[id] = {
...chats,
...({
...contact, id, ...(id.endsWith('@g.us') ?
{ subject: contact.subject || contact.name || chats.subject || '' } :
{ name: contact.notify || contact.name || chats.name || chats.notify || '' })
} || {})
}
}
} catch (e) {
console.error(e)
}
}
conn.ev.on('contacts.upsert', updateNameToDb)
conn.ev.on('groups.update', updateNameToDb)
conn.ev.on('contacts.set', updateNameToDb)
conn.ev.on('chats.set', async ({ chats }) => {
try {
for (let { id, name, readOnly } of chats) {
id = conn.decodeJid(id)
if (!id || id === 'status@broadcast') continue
const isGroup = id.endsWith('@g.us')
let chats = conn.chats[id]
if (!chats) chats = conn.chats[id] = { id }
chats.isChats = !readOnly
if (name) chats[isGroup ? 'subject' : 'name'] = name
if (isGroup) {
const metadata = await conn.groupMetadata(id).catch(_ => null)
if (name || metadata?.subject) chats.subject = name || metadata.subject
if (!metadata) continue
chats.metadata = metadata
}
}
} catch (e) {
console.error(e)
}
})
conn.ev.on('group-participants.update', async function updateParticipantsToDb({ id, participants, action }) {
if (!id) return
id = conn.decodeJid(id)
if (id === 'status@broadcast') return
if (!(id in conn.chats)) conn.chats[id] = { id }
let chats = conn.chats[id]
chats.isChats = true
const groupMetadata = await conn.groupMetadata(id).catch(_ => null)
if (!groupMetadata) return
chats.subject = groupMetadata.subject
chats.metadata = groupMetadata
})
conn.ev.on('groups.update', async function groupUpdatePushToDb(groupsUpdates) {
try {
for (const update of groupsUpdates) {
const id = conn.decodeJid(update.id)
if (!id || id === 'status@broadcast') continue
const isGroup = id.endsWith('@g.us')
if (!isGroup) continue
let chats = conn.chats[id]
if (!chats) chats = conn.chats[id] = { id }
chats.isChats = true
const metadata = await conn.groupMetadata(id).catch(_ => null)
if (metadata) chats.metadata = metadata
if (update.subject || metadata?.subject) chats.subject = update.subject || metadata.subject
}
} catch (e) {
console.error(e)
}
})
conn.ev.on('chats.upsert', function chatsUpsertPushToDb(chatsUpsert) {
try {
const { id, name } = chatsUpsert
if (!id || id === 'status@broadcast') return
conn.chats[id] = { ...(conn.chats[id] || {}), ...chatsUpsert, isChats: true }
const isGroup = id.endsWith('@g.us')
if (isGroup) conn.insertAllGroup().catch(_ => null)
} catch (e) {
console.error(e)
}
})
conn.ev.on('presence.update', async function presenceUpdatePushToDb({ id, presences }) {
try {
const sender = Object.keys(presences)[0] || id
const _sender = conn.decodeJid(sender)
const presence = presences[sender]['lastKnownPresence'] || 'composing'
let chats = conn.chats[_sender]
if (!chats) chats = conn.chats[_sender] = { id: sender }
chats.presences = presence
if (id.endsWith('@g.us')) {
let chats = conn.chats[id]
if (!chats) chats = conn.chats[id] = { id }
}
} catch (e) {
console.error(e)
}
})
}
const KEY_MAP = {
'pre-key': 'preKeys',
'session': 'sessions',
'sender-key': 'senderKeys',
'app-state-sync-key': 'appStateSyncKeys',
'app-state-sync-version': 'appStateVersions',
'sender-key-memory': 'senderKeyMemory'
}
/**
*
* @param {String} filename
* @param {import('pino').Logger} logger
* @returns
*/
function useSingleFileAuthState(filename, logger) {
let creds, keys = {}, saveCount = 0
// save the authentication state to a file
const saveState = (forceSave) => {
logger?.trace('saving auth state')
saveCount++
if (forceSave || saveCount > 5) {
writeFileSync(
filename,
// BufferJSON replacer utility saves buffers nicely
JSON.stringify({ creds, keys }, BufferJSON.replacer, 2)
)
saveCount = 0
}
}
if (existsSync(filename)) {
const result = JSON.parse(
readFileSync(filename, { encoding: 'utf-8' }),
BufferJSON.reviver
)
creds = result.creds
keys = result.keys
} else {
creds = initAuthCreds()
keys = {}
}
return {
state: {
creds,
keys: {
get: (type, ids) => {
const key = KEY_MAP[type]
return ids.reduce(
(dict, id) => {
let value = keys[key]?.[id]
if (value) {
if (type === 'app-state-sync-key') {
value = proto.AppStateSyncKeyData.fromObject(value)
}
dict[id] = value
}
return dict
}, {}
)
},
set: (data) => {
for (const _key in data) {
const key = KEY_MAP[_key]
keys[key] = keys[key] || {}
Object.assign(keys[key], data[_key])
}
saveState()
}
}
},
saveState
}
}
export default {
bind,
useSingleFileAuthState
}