x3ui-api 1.0.3 → 1.0.4
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/README.md +174 -26
- package/package.json +1 -1
- package/src/core/ClientBuilder.d.ts +37 -0
- package/src/core/ClientBuilder.js +57 -0
- package/src/core/IndoundBuilder.d.ts +1 -0
- package/src/core/X3UIClient.d.ts +31 -0
- package/src/core/X3UIClient.js +147 -0
- package/src/index.d.ts +12 -148
- package/src/index.d.ts~ +185 -0
- package/src/index.js +2 -455
- package/src/protocols/vless/RealityBuilder.d.ts +69 -0
- package/src/protocols/vless/RealityBuilder.js +223 -0
- package/src/protocols/vless/RealityClientBuilder.d.ts +11 -0
- package/src/protocols/vless/RealityClientBuilder.js +25 -0
- package/src/protocols/vless/index.d.ts +9 -0
- package/src/protocols/vless/index.js +4 -0
- package/src/protocols/vmess/VmessBuilder.d.ts +77 -0
- package/src/protocols/vmess/VmessBuilder.js +189 -0
- package/src/protocols/vmess/VmessClientBuilder.d.ts +13 -0
- package/src/protocols/vmess/VmessClientBuilder.js +92 -0
- package/src/protocols/vmess/index.d.ts +9 -0
- package/src/protocols/vmess/index.js +4 -0
package/README.md
CHANGED
|
@@ -13,7 +13,9 @@ npm install x3ui-api
|
|
|
13
13
|
- Authentication with x3ui panel
|
|
14
14
|
- Get system statistics (CPU, memory, network, etc.)
|
|
15
15
|
- Manage inbounds (list, add, update, delete)
|
|
16
|
-
-
|
|
16
|
+
- Protocol-specific builders with fluent API:
|
|
17
|
+
- VLESS with Reality support
|
|
18
|
+
- VMess with HTTP Upgrade support
|
|
17
19
|
- Client management with fluent API
|
|
18
20
|
- TypeScript support
|
|
19
21
|
|
|
@@ -59,15 +61,72 @@ async function main() {
|
|
|
59
61
|
main();
|
|
60
62
|
```
|
|
61
63
|
|
|
62
|
-
### Creating a
|
|
64
|
+
### Creating a VMess Inbound
|
|
65
|
+
|
|
66
|
+
The library provides a convenient builder pattern for creating VMess inbounds with HTTP Upgrade:
|
|
67
|
+
|
|
68
|
+
```javascript
|
|
69
|
+
const X3UIClient = require('x3ui-api');
|
|
70
|
+
const vmess = require('x3ui-api/src/protocols/vmess');
|
|
71
|
+
|
|
72
|
+
const client = new X3UIClient({
|
|
73
|
+
baseURL: 'http://your-x3ui-panel.com:54321'
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
async function createVmessInbound() {
|
|
77
|
+
try {
|
|
78
|
+
await client.login('admin', 'password');
|
|
79
|
+
|
|
80
|
+
// Create a VMess inbound builder
|
|
81
|
+
let builder = new vmess.VmessBuilder(client)
|
|
82
|
+
.setRemark('My VMess Inbound')
|
|
83
|
+
.setPort(8443) // Optional, will auto-generate if not provided
|
|
84
|
+
.setHttpUpgradeHost('your-domain.com');
|
|
85
|
+
|
|
86
|
+
// Add a client
|
|
87
|
+
builder.addClient()
|
|
88
|
+
.setEmail('user@example.com')
|
|
89
|
+
.setTotalGB(100) // 100 GB traffic limit
|
|
90
|
+
.setExpiryTime(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30 days
|
|
91
|
+
|
|
92
|
+
// Build and add the inbound
|
|
93
|
+
const inbound = await builder.build();
|
|
94
|
+
const createdInbound = await client.addInbound(inbound);
|
|
95
|
+
|
|
96
|
+
// Update the builder with the server-returned inbound to get all metrics and IDs
|
|
97
|
+
builder = new vmess.VmessBuilder(client, createdInbound);
|
|
98
|
+
|
|
99
|
+
console.log('Inbound created:', createdInbound);
|
|
100
|
+
|
|
101
|
+
// Get connection link for the client (now with accurate server-assigned values)
|
|
102
|
+
const link = builder.getClientLink(0, 'your-server-ip.com');
|
|
103
|
+
console.log('Client connection link:', link);
|
|
104
|
+
} catch (error) {
|
|
105
|
+
console.error('Error creating inbound:', error.message);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
createVmessInbound();
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Creating a VLESS Reality Inbound
|
|
63
113
|
|
|
64
114
|
The library provides a convenient builder pattern for creating Reality inbounds:
|
|
65
115
|
|
|
66
116
|
```javascript
|
|
117
|
+
const X3UIClient = require('x3ui-api');
|
|
118
|
+
const vless = require('x3ui-api/src/protocols/vless');
|
|
119
|
+
|
|
120
|
+
const client = new X3UIClient({
|
|
121
|
+
baseURL: 'http://your-x3ui-panel.com:54321'
|
|
122
|
+
});
|
|
123
|
+
|
|
67
124
|
async function createRealityInbound() {
|
|
68
125
|
try {
|
|
126
|
+
await client.login('admin', 'password');
|
|
127
|
+
|
|
69
128
|
// Create a Reality inbound builder
|
|
70
|
-
|
|
129
|
+
let builder = new vless.RealityBuilder(client, {
|
|
71
130
|
remark: 'My Reality Inbound',
|
|
72
131
|
port: 8443 // Optional, will auto-generate if not provided
|
|
73
132
|
});
|
|
@@ -79,18 +138,21 @@ async function createRealityInbound() {
|
|
|
79
138
|
.setFingerprint('chrome');
|
|
80
139
|
|
|
81
140
|
// Add a client
|
|
82
|
-
|
|
141
|
+
builder.addClient()
|
|
83
142
|
.setEmail('user@example.com')
|
|
84
143
|
.setTotalGB(100) // 100 GB traffic limit
|
|
85
144
|
.setExpiryTime(Date.now() + 30 * 24 * 60 * 60 * 1000); // 30 days
|
|
86
145
|
|
|
87
146
|
// Build and add the inbound
|
|
88
147
|
const inbound = await builder.build();
|
|
89
|
-
const
|
|
148
|
+
const createdInbound = await client.addInbound(inbound);
|
|
90
149
|
|
|
91
|
-
|
|
150
|
+
// Update the builder with the server-returned inbound to get all metrics and IDs
|
|
151
|
+
builder = new vless.RealityBuilder(client, createdInbound);
|
|
92
152
|
|
|
93
|
-
|
|
153
|
+
console.log('Inbound created:', createdInbound);
|
|
154
|
+
|
|
155
|
+
// Get connection link for the client (now with accurate server-assigned values)
|
|
94
156
|
const link = builder.getClientLink(0, 'your-server-ip.com');
|
|
95
157
|
console.log('Client connection link:', link);
|
|
96
158
|
} catch (error) {
|
|
@@ -99,24 +161,84 @@ async function createRealityInbound() {
|
|
|
99
161
|
}
|
|
100
162
|
```
|
|
101
163
|
|
|
164
|
+
### Real-World Example
|
|
165
|
+
|
|
166
|
+
Here's a complete example showing how to create a VMess inbound and get the client link:
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
const X3UIClient = require('x3ui-api');
|
|
170
|
+
const vmess = require('x3ui-api/src/protocols/vmess');
|
|
171
|
+
|
|
172
|
+
const client = new X3UIClient({
|
|
173
|
+
baseURL: 'https://your-panel-url.com/path/',
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
(async () => {
|
|
177
|
+
await client.login('username', 'password');
|
|
178
|
+
|
|
179
|
+
// Create VMess builder with HTTP Upgrade
|
|
180
|
+
let vmessBuilder = new vmess.VmessBuilder(client)
|
|
181
|
+
.setRemark("My VMess Inbound")
|
|
182
|
+
.setHttpUpgradeHost("your-domain.com");
|
|
183
|
+
|
|
184
|
+
// Add the inbound to the server
|
|
185
|
+
const vmessInbound = await client.addInbound(await vmessBuilder.build());
|
|
186
|
+
|
|
187
|
+
// Create a new builder with the server-returned inbound to get accurate client links
|
|
188
|
+
vmessBuilder = new vmess.VmessBuilder(client, vmessInbound);
|
|
189
|
+
|
|
190
|
+
// Generate and output the client connection link
|
|
191
|
+
console.log(vmessBuilder.getClientLink(0, "your-domain.com"));
|
|
192
|
+
})();
|
|
193
|
+
```
|
|
194
|
+
|
|
102
195
|
### Managing Existing Inbounds
|
|
103
196
|
|
|
104
197
|
```javascript
|
|
105
198
|
async function manageInbounds() {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (inbounds.length > 0) {
|
|
110
|
-
const inboundId = inbounds[0].id;
|
|
111
|
-
|
|
112
|
-
// Update an inbound
|
|
113
|
-
await client.updateInbound(inboundId, {
|
|
114
|
-
remark: 'Updated Inbound Name',
|
|
115
|
-
enable: true
|
|
116
|
-
});
|
|
199
|
+
try {
|
|
200
|
+
// Get all inbounds
|
|
201
|
+
const inbounds = await client.getInbounds();
|
|
117
202
|
|
|
118
|
-
|
|
119
|
-
|
|
203
|
+
if (inbounds.length > 0) {
|
|
204
|
+
// Get the first inbound
|
|
205
|
+
const inbound = inbounds[0];
|
|
206
|
+
const inboundId = inbound.id;
|
|
207
|
+
|
|
208
|
+
// IMPORTANT: When updating an inbound, always start with the complete inbound object
|
|
209
|
+
// to avoid losing data, then modify only what you need to change
|
|
210
|
+
|
|
211
|
+
// Example 1: Update the remark and enable status
|
|
212
|
+
inbound.remark = 'Updated Inbound Name';
|
|
213
|
+
inbound.enable = true;
|
|
214
|
+
|
|
215
|
+
// Send the complete updated inbound back to the server
|
|
216
|
+
await client.updateInbound(inboundId, inbound);
|
|
217
|
+
|
|
218
|
+
// Example 2: Add a new client to an existing inbound
|
|
219
|
+
if (inbound.protocol === 'vmess') {
|
|
220
|
+
// Create a builder with the existing inbound
|
|
221
|
+
const builder = new vmess.VmessBuilder(client, inbound);
|
|
222
|
+
|
|
223
|
+
// Add a new client
|
|
224
|
+
builder.addClient()
|
|
225
|
+
.setEmail('newuser@example.com')
|
|
226
|
+
.setTotalGB(50);
|
|
227
|
+
|
|
228
|
+
// Build the updated inbound and send it to the server
|
|
229
|
+
const updatedInbound = await builder.build();
|
|
230
|
+
await client.updateInbound(inboundId, updatedInbound);
|
|
231
|
+
|
|
232
|
+
// Get the link for the new client
|
|
233
|
+
const link = builder.getClientLink(builder.clients.length - 1, 'your-server-ip.com');
|
|
234
|
+
console.log('New client link:', link);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Example 3: Delete an inbound
|
|
238
|
+
await client.deleteInbound(inboundId);
|
|
239
|
+
}
|
|
240
|
+
} catch (error) {
|
|
241
|
+
console.error('Error managing inbounds:', error.message);
|
|
120
242
|
}
|
|
121
243
|
}
|
|
122
244
|
```
|
|
@@ -140,18 +262,44 @@ new X3UIClient({
|
|
|
140
262
|
- `login(username: string, password: string)` - Authenticate with the panel
|
|
141
263
|
- `getSystemStats()` - Get system statistics
|
|
142
264
|
- `getInbounds()` - Get all configured inbounds
|
|
143
|
-
- `addInbound(config)` - Add a new inbound
|
|
144
|
-
- `updateInbound(id, config)` - Update an existing inbound
|
|
265
|
+
- `addInbound(config)` - Add a new inbound and returns the created inbound with server-assigned values
|
|
266
|
+
- `updateInbound(id, config)` - Update an existing inbound with the complete inbound configuration
|
|
145
267
|
- `deleteInbound(id)` - Delete an inbound
|
|
146
268
|
- `getNewX25519Cert()` - Generate a new X25519 certificate
|
|
147
|
-
- `createRealityBuilder(options)` - Create a Reality inbound builder
|
|
148
269
|
|
|
149
|
-
###
|
|
270
|
+
### Protocol Builders
|
|
150
271
|
|
|
151
|
-
|
|
272
|
+
The library provides protocol-specific builders for creating different types of inbounds:
|
|
152
273
|
|
|
153
|
-
####
|
|
274
|
+
#### VMess Builder
|
|
275
|
+
|
|
276
|
+
```javascript
|
|
277
|
+
const vmess = require('x3ui-api/src/protocols/vmess');
|
|
278
|
+
const builder = new vmess.VmessBuilder(client, options);
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Methods:
|
|
282
|
+
- `setPort(port)` - Set the port for the inbound
|
|
283
|
+
- `setRemark(remark)` - Set the name/remark for the inbound
|
|
284
|
+
- `setNetwork(network)` - Set the network type (default: 'httpupgrade')
|
|
285
|
+
- `setSecurity(security)` - Set the security type (default: 'none')
|
|
286
|
+
- `setHttpUpgradePath(path)` - Set the HTTP upgrade path
|
|
287
|
+
- `setHttpUpgradeHost(host)` - Set the HTTP upgrade host
|
|
288
|
+
- `setSniffing(enabled, destOverride, metadataOnly, routeOnly)` - Configure sniffing
|
|
289
|
+
- `setListenIP(ip)` - Set listen IP address
|
|
290
|
+
- `setExpiryTime(timestamp)` - Set inbound expiry time
|
|
291
|
+
- `addClient(options)` - Add a new client to the inbound
|
|
292
|
+
- `getClientLink(clientIndex, host, port)` - Get connection link for a client
|
|
293
|
+
- `build()` - Build the final inbound config
|
|
294
|
+
|
|
295
|
+
#### VLESS Reality Builder
|
|
296
|
+
|
|
297
|
+
```javascript
|
|
298
|
+
const vless = require('x3ui-api/src/protocols/vless');
|
|
299
|
+
const builder = new vless.RealityBuilder(client, options);
|
|
300
|
+
```
|
|
154
301
|
|
|
302
|
+
Methods:
|
|
155
303
|
- `setPort(port)` - Set the port for the inbound
|
|
156
304
|
- `setRemark(remark)` - Set the name/remark for the inbound
|
|
157
305
|
- `setDest(dest)` - Set the destination address (e.g., "yahoo.com:443")
|
package/package.json
CHANGED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {ClientSettings, InboundConfig} from "../index";
|
|
2
|
+
import InboundBuilder from "./IndoundBuilder";
|
|
3
|
+
|
|
4
|
+
export default class ClientBuilder {
|
|
5
|
+
|
|
6
|
+
constructor(parent: InboundBuilder | InboundConfig);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Set client UUID. If not provided, will be auto-generated
|
|
10
|
+
*/
|
|
11
|
+
setId(id: string): this;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Set client email
|
|
15
|
+
*/
|
|
16
|
+
setEmail(email: string): this;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Set total traffic limit in GB
|
|
20
|
+
*/
|
|
21
|
+
setTotalGB(gb: number): this;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Set expiry time in unix timestamp
|
|
25
|
+
*/
|
|
26
|
+
setExpiryTime(timestamp: number): this;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Set Telegram ID
|
|
30
|
+
*/
|
|
31
|
+
setTgId(id: string): this;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Build the client configuration
|
|
35
|
+
*/
|
|
36
|
+
build(): ClientSettings;
|
|
37
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const crypto = require("crypto");
|
|
2
|
+
|
|
3
|
+
module.exports = class ClientBuilder {
|
|
4
|
+
constructor(parent) {
|
|
5
|
+
this.parent = parent;
|
|
6
|
+
this.id = '';
|
|
7
|
+
this.flow = '';
|
|
8
|
+
this.email = '';
|
|
9
|
+
this.limitIp = 0;
|
|
10
|
+
this.totalGB = 0;
|
|
11
|
+
this.expiryTime = 0;
|
|
12
|
+
this.enable = true;
|
|
13
|
+
this.tgId = '';
|
|
14
|
+
this.subId = '';
|
|
15
|
+
this.reset = 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setId(id) {
|
|
19
|
+
this.id = id;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
setEmail(email) {
|
|
24
|
+
this.email = email;
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
setTotalGB(gb) {
|
|
29
|
+
this.totalGB = gb;
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
setExpiryTime(timestamp) {
|
|
34
|
+
this.expiryTime = timestamp;
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setTgId(id) {
|
|
39
|
+
this.tgId = id;
|
|
40
|
+
return this;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
build() {
|
|
44
|
+
return {
|
|
45
|
+
id: this.id || crypto.randomUUID(),
|
|
46
|
+
flow: this.flow,
|
|
47
|
+
email: this.email || Math.random().toString(36).substring(2, 10),
|
|
48
|
+
limitIp: this.limitIp,
|
|
49
|
+
totalGB: this.totalGB,
|
|
50
|
+
expiryTime: this.expiryTime,
|
|
51
|
+
enable: this.enable,
|
|
52
|
+
tgId: this.tgId,
|
|
53
|
+
subId: this.subId || Math.random().toString(36).substring(2, 18),
|
|
54
|
+
reset: this.reset
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default class InboundBuilder {}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {AxiosInstance} from "axios";
|
|
2
|
+
import {
|
|
3
|
+
InboundConfig,
|
|
4
|
+
LoginResponse,
|
|
5
|
+
SystemStats,
|
|
6
|
+
X3UIConfig
|
|
7
|
+
} from "../index";
|
|
8
|
+
|
|
9
|
+
export default class X3UIClient {
|
|
10
|
+
private client: AxiosInstance;
|
|
11
|
+
|
|
12
|
+
constructor(config: X3UIConfig);
|
|
13
|
+
|
|
14
|
+
login(username: string, password: string): Promise<LoginResponse>;
|
|
15
|
+
|
|
16
|
+
getSystemStats(): Promise<SystemStats>;
|
|
17
|
+
|
|
18
|
+
getInbounds(): Promise<InboundConfig[]>;
|
|
19
|
+
|
|
20
|
+
addInbound(config: Omit<InboundConfig, 'id'>): Promise<InboundConfig>;
|
|
21
|
+
|
|
22
|
+
updateInbound(id: number, config: Partial<InboundConfig>): Promise<void>;
|
|
23
|
+
|
|
24
|
+
deleteInbound(id: number): Promise<void>;
|
|
25
|
+
|
|
26
|
+
getInboundTraffic(id: number): Promise<{ up: number; down: number }>;
|
|
27
|
+
|
|
28
|
+
resetInboundTraffic(id: number): Promise<void>;
|
|
29
|
+
|
|
30
|
+
getNewX25519Cert(): Promise<{ privateKey: string; publicKey: string }>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const axios = require("axios");
|
|
2
|
+
|
|
3
|
+
module.exports = class X3UIClient {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.parseJSONSettings = config.parseJSONSettings || true;
|
|
6
|
+
this.client = axios.create({
|
|
7
|
+
baseURL: config.baseURL,
|
|
8
|
+
headers: config.token ? {
|
|
9
|
+
'Cookie': `lang=en-US; 3x-ui=${config.token}`,
|
|
10
|
+
} : {
|
|
11
|
+
'Cookie': 'lang=en-US'
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Login to the x3ui panel
|
|
18
|
+
* @param {string} username Panel username
|
|
19
|
+
* @param {string} password Panel password
|
|
20
|
+
* @returns {Promise<{success: boolean, msg: string, obj: any}>} Login response with success status and token
|
|
21
|
+
*/
|
|
22
|
+
async login(username, password) {
|
|
23
|
+
const formData = new URLSearchParams();
|
|
24
|
+
formData.append('username', username);
|
|
25
|
+
formData.append('password', password);
|
|
26
|
+
|
|
27
|
+
const response = await this.client.post('/login', formData, {
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': 'application/x-www-form-urlencoded'
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
if (response.data.success) {
|
|
34
|
+
this.client.defaults.headers.Cookie = `lang=en-US; ${response.headers.get("set-cookie")[0].split(";")[0]}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return response.data;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async getSystemStats() {
|
|
41
|
+
const response = await this.client.post('/server/status');
|
|
42
|
+
return response.data.obj;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get all inbounds
|
|
47
|
+
* @returns {Promise<Array<{
|
|
48
|
+
* id?: number,
|
|
49
|
+
* up: number,
|
|
50
|
+
* down: number,
|
|
51
|
+
* total: number,
|
|
52
|
+
* remark: string,
|
|
53
|
+
* enable: boolean,
|
|
54
|
+
* expiryTime: number | null,
|
|
55
|
+
* listen: string,
|
|
56
|
+
* port: number,
|
|
57
|
+
* protocol: string,
|
|
58
|
+
* settings: any,
|
|
59
|
+
* streamSettings: any,
|
|
60
|
+
* sniffing: any
|
|
61
|
+
* }>>}
|
|
62
|
+
*/
|
|
63
|
+
async getInbounds() {
|
|
64
|
+
const response = await this.client.get('/panel/api/inbounds/list');
|
|
65
|
+
let inbounds = response.data.obj;
|
|
66
|
+
if (this.parseJSONSettings) {
|
|
67
|
+
inbounds = inbounds.map(inbound => this.parseInbound(inbound));
|
|
68
|
+
}
|
|
69
|
+
return inbounds;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
parseInbound(inbound) {
|
|
73
|
+
if (this.parseJSONSettings) {
|
|
74
|
+
inbound.settings = inbound.settings && inbound.settings.length > 0 ? JSON.parse(inbound.settings) : {};
|
|
75
|
+
inbound.streamSettings = inbound.streamSettings && inbound.streamSettings.length > 0 ? JSON.parse(inbound.streamSettings) : {};
|
|
76
|
+
inbound.sniffing = inbound.sniffing && inbound.sniffing.length > 0 ? JSON.parse(inbound.sniffing) : {};
|
|
77
|
+
inbound.allocate = inbound.allocate && inbound.allocate.length > 0 ? JSON.parse(inbound.allocate) : {};
|
|
78
|
+
}
|
|
79
|
+
return inbound;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
stringifyInbound(inbound) {
|
|
83
|
+
inbound.settings = JSON.stringify(inbound.settings);
|
|
84
|
+
inbound.streamSettings = JSON.stringify(inbound.streamSettings);
|
|
85
|
+
inbound.sniffing = JSON.stringify(inbound.sniffing);
|
|
86
|
+
inbound.allocate = JSON.stringify(inbound.allocate);
|
|
87
|
+
return inbound;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Add new inbound
|
|
92
|
+
* @param {Object} config Inbound configuration
|
|
93
|
+
* @param {number} config.up Upload traffic in bytes
|
|
94
|
+
* @param {number} config.down Download traffic in bytes
|
|
95
|
+
* @param {number} config.total Total traffic limit in bytes
|
|
96
|
+
* @param {string} config.remark Inbound remark/name
|
|
97
|
+
* @param {boolean} config.enable Enable status
|
|
98
|
+
* @param {number|null} config.expiryTime Expiry timestamp
|
|
99
|
+
* @param {string} config.listen Listen address
|
|
100
|
+
* @param {number} config.port Port number
|
|
101
|
+
* @param {string} config.protocol Protocol type
|
|
102
|
+
* @param {Object} config.settings Protocol settings
|
|
103
|
+
* @param {Object} config.streamSettings Stream settings
|
|
104
|
+
* @param {Object} config.sniffing Sniffing settings
|
|
105
|
+
* @param {Object} config.allocate Allocation settings
|
|
106
|
+
* @returns {Promise<void>}
|
|
107
|
+
*/
|
|
108
|
+
async addInbound(config) {
|
|
109
|
+
config = this.stringifyInbound(config);
|
|
110
|
+
const response = await this.client.post('/panel/api/inbounds/add', config);
|
|
111
|
+
if(!response.data.success)
|
|
112
|
+
throw new Error(response.data.msg);
|
|
113
|
+
return this.parseInbound(response.data.obj);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Update existing inbound
|
|
118
|
+
* @param {number} id Inbound ID
|
|
119
|
+
* @param {Object} config Partial inbound configuration
|
|
120
|
+
* @returns {Promise<void>}
|
|
121
|
+
*/
|
|
122
|
+
async updateInbound(id, config) {
|
|
123
|
+
config = this.stringifyInbound(config);
|
|
124
|
+
const response = await this.client.post(`/panel/api/inbounds/update/${id}`, config);
|
|
125
|
+
if(!response.data.success)
|
|
126
|
+
throw new Error(response.data.msg);
|
|
127
|
+
return this.parseInbound(response.data.obj);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Delete inbound
|
|
132
|
+
* @param {number} id Inbound ID
|
|
133
|
+
* @returns {Promise<void>}
|
|
134
|
+
*/
|
|
135
|
+
async deleteInbound(id) {
|
|
136
|
+
await this.client.post(`/panel/api/inbounds/del/${id}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Get new X25519 certificate
|
|
141
|
+
* @returns {Promise<{privateKey: string, publicKey: string}>} New X25519 key pair
|
|
142
|
+
*/
|
|
143
|
+
async getNewX25519Cert() {
|
|
144
|
+
const response = await this.client.post('/server/getNewX25519Cert');
|
|
145
|
+
return response.data.obj;
|
|
146
|
+
}
|
|
147
|
+
}
|