x3ui-api 1.0.6-3 → 1.0.7-1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "x3ui-api",
3
- "version": "1.0.6-3",
3
+ "version": "1.0.7-1",
4
4
  "description": "API client for x3ui panel",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -0,0 +1,51 @@
1
+ import X3UIClient, {ClientSettings, InboundConfig, DeepPartial} from "../../index";
2
+ import RealityClientBuilder from "./RealityClientBuilder";
3
+
4
+ export default class ClearBuilder {
5
+
6
+ constructor(client: X3UIClient, inbound?: DeepPartial<InboundConfig>);
7
+
8
+ /**
9
+ * Set the port for the inbound. If not provided, will auto-generate unused port
10
+ */
11
+ setPort(port: number): this;
12
+
13
+ /**
14
+ * Set the remark/name for the inbound
15
+ */
16
+ setRemark(remark: string): this;
17
+
18
+ /**
19
+ * Set listen IP address. Defaults to empty string
20
+ */
21
+ setListenIP(ip: string): this;
22
+
23
+ /**
24
+ * Set inbound expiry time. Defaults to 0 (no expiry)
25
+ */
26
+ setExpiryTime(timestamp: number): this;
27
+
28
+ /**
29
+ * Add a new client to the inbound
30
+ */
31
+ addClient(options?: DeepPartial<ClientSettings>): RealityClientBuilder;
32
+
33
+ /**
34
+ * Get connection link for a client
35
+ * @param clientIndex Index of the client (defaults to 0)
36
+ * @param host Optional host address (defaults to listenIP or 'localhost')
37
+ */
38
+ getClientLinkByIndex(clientIndex?: number, host?: string): string;
39
+
40
+ /**
41
+ * Get connection link for a client
42
+ * @param email Email of the client
43
+ * @param host Optional host address (defaults to listenIP or 'localhost')
44
+ */
45
+ getClientLinkByEmail(email: string, host?: string): string;
46
+
47
+ /**
48
+ * Build the final inbound config
49
+ */
50
+ build(): Promise<InboundConfig>;
51
+ }
@@ -0,0 +1,150 @@
1
+ const ClearClientBuilder = require("./ClearClientBuilder");
2
+
3
+ module.exports = class ClearBuilder {
4
+ constructor(client, options = {}) {
5
+ this.client = client;
6
+ // Initialize from InboundConfig
7
+ this.id = options.id || undefined;
8
+ this.port = options.port || 0;
9
+ this.remark = options.remark || '';
10
+ this.listenIP = options.listen || '';
11
+ this.expiryTime = options.expiryTime || 0;
12
+ this.enable = true;
13
+
14
+ // Initialize from StreamSettings and RealitySettings
15
+ const streamSettings = typeof options.streamSettings === 'string'
16
+ ? JSON.parse(options.streamSettings)
17
+ : options.streamSettings || {};
18
+
19
+ // Initialize clients
20
+ this.clients = [];
21
+ const settings = typeof options.settings === 'string'
22
+ ? JSON.parse(options.settings)
23
+ : options.settings;
24
+
25
+ if (settings?.clients) {
26
+ settings.clients.forEach(client => {
27
+ this.addClient(client);
28
+ });
29
+ }
30
+ }
31
+
32
+ setPort(port) {
33
+ this.port = port;
34
+ return this;
35
+ }
36
+
37
+ setRemark(remark) {
38
+ this.remark = remark;
39
+ return this;
40
+ }
41
+
42
+ setListenIP(ip) {
43
+ this.listenIP = ip;
44
+ return this;
45
+ }
46
+
47
+ setExpiryTime(timestamp) {
48
+ this.expiryTime = timestamp;
49
+ return this;
50
+ }
51
+
52
+ addClient(options = {}) {
53
+ const builder = new ClearClientBuilder(this);
54
+ if (options.id) builder.setId(options.id);
55
+ if (options.email) builder.setEmail(options.email);
56
+ if (options.totalGB) builder.setTotalGB(options.totalGB);
57
+ if (options.expiryTime) builder.setExpiryTime(options.expiryTime);
58
+ if (options.tgId) builder.setTgId(options.tgId);
59
+ this.clients.push(builder);
60
+ return builder;
61
+ }
62
+
63
+ getClientLinkByIndex(clientIndex = 0, host) {
64
+ if (clientIndex < 0 || clientIndex >= this.clients.length) {
65
+ throw new Error('Invalid client index');
66
+ }
67
+ const client = this.clients[clientIndex];
68
+ return client.getLink(host || this.listenIP || 'localhost', this.port);
69
+ }
70
+
71
+ getClientLinkByEmail(email, host) {
72
+ const client = this.clients.find(client => client.email === email);
73
+ if (!client) {
74
+ throw new Error('Client not found');
75
+ }
76
+ return client.getLink(host || this.listenIP || 'localhost', this.port);
77
+ }
78
+
79
+ generateRandomPort() {
80
+ return Math.floor(Math.random() * (65535 - 1024) + 1024);
81
+ }
82
+
83
+ async build() {
84
+ if (!this.remark) {
85
+ throw new Error('Remark is required');
86
+ }
87
+
88
+ // If no port specified, find unused one
89
+ if (!this.port) {
90
+ const inbounds = await this.client.getInbounds();
91
+ const usedPorts = new Set(inbounds.map(i => i.port));
92
+ let port;
93
+ do {
94
+ port = this.generateRandomPort();
95
+ } while (usedPorts.has(port));
96
+ this.port = port;
97
+ }
98
+
99
+ // If no clients added, create one default client
100
+ if (this.clients.length === 0) {
101
+ this.addClient();
102
+ }
103
+
104
+ // Build all clients
105
+ const clientConfigs = await Promise.all(this.clients.map(builder => builder.build()));
106
+
107
+ return {
108
+ id: this.id,
109
+ up: 0,
110
+ down: 0,
111
+ total: 0,
112
+ remark: this.remark,
113
+ enable: true,
114
+ expiryTime: this.expiryTime,
115
+ listen: this.listenIP,
116
+ port: this.port,
117
+ protocol: 'vless',
118
+ settings: {
119
+ clients: clientConfigs,
120
+ decryption: 'none',
121
+ fallbacks: []
122
+ },
123
+ streamSettings: {
124
+ network: 'tcp',
125
+ security: 'none',
126
+ externalProxy: [],
127
+ tcpSettings: {
128
+ acceptProxyProtocol: false,
129
+ header: {
130
+ type: 'none'
131
+ }
132
+ }
133
+ },
134
+ tag: `inbound-${this.port}`,
135
+ sniffing: {
136
+ enabled: false,
137
+ destOverride: ['http', 'tls', 'quic', 'fakedns'],
138
+ metadataOnly: false,
139
+ routeOnly: false
140
+ },
141
+ allocate: {
142
+ strategy: 'always',
143
+ refresh: 5,
144
+ concurrency: 3
145
+ }
146
+ };
147
+ }
148
+ }
149
+
150
+ module.exports.default = module.exports;
@@ -0,0 +1,11 @@
1
+ import ClientBuilder from "../../core/ClientBuilder";
2
+
3
+ export default class ClearClientBuilder extends ClientBuilder {
4
+
5
+ /**
6
+ * Generate connection link for this client
7
+ * @param host Host address
8
+ * @param port Optional port number, defaults to parent's port
9
+ */
10
+ getLink(host: string, port?: number): string;
11
+ }
@@ -0,0 +1,20 @@
1
+ const ClientBuilder = require('../../core/ClientBuilder');
2
+
3
+ module.exports = class ClearClientBuilder extends ClientBuilder {
4
+ getLink(host, port) {
5
+ const id = this.id || crypto.randomUUID();
6
+
7
+ port = port || this.parent.port;
8
+ let protocol = this.parent.protocol || 'vless';
9
+
10
+ const params = new URLSearchParams({
11
+ security: this.parent.streamSettings?.security || 'none',
12
+ type: this.parent.streamSettings?.network || 'tcp',
13
+ encryption: this.parent.settings?.decryption || 'none'
14
+ });
15
+
16
+ return `${protocol}://${id}@${host}:${port}?${params.toString()}#${encodeURIComponent(this.email || 'default')}`;
17
+ }
18
+ }
19
+
20
+ module.exports.default = module.exports;
@@ -4,6 +4,8 @@ import RealityClientBuilder from "./RealityClientBuilder";
4
4
  declare const _default: {
5
5
  RealityBuilder: typeof RealityBuilder;
6
6
  RealityClientBuilder: typeof RealityClientBuilder;
7
+ ClearBuilder: typeof RealityBuilder;
8
+ ClearClientBuilder: typeof RealityClientBuilder;
7
9
  };
8
10
 
9
11
  export default _default;
@@ -1,6 +1,8 @@
1
1
  module.exports = {
2
2
  RealityBuilder: require('./RealityBuilder'),
3
- RealityClientBuilder: require('./RealityClientBuilder')
3
+ RealityClientBuilder: require('./RealityClientBuilder'),
4
+ ClearBuilder: require('./ClearBuilder'),
5
+ ClearClientBuilder: require('./ClearClientBuilder')
4
6
  }
5
7
 
6
8
  module.exports.default = module.exports