From 21f8431e61f842e4294b8458b2bdc2355e605c16 Mon Sep 17 00:00:00 2001 From: "contato.mateusfr@gmail.com" <47920083+MateusFrFreitas@users.noreply.github.com> Date: Sat, 1 Mar 2025 13:30:51 -0300 Subject: [PATCH] Dependency Inversion for Logger (#1153) * feat: interface "ILogger" created feat: interface "ILogger" used instead of pino logger feat: "PinoLoggerAdapter" created to implement "ILogger" interface * feat: PinoLoggerAdapter removed feat: ILogger mapping the features we're using from pino * fix: sort imports --------- Co-authored-by: Mateus Franchini de Freitas Co-authored-by: Mateus Franchini de Freitas Co-authored-by: Rajeh Taher --- src/Socket/messages-recv.ts | 6 +++--- src/Store/make-in-memory-store.ts | 6 +++--- src/Types/Message.ts | 4 ++-- src/Types/Socket.ts | 6 +++--- src/Utils/auth-utils.ts | 5 +++-- src/Utils/chat-utils.ts | 6 +++--- src/Utils/decode-wa-message.ts | 4 ++-- src/Utils/event-buffer.ts | 6 +++--- src/Utils/generics.ts | 4 ++-- src/Utils/link-preview.ts | 4 ++-- src/Utils/logger.ts | 12 +++++++++++- src/Utils/messages-media.ts | 8 ++++---- src/Utils/messages.ts | 4 ++-- src/Utils/noise-handler.ts | 4 ++-- src/Utils/process-message.ts | 4 ++-- 15 files changed, 47 insertions(+), 36 deletions(-) diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index 5e11416db2d..7a348d4da7b 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -866,7 +866,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } if(placeholderResendCache.get(messageKey?.id!)) { - logger.debug('already requested resend', { messageKey }) + logger.debug({ messageKey }, 'already requested resend') return } else { placeholderResendCache.set(messageKey?.id!, true) @@ -875,7 +875,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { await delay(5000) if(!placeholderResendCache.get(messageKey?.id!)) { - logger.debug('message received while resend requested', { messageKey }) + logger.debug({ messageKey }, 'message received while resend requested') return 'RESOLVED' } @@ -888,7 +888,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { setTimeout(() => { if(placeholderResendCache.get(messageKey?.id!)) { - logger.debug('PDO message without response after 15 seconds. Phone possibly offline', { messageKey }) + logger.debug({ messageKey }, 'PDO message without response after 15 seconds. Phone possibly offline') placeholderResendCache.del(messageKey?.id!) } }, 15_000) diff --git a/src/Store/make-in-memory-store.ts b/src/Store/make-in-memory-store.ts index aeacc8cb05a..83492f714bc 100644 --- a/src/Store/make-in-memory-store.ts +++ b/src/Store/make-in-memory-store.ts @@ -1,6 +1,5 @@ import type 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' @@ -8,6 +7,7 @@ import type { BaileysEventEmitter, Chat, ConnectionState, Contact, GroupMetadata import { Label } from '../Types/Label' import { LabelAssociation, LabelAssociationType, MessageLabelAssociation } from '../Types/LabelAssociation' import { md5, toNumber, updateMessageWithReaction, updateMessageWithReceipt } from '../Utils' +import { ILogger } from '../Utils/logger' import { jidDecode, jidNormalizedUser } from '../WABinary' import makeOrderedDictionary from './make-ordered-dictionary' import { ObjectRepository } from './object-repository' @@ -29,7 +29,7 @@ export const waLabelAssociationKey: Comparable = { export type BaileysInMemoryStoreConfig = { chatKey?: Comparable labelAssociationKey?: Comparable - logger?: Logger + logger?: ILogger socket?: WASocket } @@ -39,7 +39,7 @@ export default (config: BaileysInMemoryStoreConfig) => { const socket = config.socket const chatKey = config.chatKey || waChatKey(true) const labelAssociationKey = config.labelAssociationKey || waLabelAssociationKey - const logger: Logger = config.logger || DEFAULT_CONNECTION_CONFIG.logger.child({ stream: 'in-mem-store' }) + const logger: ILogger = config.logger || DEFAULT_CONNECTION_CONFIG.logger.child({ stream: 'in-mem-store' }) const KeyedDB = require('@adiwajshing/keyed-db').default const chats = new KeyedDB(chatKey, c => c.id) as KeyedDB diff --git a/src/Types/Message.ts b/src/Types/Message.ts index 5577c3ee553..899615a2ad7 100644 --- a/src/Types/Message.ts +++ b/src/Types/Message.ts @@ -1,5 +1,4 @@ import { AxiosRequestConfig } from 'axios' -import type { Logger } from 'pino' import type { Readable } from 'stream' import type { URL } from 'url' import { proto } from '../../WAProto' @@ -23,6 +22,7 @@ export type WAGenericMediaMessage = proto.Message.IVideoMessage | proto.Message. export import WAMessageStubType = proto.WebMessageInfo.StubType // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars export import WAMessageStatus = proto.WebMessageInfo.Status +import { ILogger } from '../Utils/logger' export type WAMediaPayloadURL = { url: URL | string } export type WAMediaPayloadStream = { stream: Readable } export type WAMediaUpload = Buffer | WAMediaPayloadStream | WAMediaPayloadURL @@ -241,7 +241,7 @@ export type MessageGenerationOptionsFromContent = MiscMessageGenerationOptions & export type WAMediaUploadFunction = (readStream: Readable, opts: { fileEncSha256B64: string, mediaType: MediaType, timeoutMs?: number }) => Promise<{ mediaUrl: string, directPath: string }> export type MediaGenerationOptions = { - logger?: Logger + logger?: ILogger mediaTypeOverride?: MediaType upload: WAMediaUploadFunction /** cache media so it does not have to be uploaded again */ diff --git a/src/Types/Socket.ts b/src/Types/Socket.ts index 0237f2bb04d..79fd83dae87 100644 --- a/src/Types/Socket.ts +++ b/src/Types/Socket.ts @@ -1,9 +1,9 @@ import { AxiosRequestConfig } from 'axios' import type { Agent } from 'https' -import type { Logger } from 'pino' import type { URL } from 'url' import { proto } from '../../WAProto' +import { ILogger } from '../Utils/logger' import { AuthenticationState, SignalAuthState, TransactionCapabilityOptions } from './Auth' import { GroupMetadata } from './GroupMetadata' import { MediaConnInfo } from './Message' @@ -38,8 +38,8 @@ export type SocketConfig = { mobile?: boolean /** proxy agent */ agent?: Agent - /** pino logger */ - logger: Logger + /** logger */ + logger: ILogger /** version to connect with */ version: WAVersion /** override browser config */ diff --git a/src/Utils/auth-utils.ts b/src/Utils/auth-utils.ts index f758eb7cb13..4d74947b5e5 100644 --- a/src/Utils/auth-utils.ts +++ b/src/Utils/auth-utils.ts @@ -5,6 +5,7 @@ import { DEFAULT_CACHE_TTLS } from '../Defaults' import type { AuthenticationCreds, CacheStore, SignalDataSet, SignalDataTypeMap, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types' import { Curve, signedKeyPair } from './crypto' import { delay, generateRegistrationId } from './generics' +import { ILogger } from './logger' /** * Adds caching capability to a SignalKeyStore @@ -14,7 +15,7 @@ import { delay, generateRegistrationId } from './generics' */ export function makeCacheableSignalKeyStore( store: SignalKeyStore, - logger: Logger, + logger: ILogger, _cache?: CacheStore ): SignalKeyStore { const cache = _cache || new NodeCache({ @@ -83,7 +84,7 @@ export function makeCacheableSignalKeyStore( */ export const addTransactionCapability = ( state: SignalKeyStore, - logger: Logger, + logger: ILogger, { maxCommitRetries, delayBetweenTriesMs }: TransactionCapabilityOptions ): SignalKeyStoreWithTransaction => { // number of queries made to the DB during the transaction diff --git a/src/Utils/chat-utils.ts b/src/Utils/chat-utils.ts index 9b56f868568..dd89bfffc19 100644 --- a/src/Utils/chat-utils.ts +++ b/src/Utils/chat-utils.ts @@ -1,12 +1,12 @@ import { Boom } from '@hapi/boom' 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' +import { ILogger } from './logger' import { LT_HASH_ANTI_TAMPERING } from './lt-hash' import { downloadContentFromMessage, } from './messages-media' @@ -410,7 +410,7 @@ export const decodePatches = async( getAppStateSyncKey: FetchAppStateSyncKey, options: AxiosRequestConfig<{}>, minimumVersionNumber?: number, - logger?: Logger, + logger?: ILogger, validateMacs = true ) => { const newState: LTHashState = { @@ -716,7 +716,7 @@ export const processSyncAction = ( ev: BaileysEventEmitter, me: Contact, initialSyncOpts?: InitialAppStateSyncOptions, - logger?: Logger, + logger?: ILogger, ) => { const isInitialSync = !!initialSyncOpts const accountSettings = initialSyncOpts?.accountSettings diff --git a/src/Utils/decode-wa-message.ts b/src/Utils/decode-wa-message.ts index d8c0d868793..25e6f171502 100644 --- a/src/Utils/decode-wa-message.ts +++ b/src/Utils/decode-wa-message.ts @@ -1,9 +1,9 @@ import { Boom } from '@hapi/boom' -import { Logger } from 'pino' import { proto } from '../../WAProto' import { SignalRepository, WAMessageKey } from '../Types' import { areJidsSameUser, BinaryNode, isJidBroadcast, isJidGroup, isJidNewsletter, isJidStatusBroadcast, isJidUser, isLidUser } from '../WABinary' import { unpadRandomMax16 } from './generics' +import { ILogger } from './logger' export const NO_MESSAGE_FOUND_ERROR_TEXT = 'Message absent from node' export const MISSING_KEYS_ERROR_TEXT = 'Key used already or never filled' @@ -136,7 +136,7 @@ export const decryptMessageNode = ( meId: string, meLid: string, repository: SignalRepository, - logger: Logger + logger: ILogger ) => { const { fullMessage, author, sender } = decodeMessageNode(stanza, meId, meLid) return { diff --git a/src/Utils/event-buffer.ts b/src/Utils/event-buffer.ts index 879ae50e699..bddad0a74db 100644 --- a/src/Utils/event-buffer.ts +++ b/src/Utils/event-buffer.ts @@ -1,8 +1,8 @@ import EventEmitter from 'events' -import { Logger } from 'pino' import { proto } from '../../WAProto' import { BaileysEvent, BaileysEventEmitter, BaileysEventMap, BufferedEventData, Chat, ChatUpdate, Contact, WAMessage, WAMessageStatus } from '../Types' import { trimUndefined } from './generics' +import { ILogger } from './logger' import { updateMessageWithReaction, updateMessageWithReceipt } from './messages' import { isRealMessage, shouldIncrementChatUnread } from './process-message' @@ -59,7 +59,7 @@ type BaileysBufferableEventEmitter = BaileysEventEmitter & { * making the data processing more efficient. * @param ev the baileys event emitter */ -export const makeEventBuffer = (logger: Logger): BaileysBufferableEventEmitter => { +export const makeEventBuffer = (logger: ILogger): BaileysBufferableEventEmitter => { const ev = new EventEmitter() const historyCache = new Set() @@ -190,7 +190,7 @@ function append( event: E, // eslint-disable-next-line @typescript-eslint/no-explicit-any eventData: any, - logger: Logger + logger: ILogger ) { switch (event) { case 'messaging-history.set': diff --git a/src/Utils/generics.ts b/src/Utils/generics.ts index 8f735e0e46f..6e2288dfb67 100644 --- a/src/Utils/generics.ts +++ b/src/Utils/generics.ts @@ -2,11 +2,11 @@ import { Boom } from '@hapi/boom' import axios, { AxiosRequestConfig } from 'axios' import { createHash, randomBytes } from 'crypto' import { platform, release } from 'os' -import { Logger } from 'pino' import { proto } from '../../WAProto' import { version as baileysVersion } from '../Defaults/baileys-version.json' import { BaileysEventEmitter, BaileysEventMap, BrowsersMap, ConnectionState, DisconnectReason, WACallUpdateType, WAVersion } from '../Types' import { BinaryNode, getAllBinaryNodeChildren, jidDecode } from '../WABinary' +import { ILogger } from './logger' const PLATFORM_MAP = { 'aix': 'AIX', @@ -242,7 +242,7 @@ export function bindWaitForEvent(ev: BaileysEve export const bindWaitForConnectionUpdate = (ev: BaileysEventEmitter) => bindWaitForEvent(ev, 'connection.update') -export const printQRIfNecessaryListener = (ev: BaileysEventEmitter, logger: Logger) => { +export const printQRIfNecessaryListener = (ev: BaileysEventEmitter, logger: ILogger) => { ev.on('connection.update', async({ qr }) => { if(qr) { const QR = await import('qrcode-terminal') diff --git a/src/Utils/link-preview.ts b/src/Utils/link-preview.ts index 702feb105b7..26051302cf0 100644 --- a/src/Utils/link-preview.ts +++ b/src/Utils/link-preview.ts @@ -1,6 +1,6 @@ import { AxiosRequestConfig } from 'axios' -import { Logger } from 'pino' import { WAMediaUploadFunction, WAUrlInfo } from '../Types' +import { ILogger } from './logger' import { prepareWAMessageMedia } from './messages' import { extractImageThumb, getHttpStream } from './messages-media' @@ -25,7 +25,7 @@ export type URLGenerationOptions = { headers?: AxiosRequestConfig<{}>['headers'] } uploadImage?: WAMediaUploadFunction - logger?: Logger + logger?: ILogger } /** diff --git a/src/Utils/logger.ts b/src/Utils/logger.ts index bb651e3276a..a5274226aa4 100644 --- a/src/Utils/logger.ts +++ b/src/Utils/logger.ts @@ -1,3 +1,13 @@ import P from 'pino' -export default P({ timestamp: () => `,"time":"${new Date().toJSON()}"` }) \ No newline at end of file +export interface ILogger { + level: string + child(obj: Record): ILogger + trace(obj: unknown, msg?: string) + debug(obj: unknown, msg?: string) + info(obj: unknown, msg?: string) + warn(obj: unknown, msg?: string) + error(obj: unknown, msg?: string) +} + +export default P({ timestamp: () => `,"time":"${new Date().toJSON()}"` }) diff --git a/src/Utils/messages-media.ts b/src/Utils/messages-media.ts index 1a4bbfad82b..b2b11337025 100644 --- a/src/Utils/messages-media.ts +++ b/src/Utils/messages-media.ts @@ -7,7 +7,6 @@ import { createReadStream, createWriteStream, promises as fs, WriteStream } from import type { IAudioMetadata } from 'music-metadata' import { tmpdir } from 'os' import { join } from 'path' -import type { Logger } from 'pino' import { Readable, Transform } from 'stream' import { URL } from 'url' import { proto } from '../../WAProto' @@ -16,6 +15,7 @@ import { BaileysEventMap, DownloadableMessage, MediaConnInfo, MediaDecryptionKey import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, jidNormalizedUser } from '../WABinary' import { aesDecryptGCM, aesEncryptGCM, hkdf } from './crypto' import { generateMessageID } from './generics' +import { ILogger } from './logger' const getTmpFilesDirectory = () => tmpdir() @@ -207,7 +207,7 @@ export async function getAudioDuration(buffer: Buffer | string | Readable) { /** referenced from and modifying https://github.com/wppconnect-team/wa-js/blob/main/src/chat/functions/prepareAudioWaveform.ts */ -export async function getAudioWaveform(buffer: Buffer | string | Readable, logger?: Logger) { +export async function getAudioWaveform(buffer: Buffer | string | Readable, logger?: ILogger) { try { const { default: decoder } = await eval('import(\'audio-decode\')') let audioData: Buffer @@ -290,7 +290,7 @@ export async function generateThumbnail( file: string, mediaType: 'video' | 'image', options: { - logger?: Logger + logger?: ILogger } ) { let thumbnail: string | undefined @@ -330,7 +330,7 @@ export const getHttpStream = async(url: string | URL, options: AxiosRequestConfi type EncryptedStreamOptions = { saveOriginalFileIfRequired?: boolean - logger?: Logger + logger?: ILogger opts?: AxiosRequestConfig } diff --git a/src/Utils/messages.ts b/src/Utils/messages.ts index 1d771f8134d..61c2d2308ba 100644 --- a/src/Utils/messages.ts +++ b/src/Utils/messages.ts @@ -2,7 +2,6 @@ import { Boom } from '@hapi/boom' import axios from 'axios' import { randomBytes } from 'crypto' import { promises as fs } from 'fs' -import { Logger } from 'pino' import { type Transform } from 'stream' import { proto } from '../../WAProto' import { MEDIA_KEYS, URL_REGEX, WA_DEFAULT_EPHEMERAL } from '../Defaults' @@ -27,6 +26,7 @@ import { import { isJidGroup, isJidStatusBroadcast, jidNormalizedUser } from '../WABinary' import { sha256 } from './crypto' import { generateMessageID, getKeyAuthor, unixTimestampSeconds } from './generics' +import { ILogger } from './logger' import { downloadContentFromMessage, encryptedStream, generateThumbnail, getAudioDuration, getAudioWaveform, MediaDownloadOptions } from './messages-media' type MediaUploadData = { @@ -847,7 +847,7 @@ export const aggregateMessageKeysNotFromMe = (keys: proto.IMessageKey[]) => { type DownloadMediaMessageContext = { reuploadRequest: (msg: WAMessage) => Promise - logger: Logger + logger: ILogger } const REUPLOAD_REQUIRED_STATUS = [410, 404] diff --git a/src/Utils/noise-handler.ts b/src/Utils/noise-handler.ts index 9ea89ec30d7..15096bbb3a2 100644 --- a/src/Utils/noise-handler.ts +++ b/src/Utils/noise-handler.ts @@ -1,10 +1,10 @@ import { Boom } from '@hapi/boom' -import { Logger } from 'pino' import { proto } from '../../WAProto' import { NOISE_MODE, WA_CERT_DETAILS } from '../Defaults' import { KeyPair } from '../Types' import { BinaryNode, decodeBinaryNode } from '../WABinary' import { aesDecryptGCM, aesEncryptGCM, Curve, hkdf, sha256 } from './crypto' +import { ILogger } from './logger' const generateIV = (counter: number) => { const iv = new ArrayBuffer(12) @@ -21,7 +21,7 @@ export const makeNoiseHandler = ({ }: { keyPair: KeyPair NOISE_HEADER: Uint8Array - logger: Logger + logger: ILogger routingInfo?: Buffer | undefined }) => { logger = logger.child({ class: 'ns' }) diff --git a/src/Utils/process-message.ts b/src/Utils/process-message.ts index 09b173aa7e5..6e47a368563 100644 --- a/src/Utils/process-message.ts +++ b/src/Utils/process-message.ts @@ -1,5 +1,4 @@ import { AxiosRequestConfig } from 'axios' -import type { Logger } from 'pino' import { proto } from '../../WAProto' import { AuthenticationCreds, BaileysEventEmitter, CacheStore, Chat, GroupMetadata, ParticipantAction, RequestJoinAction, RequestJoinMethod, SignalKeyStoreWithTransaction, SocketConfig, WAMessageStubType } from '../Types' import { getContentType, normalizeMessageContent } from '../Utils/messages' @@ -7,6 +6,7 @@ import { areJidsSameUser, isJidBroadcast, isJidStatusBroadcast, jidNormalizedUse import { aesDecryptGCM, hmacSign } from './crypto' import { getKeyAuthor, toNumber } from './generics' import { downloadAndProcessHistorySyncNotification } from './history' +import { ILogger } from './logger' type ProcessMessageContext = { shouldProcessHistoryMsg: boolean @@ -15,7 +15,7 @@ type ProcessMessageContext = { keyStore: SignalKeyStoreWithTransaction ev: BaileysEventEmitter getMessage: SocketConfig['getMessage'] - logger?: Logger + logger?: ILogger options: AxiosRequestConfig<{}> }