Upload 14 files
Browse files- src/lightweight-client.js +85 -121
src/lightweight-client.js
CHANGED
|
@@ -30,6 +30,11 @@ const logger = {
|
|
| 30 |
|
| 31 |
// 配置
|
| 32 |
const NOTION_API_URL = "https://www.notion.so/api/v3/runInferenceTranscript";
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
let NOTION_COOKIE = '';
|
| 34 |
let NOTION_SPACE_ID = process.env.NOTION_SPACE_ID;
|
| 35 |
let FETCHED_NOTION_USER_ID = process.env.NOTION_ACTIVE_USER_HEADER;
|
|
@@ -73,20 +78,12 @@ process.on('exit', () => {
|
|
| 73 |
});
|
| 74 |
|
| 75 |
function getCookie() {
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
let cookiePairs = cookies.split('|');
|
| 79 |
-
if (cookiePairs.length > 1){
|
| 80 |
-
isMoreThanOne=true;
|
| 81 |
-
}
|
| 82 |
-
let currentIndex = index;
|
| 83 |
-
index++;
|
| 84 |
-
if (index >= cookiePairs.length) {
|
| 85 |
-
index = 0;
|
| 86 |
-
}
|
| 87 |
-
return cookiePairs[currentIndex];
|
| 88 |
}
|
| 89 |
-
|
|
|
|
|
|
|
| 90 |
}
|
| 91 |
|
| 92 |
// 添加一个通用的cookie解析函数
|
|
@@ -136,8 +133,8 @@ function parseCookiesFromString(cookieString, logPrefix = "") {
|
|
| 136 |
}
|
| 137 |
|
| 138 |
// 获取Notion空间ID和用户ID
|
| 139 |
-
async function fetchAndSetNotionIds() {
|
| 140 |
-
if (!
|
| 141 |
logger.error(`无法获取Notion ID: 未设置NOTION_COOKIE`);
|
| 142 |
FETCHED_IDS_SUCCESSFULLY = false;
|
| 143 |
return;
|
|
@@ -188,7 +185,7 @@ async function fetchAndSetNotionIds() {
|
|
| 188 |
}
|
| 189 |
|
| 190 |
// 设置cookie
|
| 191 |
-
document.cookie =
|
| 192 |
|
| 193 |
// 创建fetch选项
|
| 194 |
const fetchOptions = {
|
|
@@ -202,7 +199,7 @@ async function fetchAndSetNotionIds() {
|
|
| 202 |
'origin': 'https://www.notion.so',
|
| 203 |
'referer': 'https://www.notion.so/',
|
| 204 |
'user-agent': window.navigator.userAgent,
|
| 205 |
-
'Cookie':
|
| 206 |
},
|
| 207 |
body: JSON.stringify({}),
|
| 208 |
};
|
|
@@ -280,6 +277,7 @@ async function fetchAndSetNotionIds() {
|
|
| 280 |
logger.warning(`清理全局对象时出错: ${cleanupError.message}`);
|
| 281 |
}
|
| 282 |
|
|
|
|
| 283 |
} catch (error) {
|
| 284 |
logger.error(`获取Notion ID时出错: ${error}`);
|
| 285 |
FETCHED_IDS_SUCCESSFULLY = false;
|
|
@@ -429,80 +427,44 @@ function buildNotionRequest(requestData) {
|
|
| 429 |
|
| 430 |
// 流式处理Notion响应
|
| 431 |
async function streamNotionResponse(notionRequestBody) {
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
'Content-Type': 'application/json',
|
| 441 |
-
'accept': 'application/x-ndjson',
|
| 442 |
-
'accept-language': 'en-US,en;q=0.9',
|
| 443 |
-
'notion-audit-log-platform': 'web',
|
| 444 |
-
'notion-client-version': '23.13.0.3686',
|
| 445 |
-
'origin': 'https://www.notion.so',
|
| 446 |
-
'referer': 'https://www.notion.so/chat',
|
| 447 |
-
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36',
|
| 448 |
-
'x-notion-active-user-header': FETCHED_NOTION_USER_ID,
|
| 449 |
-
'x-notion-space-id': NOTION_SPACE_ID
|
| 450 |
-
};
|
| 451 |
-
|
| 452 |
-
// 设置超时处理,确保流不会无限等待
|
| 453 |
-
const timeoutId = setTimeout(() => {
|
| 454 |
-
logger.warning(`请求超时,30秒内未收到响应`);
|
| 455 |
-
try {
|
| 456 |
-
// 发送结束消息
|
| 457 |
-
const endChunk = new ChatCompletionChunk({
|
| 458 |
-
choices: [
|
| 459 |
-
new Choice({
|
| 460 |
-
delta: new ChoiceDelta({ content: "请求超时,未收到Notion响应。" }),
|
| 461 |
-
finish_reason: "timeout"
|
| 462 |
-
})
|
| 463 |
-
]
|
| 464 |
-
});
|
| 465 |
-
stream.write(`data: ${JSON.stringify(endChunk)}\n\n`);
|
| 466 |
-
stream.write('data: [DONE]\n\n');
|
| 467 |
-
stream.end();
|
| 468 |
-
} catch (error) {
|
| 469 |
-
logger.error(`发送超时消息时出错: ${error}`);
|
| 470 |
-
stream.end();
|
| 471 |
}
|
| 472 |
-
|
| 473 |
-
|
| 474 |
-
|
| 475 |
-
|
| 476 |
-
|
| 477 |
-
|
| 478 |
-
|
| 479 |
-
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
logger.error(`流处理出错: ${error}`);
|
| 484 |
-
clearTimeout(timeoutId); // 清除超时计时器
|
| 485 |
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
| 491 |
-
|
| 492 |
-
|
| 493 |
-
|
| 494 |
-
|
| 495 |
-
|
| 496 |
-
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
|
| 500 |
-
|
| 501 |
-
|
| 502 |
-
|
| 503 |
-
});
|
| 504 |
-
|
| 505 |
-
return stream;
|
| 506 |
}
|
| 507 |
|
| 508 |
// 使用fetch调用Notion API并处理流式响应
|
|
@@ -891,41 +853,43 @@ async function initialize() {
|
|
| 891 |
logger.error(`启动代理服务器失败: ${error.message}`);
|
| 892 |
}
|
| 893 |
|
| 894 |
-
//
|
| 895 |
-
|
| 896 |
-
|
| 897 |
-
|
| 898 |
-
|
| 899 |
-
|
| 900 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 901 |
FETCHED_IDS_SUCCESSFULLY = true;
|
|
|
|
| 902 |
} else {
|
| 903 |
-
|
| 904 |
-
NOTION_COOKIE = getCookie(); // 获取第一个cookie
|
| 905 |
-
if (!NOTION_COOKIE) {
|
| 906 |
-
logger.error(`错误: 未设置NOTION_COOKIE环境变量,应用无法正常工作`);
|
| 907 |
-
logger.error(`请在.env文件中设置有效的NOTION_COOKIE值`);
|
| 908 |
-
return;
|
| 909 |
-
}
|
| 910 |
-
|
| 911 |
-
logger.info(`未检测到ID配置,正在通过API自动获取Notion ID...`);
|
| 912 |
-
await fetchAndSetNotionIds();
|
| 913 |
-
|
| 914 |
-
if (!FETCHED_IDS_SUCCESSFULLY) {
|
| 915 |
-
logger.error(`获取Notion ID失败,应用无法正常工作`);
|
| 916 |
-
logger.error(`请检查以下可能的问题:`);
|
| 917 |
-
logger.error(`1. NOTION_COOKIE是否有效`);
|
| 918 |
-
logger.error(`2. 网络连接是否正常`);
|
| 919 |
-
logger.error(`3. Notion服务是否可访问`);
|
| 920 |
-
logger.error(`或者手动在.env文件中设置NOTION_SPACE_ID和NOTION_ACTIVE_USER_HEADER`);
|
| 921 |
-
} else {
|
| 922 |
-
logger.info(`成功通过API获取Notion ID
|
| 923 |
-
- 用户ID: ${FETCHED_NOTION_USER_ID}
|
| 924 |
-
- 空间ID: ${NOTION_SPACE_ID}`);
|
| 925 |
-
// logger.info(`- 用户ID: ${FETCHED_NOTION_USER_ID}`);
|
| 926 |
-
// logger.info(`- 空间ID: ${NOTION_SPACE_ID}`);
|
| 927 |
-
}
|
| 928 |
}
|
|
|
|
| 929 |
if (process.env.USE_NATIVE_PROXY_POOL === 'true') {
|
| 930 |
logger.info(`正在初始化本地代理池...`);
|
| 931 |
await proxyPool.initialize();
|
|
|
|
| 30 |
|
| 31 |
// 配置
|
| 32 |
const NOTION_API_URL = "https://www.notion.so/api/v3/runInferenceTranscript";
|
| 33 |
+
let NOTION_COOKIES = [];
|
| 34 |
+
let NOTION_SPACE_IDS = {};
|
| 35 |
+
let NOTION_USER_IDS = {};
|
| 36 |
+
let currentCookieIndex = 0;
|
| 37 |
+
|
| 38 |
let NOTION_COOKIE = '';
|
| 39 |
let NOTION_SPACE_ID = process.env.NOTION_SPACE_ID;
|
| 40 |
let FETCHED_NOTION_USER_ID = process.env.NOTION_ACTIVE_USER_HEADER;
|
|
|
|
| 78 |
});
|
| 79 |
|
| 80 |
function getCookie() {
|
| 81 |
+
if (NOTION_COOKIES.length === 0) {
|
| 82 |
+
return '';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
}
|
| 84 |
+
const cookie = NOTION_COOKIES[currentCookieIndex];
|
| 85 |
+
currentCookieIndex = (currentCookieIndex + 1) % NOTION_COOKIES.length;
|
| 86 |
+
return cookie;
|
| 87 |
}
|
| 88 |
|
| 89 |
// 添加一个通用的cookie解析函数
|
|
|
|
| 133 |
}
|
| 134 |
|
| 135 |
// 获取Notion空间ID和用户ID
|
| 136 |
+
async function fetchAndSetNotionIds(cookie) {
|
| 137 |
+
if (!cookie) {
|
| 138 |
logger.error(`无法获取Notion ID: 未设置NOTION_COOKIE`);
|
| 139 |
FETCHED_IDS_SUCCESSFULLY = false;
|
| 140 |
return;
|
|
|
|
| 185 |
}
|
| 186 |
|
| 187 |
// 设置cookie
|
| 188 |
+
document.cookie = cookie;
|
| 189 |
|
| 190 |
// 创建fetch选项
|
| 191 |
const fetchOptions = {
|
|
|
|
| 199 |
'origin': 'https://www.notion.so',
|
| 200 |
'referer': 'https://www.notion.so/',
|
| 201 |
'user-agent': window.navigator.userAgent,
|
| 202 |
+
'Cookie': cookie
|
| 203 |
},
|
| 204 |
body: JSON.stringify({}),
|
| 205 |
};
|
|
|
|
| 277 |
logger.warning(`清理全局对象时出错: ${cleanupError.message}`);
|
| 278 |
}
|
| 279 |
|
| 280 |
+
return { spaceId: NOTION_SPACE_ID, userId: userIdKey };
|
| 281 |
} catch (error) {
|
| 282 |
logger.error(`获取Notion ID时出错: ${error}`);
|
| 283 |
FETCHED_IDS_SUCCESSFULLY = false;
|
|
|
|
| 427 |
|
| 428 |
// 流式处理Notion响应
|
| 429 |
async function streamNotionResponse(notionRequestBody) {
|
| 430 |
+
const chunkQueue = new PassThrough();
|
| 431 |
+
let timeoutId = null;
|
| 432 |
+
|
| 433 |
+
try {
|
| 434 |
+
// 动态获取cookie
|
| 435 |
+
const currentCookie = getCookie();
|
| 436 |
+
if (!currentCookie) {
|
| 437 |
+
throw new Error("无法获取 Notion cookie");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
}
|
| 439 |
+
NOTION_COOKIE = currentCookie; // 更新当前使用的cookie
|
| 440 |
+
|
| 441 |
+
// 获取对应的 space_id 和 user_id
|
| 442 |
+
notionRequestBody.spaceId = NOTION_SPACE_IDS[currentCookie];
|
| 443 |
+
const headers = {
|
| 444 |
+
'Content-Type': 'application/json',
|
| 445 |
+
'Cookie': currentCookie,
|
| 446 |
+
'x-notion-active-user-header': NOTION_USER_IDS[currentCookie],
|
| 447 |
+
"accept": "application/json",
|
| 448 |
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36"
|
| 449 |
+
};
|
|
|
|
|
|
|
| 450 |
|
| 451 |
+
fetchNotionResponse(chunkQueue, notionRequestBody, headers, NOTION_API_URL, currentCookie, timeoutId);
|
| 452 |
+
} catch (error) {
|
| 453 |
+
logger.error(`streamNotionResponse 错误: ${error}`);
|
| 454 |
+
const errorChunk = new ChatCompletionChunk({
|
| 455 |
+
choices: [
|
| 456 |
+
new Choice({
|
| 457 |
+
delta: new ChoiceDelta({ content: `处理流式响应时出错: ${error.message}` }),
|
| 458 |
+
finish_reason: "error"
|
| 459 |
+
})
|
| 460 |
+
]
|
| 461 |
+
});
|
| 462 |
+
chunkQueue.write(`data: ${JSON.stringify(errorChunk)}\n\n`);
|
| 463 |
+
chunkQueue.write('data: [DONE]\n\n');
|
| 464 |
+
chunkQueue.end();
|
| 465 |
+
}
|
| 466 |
+
|
| 467 |
+
return chunkQueue;
|
|
|
|
|
|
|
|
|
|
| 468 |
}
|
| 469 |
|
| 470 |
// 使用fetch调用Notion API并处理流式响应
|
|
|
|
| 853 |
logger.error(`启动代理服务器失败: ${error.message}`);
|
| 854 |
}
|
| 855 |
|
| 856 |
+
// 从环境变量加载所有 cookies
|
| 857 |
+
const cookiesEnv = process.env.NOTION_COOKIE;
|
| 858 |
+
if (!cookiesEnv) {
|
| 859 |
+
logger.error(`错误: 未设置NOTION_COOKIE环境变量,应用无法正常工作`);
|
| 860 |
+
return;
|
| 861 |
+
}
|
| 862 |
+
NOTION_COOKIES = cookiesEnv.split('|').map(c => c.trim()).filter(c => c);
|
| 863 |
+
|
| 864 |
+
if (NOTION_COOKIES.length === 0) {
|
| 865 |
+
logger.error(`错误: NOTION_COOKIE环境变量中未找到有效cookie`);
|
| 866 |
+
return;
|
| 867 |
+
}
|
| 868 |
+
|
| 869 |
+
logger.info(`共找到 ${NOTION_COOKIES.length} 个 Notion cookie,正在逐个获取 ID...`);
|
| 870 |
+
|
| 871 |
+
let successfulCookies = 0;
|
| 872 |
+
for (const cookie of NOTION_COOKIES) {
|
| 873 |
+
try {
|
| 874 |
+
const ids = await fetchAndSetNotionIds(cookie);
|
| 875 |
+
if (ids) {
|
| 876 |
+
NOTION_SPACE_IDS[cookie] = ids.spaceId;
|
| 877 |
+
NOTION_USER_IDS[cookie] = ids.userId;
|
| 878 |
+
logger.success(`成功获取 cookie 的 ID: ...${cookie.slice(-10)}`);
|
| 879 |
+
successfulCookies++;
|
| 880 |
+
}
|
| 881 |
+
} catch (error) {
|
| 882 |
+
logger.error(`获取 cookie 的 ID 失败: ...${cookie.slice(-10)} - ${error.message}`);
|
| 883 |
+
}
|
| 884 |
+
}
|
| 885 |
+
|
| 886 |
+
if (successfulCookies > 0) {
|
| 887 |
FETCHED_IDS_SUCCESSFULLY = true;
|
| 888 |
+
logger.success(`成功初始化 ${successfulCookies} 个 Notion 账号`);
|
| 889 |
} else {
|
| 890 |
+
logger.error(`所有 Notion cookie 均无法成功初始化,应用可能无法正常工作`);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 891 |
}
|
| 892 |
+
|
| 893 |
if (process.env.USE_NATIVE_PROXY_POOL === 'true') {
|
| 894 |
logger.info(`正在初始化本地代理池...`);
|
| 895 |
await proxyPool.initialize();
|