@alltiptop/geoip-3xui-rules
Version:
Middleware server to set routing rules by countries for XRAY
85 lines (84 loc) • 3.08 kB
JavaScript
const parseClients = (inbound, debug) => {
if (!inbound.settings)
return [];
const settings = typeof inbound.settings === 'string'
? JSON.parse(inbound.settings)
: inbound.settings;
if (!settings || !Array.isArray(settings.clients)) {
if (debug) {
console.warn('[3x-ui debug] Inbound has no clients array:', inbound.id);
}
return [];
}
return settings.clients;
};
export const get3xui = async ({ panelAddress, token, inboundIds, debug = false, }) => {
const baseUrl = panelAddress.endsWith('/')
? panelAddress.slice(0, -1)
: panelAddress;
const fetchWithAuth = async (endpoint, options) => {
const response = await fetch(`${baseUrl}${endpoint}`, {
...options,
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json',
...options?.headers,
},
});
if (!response.ok) {
const errorBody = await response.text().catch(() => 'Unknown error');
throw new Error(`3x-ui API error: ${response.status} ${response.statusText} - ${errorBody}`);
}
return response.json();
};
const inboundIdSet = new Set(inboundIds.map((id) => String(id)));
try {
const data = await fetchWithAuth('/panel/api/inbounds/list');
if (!data.success) {
throw new Error(`3x-ui API error: ${data.msg || 'request failed'}`);
}
const inbounds = Array.isArray(data.obj) ? data.obj : [];
if (debug) {
console.log('[3x-ui debug] Inbounds fetched:', inbounds);
}
const allClients = inbounds
.filter((inbound) => inboundIdSet.has(String(inbound.id)))
.flatMap((inbound) => {
try {
return parseClients(inbound, debug);
}
catch (error) {
if (debug) {
console.warn('[3x-ui debug] Failed to parse inbound settings:', inbound.id, error);
}
return [];
}
});
const getUserTags = (subscriptionId) => {
const client = allClients.find((client) => client.subId === subscriptionId);
const comment = client?.comment || '';
// Regex: capture sequence after 'tags=' up to ;, newline, or another key=value segment
const tagRegex = /tags=([\s\S]*?)(?=(?:\s+\S+=)|;|\n|$)/g;
const out = [];
let match;
while ((match = tagRegex.exec(comment))) {
const segment = match[1];
segment
.split(',')
.map((s) => s.trim())
.filter(Boolean)
.forEach((t) => out.push(t));
}
return Array.from(new Set(out));
};
return {
getUserTags,
};
}
catch (error) {
console.error(error);
return {
getUserTags: () => [],
};
}
};