mirror of
https://github.com/TheNetsky/Microsoft-Rewards-Script.git
synced 2026-01-17 21:43:59 +00:00
v3.1.0 initial
This commit is contained in:
@@ -1,104 +0,0 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
|
||||
const projectRoot = path.resolve(__dirname, '..')
|
||||
|
||||
const possibleConfigPaths = [
|
||||
path.join(projectRoot, 'config.json'),
|
||||
path.join(projectRoot, 'src', 'config.json'),
|
||||
path.join(projectRoot, 'dist', 'config.json')
|
||||
]
|
||||
|
||||
console.log('[DEBUG] Project root:', projectRoot)
|
||||
console.log('[DEBUG] Searching for config.json...')
|
||||
|
||||
let configPath = null
|
||||
for (const p of possibleConfigPaths) {
|
||||
console.log('[DEBUG] Checking:', p)
|
||||
if (fs.existsSync(p)) {
|
||||
configPath = p
|
||||
console.log('[DEBUG] Found config at:', p)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!configPath) {
|
||||
console.error('[ERROR] config.json not found in any expected location!')
|
||||
console.error('[ERROR] Searched:', possibleConfigPaths)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('[INFO] Using config:', configPath)
|
||||
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'))
|
||||
|
||||
if (!config.sessionPath) {
|
||||
console.error("[ERROR] config.json missing 'sessionPath' key!")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('[INFO] Session path from config:', config.sessionPath)
|
||||
|
||||
const configDir = path.dirname(configPath)
|
||||
const possibleSessionDirs = [
|
||||
path.resolve(configDir, config.sessionPath),
|
||||
path.join(projectRoot, 'src/browser', config.sessionPath),
|
||||
path.join(projectRoot, 'dist/browser', config.sessionPath)
|
||||
]
|
||||
|
||||
console.log('[DEBUG] Searching for session directory...')
|
||||
|
||||
let sessionDir = null
|
||||
for (const p of possibleSessionDirs) {
|
||||
console.log('[DEBUG] Checking:', p)
|
||||
if (fs.existsSync(p)) {
|
||||
sessionDir = p
|
||||
console.log('[DEBUG] Found session directory at:', p)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!sessionDir) {
|
||||
sessionDir = path.resolve(configDir, config.sessionPath)
|
||||
console.log('[DEBUG] Using fallback session directory:', sessionDir)
|
||||
}
|
||||
|
||||
const normalizedSessionDir = path.normalize(sessionDir)
|
||||
const normalizedProjectRoot = path.normalize(projectRoot)
|
||||
|
||||
if (!normalizedSessionDir.startsWith(normalizedProjectRoot)) {
|
||||
console.error('[ERROR] Session directory is outside project root!')
|
||||
console.error('[ERROR] Project root:', normalizedProjectRoot)
|
||||
console.error('[ERROR] Session directory:', normalizedSessionDir)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (normalizedSessionDir === normalizedProjectRoot) {
|
||||
console.error('[ERROR] Session directory cannot be the project root!')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const pathSegments = normalizedSessionDir.split(path.sep)
|
||||
if (pathSegments.length < 3) {
|
||||
console.error('[ERROR] Session path is too shallow (safety check failed)!')
|
||||
console.error('[ERROR] Path:', normalizedSessionDir)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (fs.existsSync(sessionDir)) {
|
||||
console.log('[INFO] Removing session folder:', sessionDir)
|
||||
try {
|
||||
fs.rmSync(sessionDir, { recursive: true, force: true })
|
||||
console.log('[SUCCESS] Session folder removed successfully')
|
||||
} catch (error) {
|
||||
console.error('[ERROR] Failed to remove session folder:', error.message)
|
||||
process.exit(1)
|
||||
}
|
||||
} else {
|
||||
console.log('[INFO] Session folder does not exist:', sessionDir)
|
||||
}
|
||||
|
||||
console.log('[INFO] Done.')
|
||||
168
scripts/main/browserSession.js
Normal file
168
scripts/main/browserSession.js
Normal file
@@ -0,0 +1,168 @@
|
||||
import fs from 'fs'
|
||||
import { chromium } from 'patchright'
|
||||
import { newInjectedContext } from 'fingerprint-injector'
|
||||
import {
|
||||
getDirname,
|
||||
getProjectRoot,
|
||||
log,
|
||||
parseArgs,
|
||||
validateEmail,
|
||||
loadConfig,
|
||||
loadAccounts,
|
||||
findAccountByEmail,
|
||||
getRuntimeBase,
|
||||
getSessionPath,
|
||||
loadCookies,
|
||||
loadFingerprint,
|
||||
buildProxyConfig,
|
||||
setupCleanupHandlers
|
||||
} from '../utils.js'
|
||||
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
const projectRoot = getProjectRoot(__dirname)
|
||||
|
||||
const args = parseArgs()
|
||||
args.dev = args.dev || false
|
||||
|
||||
validateEmail(args.email)
|
||||
|
||||
const { data: config } = loadConfig(projectRoot, args.dev)
|
||||
const { data: accounts } = loadAccounts(projectRoot, args.dev)
|
||||
|
||||
const account = findAccountByEmail(accounts, args.email)
|
||||
if (!account) {
|
||||
log('ERROR', `Account not found: ${args.email}`)
|
||||
log('ERROR', 'Available accounts:')
|
||||
accounts.forEach(acc => {
|
||||
if (acc?.email) log('ERROR', ` - ${acc.email}`)
|
||||
})
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const runtimeBase = getRuntimeBase(projectRoot, args.dev)
|
||||
const sessionBase = getSessionPath(runtimeBase, config.sessionPath, args.email)
|
||||
|
||||
log('INFO', 'Validating session data...')
|
||||
|
||||
if (!fs.existsSync(sessionBase)) {
|
||||
log('ERROR', `Session directory does not exist: ${sessionBase}`)
|
||||
log('ERROR', 'Please ensure the session has been created for this account')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!config.baseURL) {
|
||||
log('ERROR', 'baseURL is not set in config.json')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
let cookies = await loadCookies(sessionBase, 'desktop')
|
||||
let sessionType = 'desktop'
|
||||
|
||||
if (cookies.length === 0) {
|
||||
log('WARN', 'No desktop session cookies found, trying mobile session...')
|
||||
cookies = await loadCookies(sessionBase, 'mobile')
|
||||
sessionType = 'mobile'
|
||||
|
||||
if (cookies.length === 0) {
|
||||
log('ERROR', 'No cookies found in desktop or mobile session')
|
||||
log('ERROR', `Session directory: ${sessionBase}`)
|
||||
log('ERROR', 'Please ensure a valid session exists for this account')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
log('INFO', `Using mobile session (${cookies.length} cookies)`)
|
||||
}
|
||||
|
||||
const isMobile = sessionType === 'mobile'
|
||||
const fingerprintEnabled = isMobile ? account.saveFingerprint?.mobile : account.saveFingerprint?.desktop
|
||||
|
||||
let fingerprint = null
|
||||
if (fingerprintEnabled) {
|
||||
fingerprint = await loadFingerprint(sessionBase, sessionType)
|
||||
if (!fingerprint) {
|
||||
log('ERROR', `Fingerprint is enabled for ${sessionType} but fingerprint file not found`)
|
||||
log('ERROR', `Expected file: ${sessionBase}/session_fingerprint_${sessionType}.json`)
|
||||
log('ERROR', 'Cannot start browser without fingerprint when it is explicitly enabled')
|
||||
process.exit(1)
|
||||
}
|
||||
log('INFO', `Loaded ${sessionType} fingerprint`)
|
||||
}
|
||||
|
||||
const proxy = buildProxyConfig(account)
|
||||
|
||||
if (account.proxy && account.proxy.url && (!proxy || !proxy.server)) {
|
||||
log('ERROR', 'Proxy is configured in account but proxy data is invalid or incomplete')
|
||||
log('ERROR', 'Account proxy config:', JSON.stringify(account.proxy, null, 2))
|
||||
log('ERROR', 'Required fields: proxy.url, proxy.port')
|
||||
log('ERROR', 'Cannot start browser without proxy when it is explicitly configured')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const userAgent = fingerprint?.fingerprint?.navigator?.userAgent || fingerprint?.fingerprint?.userAgent || null
|
||||
|
||||
log('INFO', `Session: ${args.email} (${sessionType})`)
|
||||
log('INFO', ` Cookies: ${cookies.length}`)
|
||||
log('INFO', ` Fingerprint: ${fingerprint ? 'Yes' : 'No'}`)
|
||||
log('INFO', ` User-Agent: ${userAgent || 'Default'}`)
|
||||
log('INFO', ` Proxy: ${proxy ? 'Yes' : 'No'}`)
|
||||
log('INFO', 'Launching browser...')
|
||||
|
||||
const browser = await chromium.launch({
|
||||
headless: false,
|
||||
...(proxy ? { proxy } : {}),
|
||||
args: [
|
||||
'--no-sandbox',
|
||||
'--mute-audio',
|
||||
'--disable-setuid-sandbox',
|
||||
'--ignore-certificate-errors',
|
||||
'--ignore-certificate-errors-spki-list',
|
||||
'--ignore-ssl-errors',
|
||||
'--no-first-run',
|
||||
'--no-default-browser-check',
|
||||
'--disable-user-media-security=true',
|
||||
'--disable-blink-features=Attestation',
|
||||
'--disable-features=WebAuthentication,PasswordManagerOnboarding,PasswordManager,EnablePasswordsAccountStorage,Passkeys',
|
||||
'--disable-save-password-bubble'
|
||||
]
|
||||
})
|
||||
|
||||
let context
|
||||
if (fingerprint) {
|
||||
context = await newInjectedContext(browser, { fingerprint })
|
||||
|
||||
await context.addInitScript(() => {
|
||||
Object.defineProperty(navigator, 'credentials', {
|
||||
value: {
|
||||
create: () => Promise.reject(new Error('WebAuthn disabled')),
|
||||
get: () => Promise.reject(new Error('WebAuthn disabled'))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
log('SUCCESS', 'Fingerprint injected into browser context')
|
||||
} else {
|
||||
context = await browser.newContext({
|
||||
viewport: isMobile ? { width: 375, height: 667 } : { width: 1366, height: 768 }
|
||||
})
|
||||
}
|
||||
|
||||
if (cookies.length) {
|
||||
await context.addCookies(cookies)
|
||||
log('INFO', `Added ${cookies.length} cookies to context`)
|
||||
}
|
||||
|
||||
const page = await context.newPage()
|
||||
await page.goto(config.baseURL, { waitUntil: 'domcontentloaded' })
|
||||
|
||||
log('SUCCESS', 'Browser opened with session loaded')
|
||||
log('INFO', `Navigated to: ${config.baseURL}`)
|
||||
|
||||
setupCleanupHandlers(async () => {
|
||||
if (browser?.isConnected?.()) {
|
||||
await browser.close()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
main()
|
||||
67
scripts/main/clearSessions.js
Normal file
67
scripts/main/clearSessions.js
Normal file
@@ -0,0 +1,67 @@
|
||||
import path from 'path'
|
||||
import fs from 'fs'
|
||||
import {
|
||||
getDirname,
|
||||
getProjectRoot,
|
||||
log,
|
||||
loadJsonFile,
|
||||
safeRemoveDirectory
|
||||
} from '../utils.js'
|
||||
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
const projectRoot = getProjectRoot(__dirname)
|
||||
|
||||
const possibleConfigPaths = [
|
||||
path.join(projectRoot, 'config.json'),
|
||||
path.join(projectRoot, 'src', 'config.json'),
|
||||
path.join(projectRoot, 'dist', 'config.json')
|
||||
]
|
||||
|
||||
log('DEBUG', 'Project root:', projectRoot)
|
||||
log('DEBUG', 'Searching for config.json...')
|
||||
|
||||
const configResult = loadJsonFile(possibleConfigPaths, true)
|
||||
const config = configResult.data
|
||||
const configPath = configResult.path
|
||||
|
||||
log('INFO', 'Using config:', configPath)
|
||||
|
||||
if (!config.sessionPath) {
|
||||
log('ERROR', 'Invalid config.json - missing required field: sessionPath')
|
||||
log('ERROR', `Config file: ${configPath}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
log('INFO', 'Session path from config:', config.sessionPath)
|
||||
|
||||
const configDir = path.dirname(configPath)
|
||||
const possibleSessionDirs = [
|
||||
path.resolve(configDir, config.sessionPath),
|
||||
path.join(projectRoot, 'src/browser', config.sessionPath),
|
||||
path.join(projectRoot, 'dist/browser', config.sessionPath)
|
||||
]
|
||||
|
||||
log('DEBUG', 'Searching for session directory...')
|
||||
|
||||
let sessionDir = null
|
||||
for (const p of possibleSessionDirs) {
|
||||
log('DEBUG', 'Checking:', p)
|
||||
if (fs.existsSync(p)) {
|
||||
sessionDir = p
|
||||
log('DEBUG', 'Found session directory at:', p)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!sessionDir) {
|
||||
sessionDir = path.resolve(configDir, config.sessionPath)
|
||||
log('DEBUG', 'Using fallback session directory:', sessionDir)
|
||||
}
|
||||
|
||||
const success = safeRemoveDirectory(sessionDir, projectRoot)
|
||||
|
||||
if (!success) {
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
log('INFO', 'Done.')
|
||||
269
scripts/utils.js
Normal file
269
scripts/utils.js
Normal file
@@ -0,0 +1,269 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
export function getDirname(importMetaUrl) {
|
||||
const __filename = fileURLToPath(importMetaUrl)
|
||||
return path.dirname(__filename)
|
||||
}
|
||||
|
||||
export function getProjectRoot(currentDir) {
|
||||
let dir = currentDir
|
||||
while (dir !== path.parse(dir).root) {
|
||||
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
||||
return dir
|
||||
}
|
||||
dir = path.dirname(dir)
|
||||
}
|
||||
throw new Error('Could not find project root (package.json not found)')
|
||||
}
|
||||
|
||||
export function log(level, ...args) {
|
||||
console.log(`[${level}]`, ...args)
|
||||
}
|
||||
|
||||
export function parseArgs(argv = process.argv.slice(2)) {
|
||||
const args = {}
|
||||
|
||||
for (let i = 0; i < argv.length; i++) {
|
||||
const arg = argv[i]
|
||||
|
||||
if (arg.startsWith('-')) {
|
||||
const key = arg.substring(1)
|
||||
|
||||
if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {
|
||||
args[key] = argv[i + 1]
|
||||
i++
|
||||
} else {
|
||||
args[key] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
export function validateEmail(email) {
|
||||
if (!email) {
|
||||
log('ERROR', 'Missing -email argument')
|
||||
log('ERROR', 'Usage: node script.js -email you@example.com')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (typeof email !== 'string') {
|
||||
log('ERROR', `Invalid email type: expected string, got ${typeof email}`)
|
||||
log('ERROR', 'Usage: node script.js -email you@example.com')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!email.includes('@')) {
|
||||
log('ERROR', `Invalid email format: "${email}"`)
|
||||
log('ERROR', 'Email must contain "@" symbol')
|
||||
log('ERROR', 'Example: you@example.com')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
return email
|
||||
}
|
||||
|
||||
export function loadJsonFile(possiblePaths, required = true) {
|
||||
for (const filePath of possiblePaths) {
|
||||
if (fs.existsSync(filePath)) {
|
||||
try {
|
||||
const content = fs.readFileSync(filePath, 'utf8')
|
||||
return { data: JSON.parse(content), path: filePath }
|
||||
} catch (error) {
|
||||
log('ERROR', `Failed to parse JSON file: ${filePath}`)
|
||||
log('ERROR', `Parse error: ${error.message}`)
|
||||
if (required) process.exit(1)
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (required) {
|
||||
log('ERROR', 'Required file not found')
|
||||
log('ERROR', 'Searched in the following locations:')
|
||||
possiblePaths.forEach(p => log('ERROR', ` - ${p}`))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
export function loadConfig(projectRoot, isDev = false) {
|
||||
const possiblePaths = isDev
|
||||
? [path.join(projectRoot, 'src', 'config.json')]
|
||||
: [
|
||||
path.join(projectRoot, 'dist', 'config.json'),
|
||||
path.join(projectRoot, 'config.json')
|
||||
]
|
||||
|
||||
const result = loadJsonFile(possiblePaths, true)
|
||||
|
||||
const missingFields = []
|
||||
if (!result.data.baseURL) missingFields.push('baseURL')
|
||||
if (!result.data.sessionPath) missingFields.push('sessionPath')
|
||||
if (result.data.headless === undefined) missingFields.push('headless')
|
||||
if (!result.data.workers) missingFields.push('workers')
|
||||
|
||||
if (missingFields.length > 0) {
|
||||
log('ERROR', 'Invalid config.json - missing required fields:')
|
||||
missingFields.forEach(field => log('ERROR', ` - ${field}`))
|
||||
log('ERROR', `Config file: ${result.path}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export function loadAccounts(projectRoot, isDev = false) {
|
||||
const possiblePaths = isDev
|
||||
? [path.join(projectRoot, 'src', 'accounts.dev.json')]
|
||||
: [
|
||||
path.join(projectRoot, 'dist', 'accounts.json'),
|
||||
path.join(projectRoot, 'accounts.json'),
|
||||
path.join(projectRoot, 'accounts.example.json')
|
||||
]
|
||||
|
||||
return loadJsonFile(possiblePaths, true)
|
||||
}
|
||||
|
||||
export function findAccountByEmail(accounts, email) {
|
||||
if (!email || typeof email !== 'string') return null
|
||||
return accounts.find(a => a?.email && typeof a.email === 'string' && a.email.toLowerCase() === email.toLowerCase()) || null
|
||||
}
|
||||
|
||||
export function getRuntimeBase(projectRoot, isDev = false) {
|
||||
return path.join(projectRoot, isDev ? 'src' : 'dist')
|
||||
}
|
||||
|
||||
export function getSessionPath(runtimeBase, sessionPath, email) {
|
||||
return path.join(runtimeBase, 'browser', sessionPath, email)
|
||||
}
|
||||
|
||||
export async function loadCookies(sessionBase, type = 'desktop') {
|
||||
const cookiesFile = path.join(sessionBase, `session_${type}.json`)
|
||||
|
||||
if (!fs.existsSync(cookiesFile)) {
|
||||
return []
|
||||
}
|
||||
|
||||
try {
|
||||
const content = await fs.promises.readFile(cookiesFile, 'utf8')
|
||||
return JSON.parse(content)
|
||||
} catch (error) {
|
||||
log('WARN', `Failed to load cookies from: ${cookiesFile}`)
|
||||
log('WARN', `Error: ${error.message}`)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadFingerprint(sessionBase, type = 'desktop') {
|
||||
const fpFile = path.join(sessionBase, `session_fingerprint_${type}.json`)
|
||||
|
||||
if (!fs.existsSync(fpFile)) {
|
||||
return null
|
||||
}
|
||||
|
||||
try {
|
||||
const content = await fs.promises.readFile(fpFile, 'utf8')
|
||||
return JSON.parse(content)
|
||||
} catch (error) {
|
||||
log('WARN', `Failed to load fingerprint from: ${fpFile}`)
|
||||
log('WARN', `Error: ${error.message}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function getUserAgent(fingerprint) {
|
||||
if (!fingerprint) return null
|
||||
return fingerprint?.fingerprint?.userAgent || fingerprint?.userAgent || null
|
||||
}
|
||||
|
||||
export function buildProxyConfig(account) {
|
||||
if (!account.proxy || !account.proxy.url || !account.proxy.port) {
|
||||
return null
|
||||
}
|
||||
|
||||
const proxy = {
|
||||
server: `${account.proxy.url}:${account.proxy.port}`
|
||||
}
|
||||
|
||||
if (account.proxy.username && account.proxy.password) {
|
||||
proxy.username = account.proxy.username
|
||||
proxy.password = account.proxy.password
|
||||
}
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
export function setupCleanupHandlers(cleanupFn) {
|
||||
const cleanup = async () => {
|
||||
try {
|
||||
await cleanupFn()
|
||||
} catch (error) {
|
||||
log('ERROR', 'Cleanup failed:', error.message)
|
||||
}
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
process.on('SIGINT', cleanup)
|
||||
process.on('SIGTERM', cleanup)
|
||||
}
|
||||
|
||||
export function validateDeletionPath(targetPath, projectRoot) {
|
||||
const normalizedTarget = path.normalize(targetPath)
|
||||
const normalizedRoot = path.normalize(projectRoot)
|
||||
|
||||
if (!normalizedTarget.startsWith(normalizedRoot)) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Path is outside project root'
|
||||
}
|
||||
}
|
||||
|
||||
if (normalizedTarget === normalizedRoot) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Cannot delete project root'
|
||||
}
|
||||
}
|
||||
|
||||
const pathSegments = normalizedTarget.split(path.sep)
|
||||
if (pathSegments.length < 3) {
|
||||
return {
|
||||
valid: false,
|
||||
error: 'Path is too shallow (safety check failed)'
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true, error: null }
|
||||
}
|
||||
|
||||
export function safeRemoveDirectory(dirPath, projectRoot) {
|
||||
const validation = validateDeletionPath(dirPath, projectRoot)
|
||||
|
||||
if (!validation.valid) {
|
||||
log('ERROR', 'Directory deletion failed - safety check:')
|
||||
log('ERROR', ` Reason: ${validation.error}`)
|
||||
log('ERROR', ` Target: ${dirPath}`)
|
||||
log('ERROR', ` Project root: ${projectRoot}`)
|
||||
return false
|
||||
}
|
||||
|
||||
if (!fs.existsSync(dirPath)) {
|
||||
log('INFO', `Directory does not exist: ${dirPath}`)
|
||||
return true
|
||||
}
|
||||
|
||||
try {
|
||||
fs.rmSync(dirPath, { recursive: true, force: true })
|
||||
log('SUCCESS', `Directory removed: ${dirPath}`)
|
||||
return true
|
||||
} catch (error) {
|
||||
log('ERROR', `Failed to remove directory: ${dirPath}`)
|
||||
log('ERROR', `Error: ${error.message}`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user