Files
clawd/lib/config.js
2026-05-04 14:17:28 +08:00

101 lines
2.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
const fs = require('fs');
const path = require('path');
const os = require('os');
// 生产环境用 /etc/clawd/,开发环境用 ~/.clawd/
const CONFIG_DIR = process.env.CLAWD_CONFIG_DIR
|| (process.getuid && process.getuid() === 0
? '/etc/clawd'
: path.join(os.homedir(), '.clawd'));
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
const DEFAULTS = {
server: 'wss://claw.cutos.ai/ws',
claw_id: null,
token: null,
heartbeat_interval: 30, // 秒
/** 云端已激活:用于启动/重连时立即点亮 alarmpwr不等首包 connected */
activated: false,
ssh_secret_key: null,
share_key: null,
headscale_server: 'https://hs.claw.cutos.ai',
};
function _generateSshSecretKey() {
const bytes = require('crypto').randomBytes(16);
return 'sk-' + bytes.toString('hex');
}
/**
* 生成可读性好的 Samba 共享密码格式xxxxxx-xxxxxx-xxxxXX三段各6字符连字符分隔
* 最后一段包含至少1个大写字母和1个数字其余为小写字母。
* 示例juqhuf-hykgyh-mykGi3
*/
function _generateShareKey() {
const crypto = require('crypto');
const lower = 'abcdefghijklmnopqrstuvwxyz';
const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const digits = '0123456789';
function rndChars(chars, n) {
const bytes = crypto.randomBytes(n);
return Array.from(bytes).map(b => chars[b % chars.length]).join('');
}
const g1 = rndChars(lower, 6);
const g2 = rndChars(lower, 6);
// 第三段4个小写 + 1个大写 + 1个数字随机打乱顺序
const g3raw = (rndChars(lower, 4) + rndChars(upper, 1) + rndChars(digits, 1)).split('');
for (let i = g3raw.length - 1; i > 0; i--) {
const j = crypto.randomBytes(1)[0] % (i + 1);
[g3raw[i], g3raw[j]] = [g3raw[j], g3raw[i]];
}
return `${g1}-${g2}-${g3raw.join('')}`;
}
function load() {
let cfg;
try {
if (fs.existsSync(CONFIG_FILE)) {
const raw = fs.readFileSync(CONFIG_FILE, 'utf8');
cfg = Object.assign({}, DEFAULTS, JSON.parse(raw));
}
} catch (e) {
const log = require('./logger');
log.error('config', '读取配置失败,使用默认值:', e.message);
}
if (!cfg) cfg = Object.assign({}, DEFAULTS);
let dirty = false;
if (!cfg.ssh_secret_key) {
cfg.ssh_secret_key = _generateSshSecretKey();
dirty = true;
}
if (!cfg.share_key) {
cfg.share_key = _generateShareKey();
dirty = true;
}
if (dirty) save(cfg);
return cfg;
}
function save(data) {
try {
fs.mkdirSync(CONFIG_DIR, { recursive: true });
fs.writeFileSync(CONFIG_FILE, JSON.stringify(data, null, 2), 'utf8');
} catch (e) {
const log = require('./logger');
log.error('config', '写入配置失败:', e.message);
}
}
function getConfigPath() {
return CONFIG_FILE;
}
module.exports = { load, save, getConfigPath };