feat: support LAN network

This commit is contained in:
Draculabo authored and vin committed 2026-01-10 01:07:09 +08:00
1 parent 098cbe3eb9
commit f5a85e3436
2 files changed
+112 -15

No files matched your search

+51 -7
View File
@@ -2,19 +2,63 @@ import { os } from '@orpc/server';
import { z } from 'zod';
import { networkInterfaces } from 'os';
export const systemHandler = os.route({
get_local_ip: os.handler(async () => {
// Schema for IP info
const IpInfoSchema = z.object({
address: z.string(),
name: z.string(),
isRecommended: z.boolean(),
});
export const systemHandler = os.router({
// Get all available local IPs with their adapter names
get_local_ips: os.output(z.array(IpInfoSchema)).handler(async () => {
const nets = networkInterfaces();
const results: string[] = [];
const results: { address: string; name: string; isRecommended: boolean }[] = [];
for (const name of Object.keys(nets)) {
for (const net of nets[name] || []) {
// Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
if (net.family === 'IPv4' && !net.internal) {
results.push(net.address);
const family = net.family;
const isIPv4 = family === 'IPv4';
if (!isIPv4 || net.internal) {
continue;
}
const addr = net.address;
// Skip non-LAN addresses
if (addr.startsWith('169.254.')) continue; // APIPA
if (addr.startsWith('198.18.')) continue; // CGNAT / VPN
// Determine if this is a recommended (likely real LAN) address
let isRecommended = false;
const lowerName = name.toLowerCase();
if (addr.startsWith('192.168.') || addr.startsWith('10.')) {
if (
lowerName.includes('wlan') ||
lowerName.includes('wi-fi') ||
lowerName.includes('wireless') ||
lowerName === '以太网' ||
lowerName === 'ethernet' ||
lowerName.match(/^eth\d/)
) {
isRecommended = true;
}
}
results.push({ address: addr, name, isRecommended });
}
}
return results.length > 0 ? results[0] : '127.0.0.1';
// Sort: recommended first, then by address
results.sort((a, b) => {
if (a.isRecommended !== b.isRecommended) {
return b.isRecommended ? 1 : -1;
}
return a.address.localeCompare(b.address);
});
return results;
}),
});