qidao-openclaw-plugin 1.3.4 → 2.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth-cli.encrypted.js +8 -0
- package/auth-cli.js +1 -0
- package/config.js +1 -0
- package/device-fingerprint.encrypted.js +8 -0
- package/device-fingerprint.js +1 -0
- package/index.js +1 -0
- package/integrity.json +42 -0
- package/package.json +48 -61
- package/plugin.js +1 -0
- package/qidao-channel.js +1 -0
- package/qr-server.js +259 -0
- package/src/auth-cli.js +0 -175
- package/src/config.js +0 -116
- package/src/index.js +0 -458
- package/src/plugin.js +0 -205
- package/src/qidao-channel.js +0 -446
package/qr-server.js
ADDED
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 本地二维码服务器
|
|
3
|
+
* 用于显示二维码供栖岛APP扫描
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import http from 'http';
|
|
7
|
+
import { URL } from 'url';
|
|
8
|
+
|
|
9
|
+
let server = null;
|
|
10
|
+
let serverPort = null;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 创建本地HTTP服务器显示二维码
|
|
14
|
+
* @param {string} qrUrl - 要生成二维码的URL
|
|
15
|
+
* @returns {Promise<string>} - 本地服务器URL
|
|
16
|
+
*/
|
|
17
|
+
export function createQRServer(qrUrl) {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
// 如果已有服务器在运行,先关闭
|
|
20
|
+
if (server) {
|
|
21
|
+
server.close();
|
|
22
|
+
server = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 查找可用端口
|
|
26
|
+
const tryPort = (port) => {
|
|
27
|
+
server = http.createServer((req, res) => {
|
|
28
|
+
const url = new URL(req.url, `http://localhost:${port}`);
|
|
29
|
+
|
|
30
|
+
if (url.pathname === '/') {
|
|
31
|
+
// 返回二维码页面
|
|
32
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
33
|
+
res.end(generateQRPage(qrUrl));
|
|
34
|
+
} else if (url.pathname === '/favicon.ico') {
|
|
35
|
+
// 忽略favicon请求
|
|
36
|
+
res.writeHead(404);
|
|
37
|
+
res.end();
|
|
38
|
+
} else {
|
|
39
|
+
res.writeHead(404);
|
|
40
|
+
res.end('Not Found');
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
server.on('error', (err) => {
|
|
45
|
+
if (err.code === 'EADDRINUSE') {
|
|
46
|
+
// 端口被占用,尝试下一个端口
|
|
47
|
+
tryPort(port + 1);
|
|
48
|
+
} else {
|
|
49
|
+
reject(err);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
server.listen(port, 'localhost', () => {
|
|
54
|
+
serverPort = port;
|
|
55
|
+
const serverUrl = `http://localhost:${port}`;
|
|
56
|
+
// console.log(`🌐 二维码服务器启动: ${serverUrl}`);
|
|
57
|
+
resolve(serverUrl);
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// 从8080开始尝试端口
|
|
62
|
+
tryPort(8080);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* 生成二维码HTML页面
|
|
68
|
+
* @param {string} qrUrl - 要生成二维码的URL
|
|
69
|
+
* @returns {string} - HTML内容
|
|
70
|
+
*/
|
|
71
|
+
function generateQRPage(qrUrl) {
|
|
72
|
+
const qrApiUrl = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(qrUrl)}`;
|
|
73
|
+
|
|
74
|
+
return `
|
|
75
|
+
<!DOCTYPE html>
|
|
76
|
+
<html lang="zh-CN">
|
|
77
|
+
<head>
|
|
78
|
+
<meta charset="UTF-8">
|
|
79
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
80
|
+
<title>栖岛聊天 - 扫码认证</title>
|
|
81
|
+
<style>
|
|
82
|
+
* {
|
|
83
|
+
margin: 0;
|
|
84
|
+
padding: 0;
|
|
85
|
+
box-sizing: border-box;
|
|
86
|
+
}
|
|
87
|
+
body {
|
|
88
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
89
|
+
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
|
|
90
|
+
min-height: 100vh;
|
|
91
|
+
display: flex;
|
|
92
|
+
justify-content: center;
|
|
93
|
+
align-items: center;
|
|
94
|
+
padding: 20px;
|
|
95
|
+
}
|
|
96
|
+
.container {
|
|
97
|
+
background: #ffffff;
|
|
98
|
+
border-radius: 24px;
|
|
99
|
+
padding: 48px 32px;
|
|
100
|
+
text-align: center;
|
|
101
|
+
box-shadow: 0 25px 50px rgba(0,0,0,0.15), 0 0 0 1px rgba(0,0,0,0.05);
|
|
102
|
+
max-width: 480px;
|
|
103
|
+
width: 100%;
|
|
104
|
+
animation: fadeIn 0.6s ease-out;
|
|
105
|
+
}
|
|
106
|
+
@keyframes fadeIn {
|
|
107
|
+
from { opacity: 0; transform: translateY(20px); }
|
|
108
|
+
to { opacity: 1; transform: translateY(0); }
|
|
109
|
+
}
|
|
110
|
+
.title {
|
|
111
|
+
color: #1a1a2e;
|
|
112
|
+
font-size: 32px;
|
|
113
|
+
font-weight: 700;
|
|
114
|
+
margin-bottom: 8px;
|
|
115
|
+
letter-spacing: 0.5px;
|
|
116
|
+
}
|
|
117
|
+
.subtitle {
|
|
118
|
+
color: #64748b;
|
|
119
|
+
font-size: 17px;
|
|
120
|
+
margin-bottom: 40px;
|
|
121
|
+
font-weight: 400;
|
|
122
|
+
}
|
|
123
|
+
.qr-container {
|
|
124
|
+
background: #f8fafc;
|
|
125
|
+
border-radius: 20px;
|
|
126
|
+
padding: 16px;
|
|
127
|
+
margin: 0 auto 32px;
|
|
128
|
+
display: inline-block;
|
|
129
|
+
border: 1px solid #e2e8f0;
|
|
130
|
+
}
|
|
131
|
+
.qr-image {
|
|
132
|
+
border-radius: 12px;
|
|
133
|
+
box-shadow: 0 8px 20px rgba(0,0,0,0.08);
|
|
134
|
+
display: block;
|
|
135
|
+
width: 200px;
|
|
136
|
+
height: 200px;
|
|
137
|
+
}
|
|
138
|
+
.instructions {
|
|
139
|
+
color: #475569;
|
|
140
|
+
font-size: 15px;
|
|
141
|
+
line-height: 1.7;
|
|
142
|
+
margin-bottom: 28px;
|
|
143
|
+
text-align: left;
|
|
144
|
+
}
|
|
145
|
+
.step {
|
|
146
|
+
margin: 12px 0;
|
|
147
|
+
padding: 14px 0;
|
|
148
|
+
color: #334155;
|
|
149
|
+
font-size: 15px;
|
|
150
|
+
}
|
|
151
|
+
.step strong {
|
|
152
|
+
color: #0f172a;
|
|
153
|
+
font-weight: 600;
|
|
154
|
+
margin-right: 8px;
|
|
155
|
+
}
|
|
156
|
+
.download-link {
|
|
157
|
+
color: #2563eb;
|
|
158
|
+
text-decoration: none;
|
|
159
|
+
font-weight: 500;
|
|
160
|
+
margin-left: 4px;
|
|
161
|
+
}
|
|
162
|
+
.download-link:hover {
|
|
163
|
+
text-decoration: underline;
|
|
164
|
+
}
|
|
165
|
+
.status {
|
|
166
|
+
margin-top: 12px;
|
|
167
|
+
padding: 18px;
|
|
168
|
+
border-radius: 12px;
|
|
169
|
+
background: #f8fafc;
|
|
170
|
+
border: 1px solid #e2e8f0;
|
|
171
|
+
color: #334155;
|
|
172
|
+
font-weight: 500;
|
|
173
|
+
display: flex;
|
|
174
|
+
align-items: center;
|
|
175
|
+
justify-content: center;
|
|
176
|
+
font-size: 15px;
|
|
177
|
+
}
|
|
178
|
+
.loading {
|
|
179
|
+
display: inline-block;
|
|
180
|
+
width: 22px;
|
|
181
|
+
height: 22px;
|
|
182
|
+
border: 3px solid #e2e8f0;
|
|
183
|
+
border-top: 3px solid #2563eb;
|
|
184
|
+
border-radius: 50%;
|
|
185
|
+
animation: spin 1s linear infinite;
|
|
186
|
+
margin-right: 12px;
|
|
187
|
+
}
|
|
188
|
+
@keyframes spin {
|
|
189
|
+
0% { transform: rotate(0deg); }
|
|
190
|
+
100% { transform: rotate(360deg); }
|
|
191
|
+
}
|
|
192
|
+
</style>
|
|
193
|
+
</head>
|
|
194
|
+
<body>
|
|
195
|
+
<div class="container">
|
|
196
|
+
<div class="title">栖岛聊天</div>
|
|
197
|
+
<div class="subtitle">Qidao OpenClaw认证</div>
|
|
198
|
+
|
|
199
|
+
<div class="qr-container">
|
|
200
|
+
<img src="${qrApiUrl}" alt="认证二维码" class="qr-image" id="qrImage" />
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<div class="instructions">
|
|
204
|
+
<div class="step">
|
|
205
|
+
<strong>步骤 1:</strong> 打开栖岛 APP <a href="https://www.qidao.app" target="_blank" class="download-link">未安装?</a></span>
|
|
206
|
+
</div>
|
|
207
|
+
<div class="step">
|
|
208
|
+
<strong>步骤 2:</strong> 使用扫一扫功能扫描上方二维码
|
|
209
|
+
</div>
|
|
210
|
+
<div class="step">
|
|
211
|
+
<strong>步骤 3:</strong> 在栖岛内确认授权
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<div class="status">
|
|
216
|
+
<div class="loading"></div>
|
|
217
|
+
等待扫码中...
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
|
|
221
|
+
<script>
|
|
222
|
+
// 检查二维码图片加载状态
|
|
223
|
+
const qrImage = document.getElementById('qrImage');
|
|
224
|
+
qrImage.onerror = function() {
|
|
225
|
+
this.src = 'data:image/svg+xml;base64,' + btoa(\`
|
|
226
|
+
<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg">
|
|
227
|
+
<rect width="200" height="200" fill="#f8f9fa"/>
|
|
228
|
+
<text x="100" y="90" text-anchor="middle" font-family="Arial" font-size="14" fill="#666">
|
|
229
|
+
二维码加载失败
|
|
230
|
+
</text>
|
|
231
|
+
<text x="100" y="115" text-anchor="middle" font-family="Arial" font-size="12" fill="#999">
|
|
232
|
+
请手动复制URL到栖岛内打开
|
|
233
|
+
</text>
|
|
234
|
+
</svg>
|
|
235
|
+
\`);
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// 自动刷新页面(可选)
|
|
239
|
+
setTimeout(() => {
|
|
240
|
+
console.log('二维码页面已显示');
|
|
241
|
+
}, 1000);
|
|
242
|
+
</script>
|
|
243
|
+
</body>
|
|
244
|
+
</html>
|
|
245
|
+
`;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* 关闭二维码服务器
|
|
250
|
+
*/
|
|
251
|
+
export function closeQRServer() {
|
|
252
|
+
if (server) {
|
|
253
|
+
server.close();
|
|
254
|
+
server = null;
|
|
255
|
+
serverPort = null;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export default { createQRServer, closeQRServer };
|
package/src/auth-cli.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 栖岛聊天认证 CLI 命令
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import ws from 'ws';
|
|
6
|
-
import { spawn } from 'child_process';
|
|
7
|
-
|
|
8
|
-
export function registerAuthCommand(api) {
|
|
9
|
-
api.registerCli(
|
|
10
|
-
({ program }) => {
|
|
11
|
-
program
|
|
12
|
-
.command('qidao-auth')
|
|
13
|
-
.description('栖岛聊天二维码认证')
|
|
14
|
-
.action(async () => {
|
|
15
|
-
console.log('');
|
|
16
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
17
|
-
console.log('');
|
|
18
|
-
console.log(' 🔐 栖岛聊天二维码认证');
|
|
19
|
-
console.log('');
|
|
20
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
21
|
-
console.log('');
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
// 创建临时连接到 Server 进行认证
|
|
25
|
-
const tempWs = new ws('wss://oc.qidao.chat/ws');
|
|
26
|
-
|
|
27
|
-
const chatId = await new Promise((resolve, reject) => {
|
|
28
|
-
const timeout = setTimeout(() => {
|
|
29
|
-
tempWs.close();
|
|
30
|
-
reject(new Error('连接超时'));
|
|
31
|
-
}, 10000);
|
|
32
|
-
|
|
33
|
-
tempWs.on('open', () => {
|
|
34
|
-
clearTimeout(timeout);
|
|
35
|
-
console.log('✅ 已连接到认证服务器');
|
|
36
|
-
console.log('');
|
|
37
|
-
|
|
38
|
-
// 请求生成二维码
|
|
39
|
-
tempWs.send(JSON.stringify({ action: 'startAuth' }));
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
tempWs.on('message', async (data) => {
|
|
43
|
-
try {
|
|
44
|
-
const message = JSON.parse(data.toString());
|
|
45
|
-
|
|
46
|
-
// 兼容Server的响应格式
|
|
47
|
-
// 格式1: { id, code: 1, msg, data: { code, qrUrl } }
|
|
48
|
-
// 格式2: { action: 'authStarted', code, qrUrl }
|
|
49
|
-
if ((message.code === 1 && message.data && message.data.qrUrl) ||
|
|
50
|
-
(message.action === 'authStarted')) {
|
|
51
|
-
const code = message.data?.code || message.code;
|
|
52
|
-
const qrUrl = message.data?.qrUrl || message.qrUrl;
|
|
53
|
-
|
|
54
|
-
console.log('📱 请使用栖岛 APP 扫描二维码:');
|
|
55
|
-
console.log('');
|
|
56
|
-
console.log(` ${qrUrl}`);
|
|
57
|
-
console.log('');
|
|
58
|
-
console.log('正在打开浏览器...');
|
|
59
|
-
console.log('');
|
|
60
|
-
|
|
61
|
-
// 打开浏览器显示二维码
|
|
62
|
-
const openCommand = process.platform === 'win32' ? 'start' :
|
|
63
|
-
process.platform === 'darwin' ? 'open' : 'xdg-open';
|
|
64
|
-
spawn(openCommand, [qrUrl], { shell: true, detached: true });
|
|
65
|
-
|
|
66
|
-
console.log('⏳ 等待扫码...');
|
|
67
|
-
console.log('');
|
|
68
|
-
|
|
69
|
-
// 开始轮询扫码状态
|
|
70
|
-
const pollInterval = setInterval(() => {
|
|
71
|
-
tempWs.send(JSON.stringify({ action: 'checkAuthStatus', code }));
|
|
72
|
-
}, 2000);
|
|
73
|
-
|
|
74
|
-
// 保存轮询定时器以便后续清理
|
|
75
|
-
tempWs._pollInterval = pollInterval;
|
|
76
|
-
tempWs._code = code;
|
|
77
|
-
|
|
78
|
-
} else if ((message.code === 1 && message.data && message.data.status) ||
|
|
79
|
-
(message.action === 'authStatus')) {
|
|
80
|
-
// 兼容两种格式的扫码状态响应
|
|
81
|
-
const status = message.data?.status || message.status;
|
|
82
|
-
const uid = message.data?.uid || message.uid;
|
|
83
|
-
|
|
84
|
-
if (status === 'success') {
|
|
85
|
-
console.log('✅ 扫码成功!');
|
|
86
|
-
console.log('');
|
|
87
|
-
|
|
88
|
-
// 请求完成认证获取 chatId
|
|
89
|
-
tempWs.send(JSON.stringify({
|
|
90
|
-
action: 'completeAuth',
|
|
91
|
-
uid,
|
|
92
|
-
code: tempWs._code
|
|
93
|
-
}));
|
|
94
|
-
|
|
95
|
-
} else if (status === 'waiting') {
|
|
96
|
-
// 继续等待
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
} else if ((message.code === 1 && message.data && message.data.chatId) ||
|
|
100
|
-
(message.action === 'authCompleted')) {
|
|
101
|
-
// 清理轮询定时器
|
|
102
|
-
if (tempWs._pollInterval) {
|
|
103
|
-
clearInterval(tempWs._pollInterval);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const receivedChatId = message.data?.chatId || message.chatId;
|
|
107
|
-
console.log(`🎉 认证完成!您的 chatId: ${receivedChatId}`);
|
|
108
|
-
console.log('');
|
|
109
|
-
|
|
110
|
-
tempWs.close();
|
|
111
|
-
resolve(receivedChatId);
|
|
112
|
-
|
|
113
|
-
} else if (message.code === 0 || message.action === 'error') {
|
|
114
|
-
if (tempWs._pollInterval) {
|
|
115
|
-
clearInterval(tempWs._pollInterval);
|
|
116
|
-
}
|
|
117
|
-
tempWs.close();
|
|
118
|
-
const errorMsg = message.msg || message.message || '认证失败';
|
|
119
|
-
reject(new Error(errorMsg));
|
|
120
|
-
}
|
|
121
|
-
} catch (err) {
|
|
122
|
-
console.error('处理消息失败:', err);
|
|
123
|
-
reject(err);
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
tempWs.on('error', (error) => {
|
|
128
|
-
clearTimeout(timeout);
|
|
129
|
-
if (tempWs._pollInterval) {
|
|
130
|
-
clearInterval(tempWs._pollInterval);
|
|
131
|
-
}
|
|
132
|
-
reject(error);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// 自动保存配置
|
|
137
|
-
console.log('正在保存配置...');
|
|
138
|
-
console.log('');
|
|
139
|
-
|
|
140
|
-
const { execSync } = await import('child_process');
|
|
141
|
-
execSync(`openclaw config set channels.qidao.chatId ${chatId}`, { stdio: 'inherit' });
|
|
142
|
-
execSync(`openclaw config set channels.qidao.enabled true`, { stdio: 'inherit' });
|
|
143
|
-
|
|
144
|
-
console.log('');
|
|
145
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
146
|
-
console.log('');
|
|
147
|
-
console.log(' ✅ 配置完成!');
|
|
148
|
-
console.log('');
|
|
149
|
-
console.log(' 请重启 Gateway 以应用配置:');
|
|
150
|
-
console.log('');
|
|
151
|
-
console.log(' openclaw gateway restart');
|
|
152
|
-
console.log('');
|
|
153
|
-
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
154
|
-
console.log('');
|
|
155
|
-
|
|
156
|
-
} catch (error) {
|
|
157
|
-
console.error('');
|
|
158
|
-
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
159
|
-
console.error('');
|
|
160
|
-
console.error(' ❌ 认证失败:', error.message);
|
|
161
|
-
console.error('');
|
|
162
|
-
console.error(' 请重试或手动配置:');
|
|
163
|
-
console.error('');
|
|
164
|
-
console.error(' openclaw config set channels.qidao.chatId <您的chatId>');
|
|
165
|
-
console.error(' openclaw config set channels.qidao.enabled true');
|
|
166
|
-
console.error('');
|
|
167
|
-
console.error('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
168
|
-
console.error('');
|
|
169
|
-
process.exit(1);
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
},
|
|
173
|
-
{ commands: ['qidao-auth'] }
|
|
174
|
-
);
|
|
175
|
-
}
|
package/src/config.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 栖岛插件配置文件
|
|
3
|
-
* 统一管理所有API地址和配置项
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export const QIDAO_CONFIG = {
|
|
7
|
-
// 服务器地址配置
|
|
8
|
-
SERVER: {
|
|
9
|
-
// 生产环境
|
|
10
|
-
PRODUCTION: {
|
|
11
|
-
WS_URL: 'wss://oc.qidao.chat/ws',
|
|
12
|
-
HTTP_URL: 'https://oc.qidao.chat',
|
|
13
|
-
HEALTH_CHECK: 'https://oc.qidao.chat/health'
|
|
14
|
-
},
|
|
15
|
-
|
|
16
|
-
// 开发环境
|
|
17
|
-
DEVELOPMENT: {
|
|
18
|
-
WS_URL: 'wss://oc.qidao.chat/ws',
|
|
19
|
-
HTTP_URL: 'https://oc.qidao.chat',
|
|
20
|
-
HEALTH_CHECK: 'https://oc.qidao.chat/health'
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
// 栖岛官方API
|
|
25
|
-
QIDAO_API: {
|
|
26
|
-
BASE_URL: 'https://api.qidao.tvcloud.top',
|
|
27
|
-
WS_CONNECT: 'wss://api.qidao.tvcloud.top/ws/connect',
|
|
28
|
-
ENDPOINTS: {
|
|
29
|
-
SEND_MESSAGE: '/websocket/im/sendMessage',
|
|
30
|
-
ONLINE_USERS: '/websocket/im/chatRoomOnlineUsers',
|
|
31
|
-
USER_STATUS: '/websocket/im/userOnlineStatus',
|
|
32
|
-
CREATE_CHAT: '/websocket/im/createChat',
|
|
33
|
-
IM_STATS: '/websocket/im/stats'
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
// 默认配置
|
|
38
|
-
DEFAULTS: {
|
|
39
|
-
RECONNECT_INTERVAL: 5000,
|
|
40
|
-
REQUEST_TIMEOUT: 30000,
|
|
41
|
-
MAX_RECONNECT_ATTEMPTS: 10,
|
|
42
|
-
DEBUG: false,
|
|
43
|
-
AUTO_CONNECT: true
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
// 消息类型
|
|
47
|
-
MESSAGE_TYPES: {
|
|
48
|
-
TEXT: 0,
|
|
49
|
-
IMAGE: 1,
|
|
50
|
-
FILE: 2,
|
|
51
|
-
SYSTEM: 99
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
// 聊天类型
|
|
55
|
-
CHAT_TYPES: {
|
|
56
|
-
PRIVATE: 0,
|
|
57
|
-
GROUP: 1
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
// 事件类型
|
|
61
|
-
EVENTS: {
|
|
62
|
-
CONNECTED: 'connected',
|
|
63
|
-
DISCONNECTED: 'disconnected',
|
|
64
|
-
MESSAGE: 'message',
|
|
65
|
-
MESSAGE_SENT: 'messageSent',
|
|
66
|
-
MESSAGE_FAILED: 'messageFailed',
|
|
67
|
-
CHAT_CREATED: 'chatCreated',
|
|
68
|
-
ERROR: 'error',
|
|
69
|
-
RECONNECTING: 'reconnecting',
|
|
70
|
-
RECONNECTED: 'reconnected'
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* 获取当前环境配置
|
|
76
|
-
*/
|
|
77
|
-
export function getCurrentConfig(env = 'production') {
|
|
78
|
-
const environment = env.toLowerCase();
|
|
79
|
-
|
|
80
|
-
if (environment === 'development' || environment === 'dev') {
|
|
81
|
-
return QIDAO_CONFIG.SERVER.DEVELOPMENT;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return QIDAO_CONFIG.SERVER.PRODUCTION;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* 获取完整的WebSocket URL
|
|
89
|
-
*/
|
|
90
|
-
export function getWebSocketUrl(env = 'production') {
|
|
91
|
-
return getCurrentConfig(env).WS_URL;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* 获取HTTP API基础URL
|
|
96
|
-
*/
|
|
97
|
-
export function getHttpUrl(env = 'production') {
|
|
98
|
-
return getCurrentConfig(env).HTTP_URL;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* 获取健康检查URL
|
|
103
|
-
*/
|
|
104
|
-
export function getHealthCheckUrl(env = 'production') {
|
|
105
|
-
return getCurrentConfig(env).HEALTH_CHECK;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* 构建API端点URL
|
|
110
|
-
*/
|
|
111
|
-
export function buildApiUrl(endpoint, env = 'production') {
|
|
112
|
-
const baseUrl = getHttpUrl(env);
|
|
113
|
-
return `${baseUrl}/api${endpoint}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export default QIDAO_CONFIG;
|