修复文件路径含空格问题

This commit is contained in:
Jerry 2025-05-11 14:19:06 +08:00
parent d755001be4
commit 301113669e

View File

@ -49,12 +49,12 @@ export class xzq extends plugin {
async listen_outdir(dir, timeout = 30000) { async listen_outdir(dir, timeout = 30000) {
if (!dir) return false; if (!dir) return false;
return new Promise((resolve, reject) => { return new Promise((resolve) => {
const watcher = chokidar.watch(dir, { const watcher = chokidar.watch(dir, {
persistent: true, persistent: true,
ignoreInitial: true, ignoreInitial: true,
}); });
let timer = setTimeout(() => { const timer = setTimeout(() => {
watcher.close(); watcher.close();
resolve(false); resolve(false);
}, timeout); }, timeout);
@ -66,182 +66,160 @@ export class xzq extends plugin {
console.log(`已开始监听目录: ${dir}`); console.log(`已开始监听目录: ${dir}`);
}); });
} }
async clearCache(e, is_task = false, zd = false) { async clearCache(e, is_task = false, zd = false) {
if (!is_task && (!e || !e.isMaster)) { if (!is_task && (!e || !e.isMaster)) {
if (e) e.reply('你没有权限使用此功能', true); if (e) e.reply('你没有权限使用此功能', true);
return false; return false;
} }
if (!this.outDir) { if (!this.outDir) {
if (this.initConfigPromise) {
await this.initConfigPromise; await this.initConfigPromise;
}
if (!this.outDir) { if (!this.outDir) {
if (e) e.reply('缓存目录未初始化,无法清理缓存', true); if (e) e.reply('缓存目录未初始化,无法清理缓存', true);
return false; return false;
} }
} }
const dir = path.join(this.outDir, 'fanqie');
if (zd) { if (zd) {
const cdir = path.join(this.outDir, 'files', zd); const targetDir = path.join(this.outDir, 'files', zd);
if (!fs.existsSync(cdir)) { if (fs.existsSync(targetDir)) {
if (e) e.reply('目录不存在', true); fs.rmSync(targetDir, { recursive: true, force: true });
return false;
}
if (fs.rmSync) {
fs.rmSync(cdir, { recursive: true, force: true });
} else {
fs.rmdirSync(cdir, { recursive: true });
} }
} }
if (fs.existsSync(dir)) {
const files = fs.readdirSync(dir); const fanqieDir = path.join(this.outDir, 'fanqie');
for (const file of files) { if (fs.existsSync(fanqieDir)) {
const filePath = path.join(dir, file); fs.readdirSync(fanqieDir).forEach((file) => {
const stat = fs.statSync(filePath); const fullPath = path.join(fanqieDir, file);
const stat = fs.statSync(fullPath);
if (stat.isDirectory()) { if (stat.isDirectory()) {
if (fs.rmSync) { fs.rmSync(fullPath, { recursive: true, force: true });
fs.rmSync(filePath, { recursive: true, force: true });
} else { } else {
fs.rmdirSync(filePath, { recursive: true }); fs.unlinkSync(fullPath);
}
} else {
fs.unlinkSync(filePath);
}
} }
});
} }
if (!is_task && e) e.reply('缓存已清理', true); if (!is_task && e) e.reply('缓存已清理', true);
return true; return true;
} }
async control(e) { async control(e) {
if (!e.isMaster) { if (!e.isMaster) return e.reply('你没有权限使用此功能', true);
e.reply('你没有权限使用此功能', true);
return false; let id = e.msg.trim().replace(/^fq(允许|禁止)(群|用户)使用/, '') || e.group_id;
} const keyPrefix = e.msg.includes('群') ? 'g' : 'u';
let id = e.msg.trim().replace(/^fq(允许|禁止)(群|用户)使用/, ''); const key = `fqxzq:${keyPrefix}:${id}`;
if (id == '') { const allow = e.msg.includes('允许');
id = e.group_id;
} await redis.set(key, allow);
if (e.msg.includes('群')) { e.reply(
if (e.msg.includes('允许')) { `${allow ? '允许' : '禁止'}${keyPrefix === 'g' ? '群' : '用户'}${id}使用此功能`,
redis.set(`fqxzq:g:${id}`, true); true
e.reply(`已允许群${id}使用此功能`, true); );
} else {
redis.set(`fqxzq:g:${id}`, false);
e.reply(`已禁止群${id}使用此功能`, true);
}
} else {
if (e.msg.includes('允许')) {
redis.set(`fqxzq:u:${id}`, true);
e.reply(`已允许用户${id}使用此功能`, true);
} else {
redis.set(`fqxzq:u:${id}`, false);
e.reply(`已禁止用户${id}使用此功能`, true);
}
return true; return true;
} }
}
async byid(e) { async byid(e) {
let msg = e.msg.trim(); const book_id = e.msg
let book_id = msg.replace('#?fq下载', '').trim(); .trim()
.replace(/^#?fq下载/, '')
.trim();
return this.xz(e, book_id); return this.xz(e, book_id);
} }
async jx(e) { async jx(e) {
let book_id, const msg = e.msg.trim();
msg = e.msg.trim(); let book_id = null;
if (msg.includes('changdunovel.com/wap/share-v2.html')) { try {
if (msg.includes('changdunovel.com')) {
book_id = msg.match(/book_id=(\d+)/)[1]; book_id = msg.match(/book_id=(\d+)/)[1];
} else { } else {
book_id = msg.match(/page\/(\d+)/)[1]; book_id = msg.match(/page\/(\d+)/)[1];
} }
} catch {
return e.reply('链接解析失败,请检查链接是否正确', true);
}
return this.xz(e, book_id); return this.xz(e, book_id);
} }
async xz(e, id) { async xz(e, id) {
await this.initConfigPromise; await this.initConfigPromise;
let book_id = id;
let book_info; let book_info;
try { try {
book_info = await this.fq.get_info(book_id); book_info = await this.fq.get_info(id);
} catch (err) { } catch (err) {
logger.error(err); logger.error(err);
e.reply('获取信息失败', true); return e.reply('获取信息失败', true);
return true;
}
if (!book_info) {
e.reply('获取信息失败', true);
return true;
} }
if (!book_info) return e.reply('获取信息失败', true);
e.reply( e.reply(
`识别:[番茄小说]《${book_info.book_name}\n作者:${book_info.author}\n原名:${book_info.original_book_name}`, `识别:[番茄小说]《${book_info.book_name}\n作者:${book_info.author}\n原名:${book_info.original_book_name}`,
true true
); );
if (!e.isMaster) { if (!e.isMaster) {
const groupAllow = e.isGroup ? await redis.get(`fqxzq:g:${e.group_id}`) : null; const allowGroup = e.isGroup ? await redis.get(`fqxzq:g:${e.group_id}`) : null;
const userAllow = await redis.get(`fqxzq:u:${e.user_id}`); const allowUser = await redis.get(`fqxzq:u:${e.user_id}`);
if (!groupAllow && !userAllow) { if (!allowGroup && !allowUser) return false;
return false;
} }
}
e.reply('开始下载,请稍等', true); e.reply('开始下载请稍等', true);
let starttime = Date.now(); const startTime = Date.now();
let ok;
try { try {
ok = await this.fq.down(book_id, e.message_id); await this.fq.down(id, e.message_id);
} catch (err) { } catch (err) {
logger.error(err); logger.error(err);
e.reply('下载失败', true); return e.reply('下载失败', true);
return true;
} }
if (!ok) {
e.reply('下载失败', true); const outPath = path.join(this.outDir, 'files', String(e.message_id));
return true; let filePath = await this.listen_outdir(outPath);
} if (!filePath) return e.reply('下载超时', true);
let file;
const safeFilePath = filePath.replace(/ /g, '_');
if (filePath !== safeFilePath) {
try { try {
file = await this.listen_outdir(path.join(this.outDir, 'files', String(e.message_id))); fs.renameSync(filePath, safeFilePath);
filePath = safeFilePath;
} catch (err) { } catch (err) {
logger.error(err); logger.error(`重命名文件失败:${err.stack}`);
e.reply('下载超时', true); return e.reply('文件重命名失败', true);
return true;
} }
if (!file) {
e.reply('下载超时', true);
return true;
} }
ok = await this.upload(e, file, book_info);
if (!ok) { const uploadOk = await this.upload(e, filePath);
this.clearCache(false, true, String(e.message_id)); this.clearCache(false, true, String(e.message_id));
e.reply('上传失败', true); if (!uploadOk) return e.reply('上传失败', true);
e.reply(`${book_info.book_name}》上传成功,用时 ${(Date.now() - startTime) / 1000}s`, true);
return true; return true;
} }
this.clearCache(false, true, String(e.message_id));
e.reply( async upload(e, filePath) {
`${book_info.book_name}》上传成功,总用时:${((Date.now() - starttime) / 1000).toFixed(2)}s`,
true
);
}
async upload(e, filePath, bookInfo) {
try { try {
let res; let res;
if (e.isGroup) { if (e.isGroup) {
res = this.e.bot.sendApi('upload_group_file', { res = e.bot.sendApi('upload_group_file', {
group_id: e.group_id, group_id: e.group_id,
file: filePath, file: filePath,
name: bookInfo.book_name, name: path.basename(filePath),
folder: 'fanqie', folder: 'fanqie',
}); });
} else if (e.friend) { } else if (e.friend) {
res = e.bot.sendApi('upload_private_file', { res = e.bot.sendApi('upload_private_file', {
user_id: e.user_id, user_id: e.user_id,
file: filePath, file: filePath,
name: bookInfo.book_name, name: path.basename(filePath),
}); });
} }
if (res) { return !!res;
return true;
}
} catch (err) { } catch (err) {
logger.error(`文件上传错误:${logger.red(err.stack)}`); logger.error(`文件上传错误:${logger.red(err.stack)}`);
if (e && e.reply) await e.reply(`文件上传错误:${err.stack}`); if (e?.reply) e.reply(`文件上传失败:${err.message}`, true);
return false; return false;
} }
} }