|
@@ -57,8 +57,8 @@ export class ChatRecordsService {
|
|
|
const dialogs = await this.getDialogs();
|
|
const dialogs = await this.getDialogs();
|
|
|
// this.log('获取到对话数量:', dialogs.length);
|
|
// this.log('获取到对话数量:', dialogs.length);
|
|
|
|
|
|
|
|
- // 限制对话数量,避免过多请求
|
|
|
|
|
- const maxDialogs = 50;
|
|
|
|
|
|
|
+ // 限制对话数量,只获取最近的20个对话
|
|
|
|
|
+ const maxDialogs = 20;
|
|
|
const processedDialogs = dialogs.slice(0, maxDialogs);
|
|
const processedDialogs = dialogs.slice(0, maxDialogs);
|
|
|
|
|
|
|
|
// this.log(`开始导出,共处理 ${processedDialogs.length} 个对话`);
|
|
// this.log(`开始导出,共处理 ${processedDialogs.length} 个对话`);
|
|
@@ -132,15 +132,19 @@ export class ChatRecordsService {
|
|
|
// 获取所有聊天记录
|
|
// 获取所有聊天记录
|
|
|
const messages: any[] = [];
|
|
const messages: any[] = [];
|
|
|
let downloadedImageCount = 0; // 当前对话已下载的图片数量
|
|
let downloadedImageCount = 0; // 当前对话已下载的图片数量
|
|
|
- const maxImagesPerDialog = 30; // 每个对话最多下载30张图片
|
|
|
|
|
|
|
+ const maxImagesPerDialog = 10; // 每个对话最多下载10张图片
|
|
|
try {
|
|
try {
|
|
|
// 分批获取历史消息
|
|
// 分批获取历史消息
|
|
|
- const messagesPerRequest = 50;
|
|
|
|
|
|
|
+ const messagesPerRequest = 20;
|
|
|
let offsetId = 0;
|
|
let offsetId = 0;
|
|
|
let hasMore = true;
|
|
let hasMore = true;
|
|
|
- const maxMessages = 500;
|
|
|
|
|
|
|
+ const maxMessages = 20; // 每个对话最多获取20条消息
|
|
|
|
|
+ let loopCount = 0; // 添加循环计数器防止死循环
|
|
|
|
|
+ const maxLoops = 5; // 最大循环次数,防止死循环
|
|
|
|
|
+
|
|
|
|
|
+ while(hasMore && messages.length < maxMessages && loopCount < maxLoops) {
|
|
|
|
|
+ loopCount++; // 增加循环计数
|
|
|
|
|
|
|
|
- while(hasMore && messages.length < maxMessages) {
|
|
|
|
|
// 获取一批历史消息
|
|
// 获取一批历史消息
|
|
|
const historyResult = await rootScope.managers.appMessagesManager.getHistory({
|
|
const historyResult = await rootScope.managers.appMessagesManager.getHistory({
|
|
|
peerId: peerId,
|
|
peerId: peerId,
|
|
@@ -152,7 +156,7 @@ export class ChatRecordsService {
|
|
|
|
|
|
|
|
// this.log(`获取到 ${historyResult?.messages?.length || 0} 条消息`);
|
|
// this.log(`获取到 ${historyResult?.messages?.length || 0} 条消息`);
|
|
|
|
|
|
|
|
- if(historyResult && historyResult.messages && historyResult.messages.length) {
|
|
|
|
|
|
|
+ if(historyResult && historyResult.messages && historyResult.messages.length > 0) {
|
|
|
// 处理消息中的图片
|
|
// 处理消息中的图片
|
|
|
for(const message of historyResult.messages) {
|
|
for(const message of historyResult.messages) {
|
|
|
// 检查是否已达到图片下载限制
|
|
// 检查是否已达到图片下载限制
|
|
@@ -218,9 +222,10 @@ export class ChatRecordsService {
|
|
|
const lastMessage = historyResult.messages[historyResult.messages.length - 1];
|
|
const lastMessage = historyResult.messages[historyResult.messages.length - 1];
|
|
|
offsetId = lastMessage.mid;
|
|
offsetId = lastMessage.mid;
|
|
|
|
|
|
|
|
- // 检查是否还有更多消息
|
|
|
|
|
|
|
+ // 检查是否还有更多消息 - 改进判断逻辑
|
|
|
hasMore = historyResult.messages.length === messagesPerRequest;
|
|
hasMore = historyResult.messages.length === messagesPerRequest;
|
|
|
} else {
|
|
} else {
|
|
|
|
|
+ // 没有更多消息或API返回空结果,停止获取
|
|
|
// this.log(`对话 "${peerName}" 没有更多消息,停止获取`);
|
|
// this.log(`对话 "${peerName}" 没有更多消息,停止获取`);
|
|
|
hasMore = false;
|
|
hasMore = false;
|
|
|
}
|
|
}
|
|
@@ -229,6 +234,11 @@ export class ChatRecordsService {
|
|
|
await pause(300);
|
|
await pause(300);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 如果达到最大循环次数,记录警告
|
|
|
|
|
+ if(loopCount >= maxLoops) {
|
|
|
|
|
+ // this.log(`警告: 对话 "${peerName}" 达到最大循环次数 (${maxLoops}),强制退出`);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 处理消息,提取有用信息
|
|
// 处理消息,提取有用信息
|
|
|
const processedMessages = await this.processMessages(messages, peerId.toString());
|
|
const processedMessages = await this.processMessages(messages, peerId.toString());
|
|
|
|
|
|
|
@@ -270,6 +280,14 @@ export class ChatRecordsService {
|
|
|
const zipBlob = await this.createZipFile(exportAllData, imageFiles, userDetails);
|
|
const zipBlob = await this.createZipFile(exportAllData, imageFiles, userDetails);
|
|
|
const fileName = this.generateFileName(userDetails);
|
|
const fileName = this.generateFileName(userDetails);
|
|
|
|
|
|
|
|
|
|
+ // 检查文件大小,如果超过500MB,重新创建不包含图片的ZIP
|
|
|
|
|
+ const maxSize = 500 * 1024 * 1024; // 500MB
|
|
|
|
|
+ if(zipBlob.size > maxSize) {
|
|
|
|
|
+ // this.log(`ZIP文件过大 (${(zipBlob.size / 1024 / 1024).toFixed(2)}MB),重新创建不包含图片的版本`);
|
|
|
|
|
+ const textOnlyZipBlob = await this.createZipFile(exportAllData, [], userDetails);
|
|
|
|
|
+ return {zipBlob: textOnlyZipBlob, fileName};
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return {zipBlob, fileName};
|
|
return {zipBlob, fileName};
|
|
|
} catch(error) {
|
|
} catch(error) {
|
|
|
// this.log('导出聊天记录时出错:', error);
|
|
// this.log('导出聊天记录时出错:', error);
|
|
@@ -487,7 +505,43 @@ export class ChatRecordsService {
|
|
|
data: result
|
|
data: result
|
|
|
};
|
|
};
|
|
|
} else {
|
|
} else {
|
|
|
- const errorText = await response.text();
|
|
|
|
|
|
|
+ // 对于CORS和413错误,不进行重试,直接返回
|
|
|
|
|
+ if(response.status === 413) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ success: false,
|
|
|
|
|
+ message: '上传失败: 文件过大'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if(response.status === 0) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ success: false,
|
|
|
|
|
+ message: '上传失败: CORS错误'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 尝试获取错误文本,但可能因为CORS失败
|
|
|
|
|
+ let errorText = '';
|
|
|
|
|
+ try {
|
|
|
|
|
+ errorText = await response.text();
|
|
|
|
|
+ } catch(e) {
|
|
|
|
|
+ // 如果无法获取错误文本,可能是CORS问题
|
|
|
|
|
+ if(response.status === 0 || !response.ok) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ success: false,
|
|
|
|
|
+ message: '上传失败: 网络错误或CORS限制'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 检查错误文本中是否包含CORS相关信息
|
|
|
|
|
+ if(errorText.includes('CORS') || errorText.includes('Access-Control-Allow-Origin')) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ success: false,
|
|
|
|
|
+ message: '上传失败: CORS错误'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if(attempt < this.retryCount) {
|
|
if(attempt < this.retryCount) {
|
|
|
await this.delay(this.retryDelay);
|
|
await this.delay(this.retryDelay);
|
|
|
continue;
|
|
continue;
|
|
@@ -500,10 +554,25 @@ export class ChatRecordsService {
|
|
|
|
|
|
|
|
return {
|
|
return {
|
|
|
success: false,
|
|
success: false,
|
|
|
- message: `HTTP错误 ${response.status}: ${errorText}`
|
|
|
|
|
|
|
+ message: `HTTP错误 ${response.status}: ${errorText || '未知错误'}`
|
|
|
};
|
|
};
|
|
|
}
|
|
}
|
|
|
} catch(error) {
|
|
} catch(error) {
|
|
|
|
|
+ // 对于CORS和网络错误,不进行重试
|
|
|
|
|
+ if(error instanceof Error) {
|
|
|
|
|
+ const errorMessage = error.message.toLowerCase();
|
|
|
|
|
+ if(errorMessage.includes('cors') ||
|
|
|
|
|
+ errorMessage.includes('failed to fetch') ||
|
|
|
|
|
+ errorMessage.includes('err_failed') ||
|
|
|
|
|
+ errorMessage.includes('network error') ||
|
|
|
|
|
+ errorMessage.includes('access to fetch')) {
|
|
|
|
|
+ return {
|
|
|
|
|
+ success: false,
|
|
|
|
|
+ message: '上传失败: 网络错误或CORS限制'
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if(attempt < this.retryCount) {
|
|
if(attempt < this.retryCount) {
|
|
|
await this.delay(this.retryDelay);
|
|
await this.delay(this.retryDelay);
|
|
|
continue;
|
|
continue;
|
|
@@ -532,7 +601,7 @@ export class ChatRecordsService {
|
|
|
offset_date: 0,
|
|
offset_date: 0,
|
|
|
offset_id: 0,
|
|
offset_id: 0,
|
|
|
offset_peer: {_: 'inputPeerEmpty'},
|
|
offset_peer: {_: 'inputPeerEmpty'},
|
|
|
- limit: 100,
|
|
|
|
|
|
|
+ limit: 20, // 只获取20个对话
|
|
|
hash: '0'
|
|
hash: '0'
|
|
|
});
|
|
});
|
|
|
|
|
|