import axios from "axios" import qs from "qs" import fs from "fs" import path from "path" import { v4 as uuidv4 } from "uuid" import randomstring from "randomstring" process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0" export class XrayApi { constructor(url, username, password) { this.url = url this.username = username this.password = password this.api = axios.create({ baseURL: url, withCredentials: true }) } async login() { const { data, headers } = await this.api.post( "login", qs.stringify({ username: this.username, password: this.password }) ) if (headers["set-cookie"] instanceof Array) { this.api.defaults.headers.Cookie = headers["set-cookie"][1] } else { this.api.defaults.headers.Cookie = headers["set-cookie"] } } async status() { const { data } = await this.api.post("server/status") console.log(data) } async update() { try { const { data } = await this.api.post( "/panel/xray/update", qs.stringify({ xraySetting: fs.readFileSync( path.resolve("dist", "xray_edited.json") ) }) ) console.log(data) if (!data.success) { throw new Error(data.message) } } catch (e) { console.log(e.response.status) throw new Error(e.response.data) } } async restartXray() { const { data } = await this.api.post("server/restartXrayService") console.log(data) } async add(name, users) { const list = await this.list() const item = list.find(item => item.remark === name) if (item) { console.log(`Inbound ${name} already exists`) await this.del(item.id) console.log(`Inbound ${name} deleted`) } const shortId = randomstring.generate({ length: 8, charset: "hex" }) const publicKey = "6jZhBr6PvJDFaU8o0WMeJBzLlwmr-D3hScvT8iM7qW0" const privateKey = "yGN50gBt8fnx4GLyEnpD1GTjXel5rII7nSVcclC1QzQ" const port = Math.floor(Math.random() * 10000) + 20000 const clients = users.map(user => { return { id: uuidv4(), flow: "", email: user, limitIp: 0, totalGB: 0, expiryTime: 0, enable: true, tgId: "", subId: randomstring.generate(16), reset: 0 } }) const { data } = await this.api.post( "panel/inbound/add", qs.stringify({ up: 0, down: 0, total: 0, remark: name, enable: true, expiryTime: 0, listen: "", port, protocol: "vless", settings: JSON.stringify({ clients, decryption: "none", fallbacks: [] }), streamSettings: JSON.stringify({ network: "tcp", security: "reality", externalProxy: [], realitySettings: { show: false, xver: 0, dest: "yahoo.com:443", serverNames: ["yahoo.com", "www.yahoo.com"], privateKey, minClient: "", maxClient: "", maxTimediff: 0, shortIds: [shortId], settings: { publicKey, fingerprint: "firefox", serverName: "", spiderX: "/" } }, tcpSettings: { acceptProxyProtocol: false, header: { type: "none" } } }), sniffing: JSON.stringify({ enabled: true, destOverride: ["http", "tls", "quic", "fakedns"], metadataOnly: false, routeOnly: false }) }) ) console.log(data) if (!data.success) { throw new Error(data.msg) } const server = new URL(this.api.defaults.baseURL).hostname return clients.map(client => { return { name: client.email, config: `{name: ${client.email}, server: ${server}, port: ${port}, reality-opts: {public-key: ${publicKey}, short-id: ${shortId}}, client-fingerprint: chrome, type: vless, uuid: ${client.id}, tls: true, tfo: false, skip-cert-verify: false, servername: yahoo.com, network: tcp}` } }) } async del(id) { const { data } = await this.api.post(`panel/inbound/del/${id}`) console.log(data) } async list() { const { data } = await this.api.post("panel/inbound/list") return data.obj } }