Skip to content

Commit d74b8bc

Browse files
committed
🐛 ensure md data dir is deleted when deleteSessionDataOnLogout is true #2943
1 parent a79e6b9 commit d74b8bc

File tree

4 files changed

+61
-30
lines changed

4 files changed

+61
-30
lines changed

src/api/Client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ export class Client {
369369
await this._queues?.onLogout?.onEmpty();
370370
await this._queues?.onLogout?.onIdle();
371371
await invalidateSesssionData(this._createConfig)
372-
if(this._createConfig?.deleteSessionDataOnLogout) deleteSessionData(this._createConfig)
372+
if(this._createConfig?.deleteSessionDataOnLogout) await deleteSessionData(this._createConfig)
373373
if(this._createConfig?.killClientOnLogout) {
374374
console.log("Session logged out. Killing client")
375375
log.warn("Session logged out. Killing client")

src/controllers/browser.ts

Lines changed: 25 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import * as path from 'path';
2-
import * as fs from 'fs';
2+
import * as fs from 'fs/promises';
33
import ON_DEATH from 'death';
44
// import puppeteer from 'puppeteer-extra';
55
import { puppeteerConfig, useragent, width, height} from '../config/puppeteer.config';
6-
import { Browser, CDPSession, Page } from 'puppeteer';
6+
import { Browser, Page } from 'puppeteer';
77
import { Spin, EvEmitter } from './events';
88
import { ConfigObject } from '../api/model';
99
import { FileNotFoundError, getTextFile } from 'pico-s3';
1010
// eslint-disable-next-line @typescript-eslint/no-var-requires
1111
const puppeteer = require('puppeteer-extra')
1212
import terminate from 'terminate/promise';
1313
import { log } from '../logging/logging';
14-
import { now, processSendData, timeout, timePromise } from '../utils/tools';
14+
import { now, pathExists, processSendData, timeout, timePromise } from '../utils/tools';
1515
import { QRManager } from './auth';
1616
import { scriptLoader } from './script_preloader';
1717
import { earlyInjectionCheck } from './patch_manager';
@@ -155,7 +155,7 @@ export async function initPage(sessionId?: string, config?:ConfigObject, qrManag
155155
* AUTH
156156
*/
157157
spinner?.info('Loading session data')
158-
let sessionjson : any = getSessionDataFromFile(sessionId, config, spinner)
158+
let sessionjson : any = await getSessionDataFromFile(sessionId, config, spinner)
159159
if(!sessionjson && sessionjson !== "" && config.sessionDataBucketAuth) {
160160
try {
161161
spinner?.info('Unable to find session data file locally, attempting to find session data in cloud storage..')
@@ -227,16 +227,16 @@ export async function initPage(sessionId?: string, config?:ConfigObject, qrManag
227227
return waPage;
228228
}
229229

230-
const getSessionDataFromFile = (sessionId: string, config: ConfigObject, spinner ?: Spin) => {
230+
const getSessionDataFromFile = async (sessionId: string, config: ConfigObject, spinner ?: Spin) => {
231231
if(config?.sessionData == "NUKE") return ''
232232
//check if [session].json exists in __dirname
233-
const sessionjsonpath = getSessionDataFilePath(sessionId,config)
233+
const sessionjsonpath = await getSessionDataFilePath(sessionId,config)
234234
let sessionjson = '';
235235
const sd = process.env[`${sessionId.toUpperCase()}_DATA_JSON`] ? JSON.parse(process.env[`${sessionId.toUpperCase()}_DATA_JSON`]) : config?.sessionData;
236236
sessionjson = (typeof sd === 'string' && sd !== "") ? JSON.parse(Buffer.from(sd, 'base64').toString('ascii')) : sd;
237-
if (sessionjsonpath && typeof sessionjsonpath == 'string' && fs.existsSync(sessionjsonpath)) {
237+
if (sessionjsonpath && typeof sessionjsonpath == 'string' && await pathExists(sessionjsonpath)) {
238238
spinner.succeed(`Found session data file: ${sessionjsonpath}`)
239-
const s = fs.readFileSync(sessionjsonpath, "utf8");
239+
const s = await fs.readFile(sessionjsonpath, "utf8");
240240
try {
241241
sessionjson = JSON.parse(s);
242242
} catch (error) {
@@ -256,43 +256,41 @@ const getSessionDataFromFile = (sessionId: string, config: ConfigObject, spinner
256256
return sessionjson;
257257
}
258258

259-
export const deleteSessionData = (config: ConfigObject) : boolean => {
260-
const sessionjsonpath = getSessionDataFilePath(config?.sessionId || 'session', config)
261-
if(typeof sessionjsonpath == 'string' && fs.existsSync(sessionjsonpath)) {
259+
export const deleteSessionData = async (config: ConfigObject) : Promise<boolean> => {
260+
const sessionjsonpath = await getSessionDataFilePath(config?.sessionId || 'session', config)
261+
if(typeof sessionjsonpath == 'string' && await pathExists(sessionjsonpath)) {
262262
const l = `logout detected, deleting session data file: ${sessionjsonpath}`
263263
console.log(l)
264264
log.info(l)
265-
fs.unlinkSync(sessionjsonpath);
265+
await fs.unlink(sessionjsonpath);
266266
}
267-
const mdDir = config['userDataDir'];
268-
if(mdDir) {
267+
const mdDir = await pathExists(config['userDataDir']);
268+
if(config['userDataDir'] && mdDir) {
269269
log.info(`Deleting MD session directory: ${mdDir}`)
270-
//@ts-ignore
271-
fs.rmdirSync(mdDir, { force: true, recursive: true})
270+
await fs.rm(mdDir, { force: true, recursive: true})
271+
log.info(`MD directory ${mdDir} deleted: ${!(await pathExists(mdDir, true))}`)
272272
}
273273
return true;
274274
}
275275

276-
export const invalidateSesssionData = (config: ConfigObject) : boolean => {
277-
const sessionjsonpath = getSessionDataFilePath(config?.sessionId || 'session', config)
278-
if(typeof sessionjsonpath == 'string' && fs.existsSync(sessionjsonpath)) {
276+
export const invalidateSesssionData = async (config: ConfigObject) : Promise<boolean> => {
277+
const sessionjsonpath = await getSessionDataFilePath(config?.sessionId || 'session', config)
278+
if(typeof sessionjsonpath == 'string' && await pathExists(sessionjsonpath)) {
279279
const l = `logout detected, invalidating session data file: ${sessionjsonpath}`
280280
console.log(l)
281281
log.info(l)
282-
fs.writeFile(sessionjsonpath, "LOGGED OUT", (err) => {
283-
if (err) { console.error(err); return; }
284-
});
282+
fs.writeFile(sessionjsonpath, "LOGGED OUT");
285283
}
286284
return true;
287285
}
288286

289-
export const getSessionDataFilePath = (sessionId: string, config: ConfigObject) : string | false => {
287+
export const getSessionDataFilePath = async (sessionId: string, config: ConfigObject) : Promise<string | false> => {
290288
const p = require?.main?.path || process?.mainModule?.path;
291289
const sessionjsonpath = (config?.sessionDataPath && config?.sessionDataPath.includes('.data.json')) ? path.join(path.resolve(process.cwd(),config?.sessionDataPath || '')) : path.join(path.resolve(process.cwd(),config?.sessionDataPath || ''), `${sessionId || 'session'}.data.json`);
292290
const altSessionJsonPath = p ? (config?.sessionDataPath && config?.sessionDataPath.includes('.data.json')) ? path.join(path.resolve(p,config?.sessionDataPath || '')) : path.join(path.resolve(p,config?.sessionDataPath || ''), `${sessionId || 'session'}.data.json`) : false;
293-
if(fs.existsSync(sessionjsonpath)){
291+
if(pathExists(sessionjsonpath)){
294292
return sessionjsonpath
295-
} else if(p && altSessionJsonPath && fs.existsSync(altSessionJsonPath)){
293+
} else if(p && altSessionJsonPath && await pathExists(altSessionJsonPath)){
296294
return altSessionJsonPath
297295
}
298296
return false
@@ -401,9 +399,9 @@ async function initBrowser(sessionId?: string, config:any={}, spinner ?: Spin) {
401399
spinner?.info(`Data dir: ${config["userDataDir"]}`)
402400
}
403401
if(config?.corsFix) args.push('--disable-web-security');
404-
if(config["userDataDir"] && !fs.existsSync(config["userDataDir"])) {
402+
if(config["userDataDir"] && !(await pathExists(config["userDataDir"]))) {
405403
spinner?.info(`Data dir doesnt exist, creating...: ${config["userDataDir"]}`)
406-
fs.mkdirSync(config["userDataDir"], {recursive: true});
404+
fs.mkdir(config["userDataDir"], {recursive: true});
407405
}
408406
const browser = (config?.browserWSEndpoint) ? await puppeteer.connect({...config}): await puppeteer.launch({
409407
headless: true,

src/controllers/initializer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export async function create(config: AdvancedConfig | ConfigObject = {}): Promis
225225
//kill the browser
226226
spinner.fail("Session data most likely expired due to manual host account logout. Please re-authenticate this session.")
227227
await kill(waPage)
228-
if(config?.deleteSessionDataOnLogout) deleteSessionData(config)
228+
if(config?.deleteSessionDataOnLogout) await deleteSessionData(config)
229229
if(config?.throwOnExpiredSessionData) {
230230
throw new SessionExpiredError();
231231
} else

src/utils/tools.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Crypto from "crypto";
22
import * as fs from 'fs'
3+
import * as fsp from 'fs/promises'
34
import * as path from 'path';
45
import datauri from 'datauri'
56
import isUrl from 'is-url-superb'
@@ -8,6 +9,7 @@ import { AdvancedFile, ConfigObject, CustomError, DataURL, ERROR_NAME } from '..
89
import { default as axios, AxiosRequestConfig } from 'axios';
910
import { SessionInfo } from '../api/model/sessionInfo';
1011
import { execSync } from 'child_process';
12+
import { homedir } from 'os'
1113
import {
1214
performance
1315
} from 'perf_hooks';
@@ -369,4 +371,35 @@ export const assertFile : (file: AdvancedFile | Buffer, outfileName: string, des
369371
}
370372
}
371373
return file;
372-
}
374+
}
375+
376+
/**
377+
* Checks if a given path exists.
378+
*
379+
* If exists, returns the resolved absolute path. Otherwise returns false.
380+
*
381+
* @param _path a relative, absolute or homedir path to a folder or a file
382+
* @param failSilent If you're expecting for the file to not exist and just want the `false` response then set this to true to prevent false-positive error messages in the logs.
383+
* @returns string | false
384+
*/
385+
export const pathExists : (_path : string, failSilent?: boolean) => Promise<string | false> = async (_path : string, failSilent ?: boolean) => {
386+
_path = fixPath(_path)
387+
try {
388+
await fsp.access(_path, fsp.constants.R_OK | fsp.constants.W_OK)
389+
return _path;
390+
} catch (error) {
391+
if(!failSilent) log.error('Given check path threw an error', error)
392+
return false;
393+
}
394+
}
395+
396+
/**
397+
* Returns an absolute file path reference
398+
* @param _path a relative, absolute or homedir path to a folder or a file
399+
* @returns string
400+
*/
401+
export const fixPath : (_path : string) => string = ( _path : string) => {
402+
_path = _path.replace("~",homedir())
403+
_path = _path.includes('./') ? path.join(process.cwd(), _path) : _path;
404+
return _path;
405+
}

0 commit comments

Comments
 (0)