@localzet/xtls-sdk
Version:
TypeScript SDK for XRAY/AURA Core
404 lines (403 loc) • 16 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HandlerService = void 0;
const nice_grpc_1 = require("nice-grpc");
const command_1 = require("../xray-protos/app/proxyman/command/command");
const user_1 = require("../xray-protos/common/protocol/user");
const create_typed_message_1 = __importDefault(require("../common/utils/create-typed-message/create-typed-message"));
const errors_1 = require("../common/errors");
const models_1 = require("./models");
const config_1 = require("../xray-protos/proxy/trojan/config");
const account_1 = require("../xray-protos/proxy/vless/account");
const config_2 = require("../xray-protos/proxy/shadowsocks/config");
const config_3 = require("../xray-protos/proxy/shadowsocks_2022/config");
const config_4 = require("../xray-protos/proxy/socks/config");
const config_5 = require("../xray-protos/proxy/http/config");
const remove_user_response_model_1 = require("./models/remove-user/remove-user.response.model");
/**
* Service for managing Xray inbound handlers and their users
*/
class HandlerService {
constructor(channel) {
this.channel = channel;
this.client = (0, nice_grpc_1.createClient)(command_1.HandlerServiceDefinition, channel);
}
/**
* Retrieves all users from a specified inbound handler.
* This method fetches user information including their credentials and metadata from the Xray server.
*
* @param {string} tag - The tag identifying the inbound handler to query
* @returns {Promise<ISdkResponse<GetInboundUsersResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data` containing an array of decoded user information
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*
* @example
* ```typescript
* const handler = new HandlerService(channel);
* const response = await handler.getInboundUsers('Personal');
*
* if (response.isOk) {
* console.log(response.data.users); // Array of DecodedUser objects
* } else {
* console.error(response.message); // Error message
* }
* ```
*/
async getInboundUsers(tag) {
try {
const response = await this.client.getInboundUsers({ tag });
return {
isOk: true,
data: new models_1.GetInboundUsersResponseModel(response.users),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.GET_ALL_USERS_ERROR(message),
};
}
}
/**
* Adds a new Trojan user to a specified inbound handler.
*
* @param {IAddTrojanUser} data - The user data containing tag, username, password and level
* @returns {Promise<ISdkResponse<AddUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was added
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async addTrojanUser(data) {
try {
const response = await this.client.alterInbound({
tag: data.tag,
operation: (0, create_typed_message_1.default)(command_1.AddUserOperation, {
user: user_1.User.create({
email: data.username,
level: data.level,
account: (0, create_typed_message_1.default)(config_1.Account, {
password: data.password,
}),
}),
}),
});
return {
isOk: true,
data: new models_1.AddUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('already exists')) {
return {
isOk: true,
data: new models_1.AddUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.ADD_USER_ERROR(message),
};
}
}
/**
* Adds a new VLESS user to a specified inbound handler.
*
* @param {IAddVlessUser} data - The user data containing tag, username, UUID, flow and level
* @returns {Promise<ISdkResponse<AddUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was added
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async addVlessUser(data) {
try {
const response = await this.client.alterInbound({
tag: data.tag,
operation: (0, create_typed_message_1.default)(command_1.AddUserOperation, {
user: user_1.User.create({
email: data.username,
level: data.level,
account: (0, create_typed_message_1.default)(account_1.Account, {
id: data.uuid,
flow: data.flow,
encryption: 'none',
}),
}),
}),
});
return {
isOk: true,
data: new models_1.AddUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('already exists')) {
return {
isOk: true,
data: new models_1.AddUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.ADD_USER_ERROR(message),
};
}
}
/**
* Adds a new Shadowsocks user to a specified inbound handler.
*
* @param {IAddShadowsocksUser} data - The user data containing tag, username, password, cipher type, IV check and level
* @returns {Promise<ISdkResponse<AddUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was added
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async addShadowsocksUser(data) {
try {
const response = await this.client.alterInbound({
tag: data.tag,
operation: (0, create_typed_message_1.default)(command_1.AddUserOperation, {
user: user_1.User.create({
email: data.username,
level: data.level,
account: (0, create_typed_message_1.default)(config_2.Account, {
password: data.password,
cipherType: data.cipherType,
ivCheck: data.ivCheck,
}),
}),
}),
});
return {
isOk: true,
data: new models_1.AddUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('already exists')) {
return {
isOk: true,
data: new models_1.AddUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.ADD_USER_ERROR(message),
};
}
}
/**
* Adds a new Shadowsocks 2022 user to a specified inbound handler.
*
* @param {IAddShadowsocks2022User} data - The user data containing tag, username, key and level
* @returns {Promise<ISdkResponse<AddUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was added
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async addShadowsocks2022User(data) {
try {
const response = await this.client.alterInbound({
tag: data.tag,
operation: (0, create_typed_message_1.default)(command_1.AddUserOperation, {
user: user_1.User.create({
email: data.username,
level: data.level,
account: (0, create_typed_message_1.default)(config_3.Account, {
key: data.key,
}),
}),
}),
});
return {
isOk: true,
data: new models_1.AddUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('already exists')) {
return {
isOk: true,
data: new models_1.AddUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.ADD_USER_ERROR(message),
};
}
}
/**
* Adds a new SOCKS user to a specified inbound handler.
*
* @param {IAddSocksUser} data - The user data containing tag, username, SOCKS username, SOCKS password and level
* @returns {Promise<ISdkResponse<AddUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was added
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async addSocksUser(data) {
try {
const response = await this.client.alterInbound({
tag: data.tag,
operation: (0, create_typed_message_1.default)(command_1.AddUserOperation, {
user: user_1.User.create({
email: data.username,
level: data.level,
account: (0, create_typed_message_1.default)(config_4.Account, {
username: data.socks_username,
password: data.socks_password,
}),
}),
}),
});
return {
isOk: true,
data: new models_1.AddUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('already exists')) {
return {
isOk: true,
data: new models_1.AddUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.ADD_USER_ERROR(message),
};
}
}
/**
* Adds a new HTTP user to a specified inbound handler.
*
* @param {IAddHttpUser} data - The user data containing tag, username, HTTP username, HTTP password and level
* @returns {Promise<ISdkResponse<AddUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was added
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async addHttpUser(data) {
try {
const response = await this.client.alterInbound({
tag: data.tag,
operation: (0, create_typed_message_1.default)(command_1.AddUserOperation, {
user: user_1.User.create({
email: data.username,
level: data.level,
account: (0, create_typed_message_1.default)(config_5.Account, {
username: data.http_username,
password: data.http_password,
}),
}),
}),
});
return {
isOk: true,
data: new models_1.AddUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('already exists')) {
return {
isOk: true,
data: new models_1.AddUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.ADD_USER_ERROR(message),
};
}
}
/**
* Removes a user from a specified inbound handler.
*
* @param {string} tag - The tag identifying the inbound handler
* @param {string} username - The username/email of the user to remove
* @returns {Promise<ISdkResponse<RemoveUserResponseModel>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data.success` indicating if user was removed
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async removeUser(tag, username) {
try {
const response = await this.client.alterInbound({
tag: tag,
operation: (0, create_typed_message_1.default)(command_1.RemoveUserOperation, { email: username }),
});
return {
isOk: true,
data: new remove_user_response_model_1.RemoveUserResponseModel(true),
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
if (message.includes('not found')) {
return {
isOk: true,
data: new remove_user_response_model_1.RemoveUserResponseModel(false),
};
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.REMOVE_USER_ERROR(message),
};
}
}
/**
* Gets the count of users in a specified inbound handler.
*
* @param {string} tag - The tag identifying the inbound handler
* @returns {Promise<ISdkResponse<number>>} A promise that resolves to:
* - On success: An object with `isOk: true` and `data` containing the user count
* - On failure: An object with `isOk: false` and error details from HANDLER_ERRORS
*/
async getInboundUsersCount(tag) {
try {
const response = await this.client.getInboundUsersCount({ tag });
return {
isOk: true,
data: response.count,
};
}
catch (error) {
let message = '';
if (error instanceof Error) {
message = error.message;
}
return {
isOk: false,
...errors_1.HANDLER_ERRORS.GET_INBOUND_USERS_COUNT_ERROR(message),
};
}
}
}
exports.HandlerService = HandlerService;