1b3c3496c5
- Убраны все машинно/инфра-специфичные данные из README/CODEMAP/скриптов/ workflows (хосты, IP, домен gitea -> github.server_url). - preconfigure: enable-check-update=N (выкл. проверку обновлений); подсказка «set up your own server» и так гаснет с override-сервером. - CI публикует exe/apk в Gitea Release `latest` (обновляется каждый прогон, стабильная ссылка) + версионный релиз на теге v*. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
161 lines
8.5 KiB
Bash
161 lines
8.5 KiB
Bash
#!/usr/bin/env bash
|
||
# Вшивает адрес сервера и публичный ключ в клон RustDesk перед сборкой.
|
||
# Патчит две константы в сабмодуле hbb_common:
|
||
# pub const RENDEZVOUS_SERVERS: &[&str] = &["rs-ny.rustdesk.com"];
|
||
# pub const RS_PUB_KEY: &str = "OeVu...";
|
||
#
|
||
# Значения берутся из окружения (см. config/server.env.example):
|
||
# RUSTDESK_SERVER — хост(ы) hbbs. Несколько — через запятую. Порт по умолчанию 21116,
|
||
# нестандартный указывать как host:port.
|
||
# RUSTDESK_PUB_KEY — публичный ключ сервера (содержимое id_ed25519.pub, base64).
|
||
# RUSTDESK_API_SERVER — (опц.) URL API-сервера (RustDesk Server Pro). Пусто — пропустить.
|
||
#
|
||
# Использование: RUSTDESK_SERVER=... RUSTDESK_PUB_KEY=... ./scripts/preconfigure.sh <путь-к-клону-rustdesk>
|
||
set -euo pipefail
|
||
|
||
SRC="${1:?укажи путь к клону rustdesk первым аргументом}"
|
||
CFG="$SRC/libs/hbb_common/src/config.rs"
|
||
|
||
[ -f "$CFG" ] || { echo "ОШИБКА: не найден $CFG — сабмодуль hbb_common не инициализирован?" >&2; exit 1; }
|
||
: "${RUSTDESK_SERVER:?не задан RUSTDESK_SERVER}"
|
||
: "${RUSTDESK_PUB_KEY:?не задан RUSTDESK_PUB_KEY}"
|
||
|
||
# Собираем Rust-массив &["a", "b"] из запятой-разделённого списка серверов.
|
||
IFS=',' read -ra SRV <<< "$RUSTDESK_SERVER"
|
||
ARR=""
|
||
for s in "${SRV[@]}"; do
|
||
s="$(echo -n "$s" | tr -d '[:space:]')"
|
||
[ -n "$s" ] && ARR="${ARR}\"${s}\", "
|
||
done
|
||
ARR="&[${ARR%, }]"
|
||
|
||
# Экранируем спецсимволы sed-замены (& | \) в подставляемых значениях.
|
||
esc() { printf '%s' "$1" | sed -e 's/[\\&|]/\\&/g'; }
|
||
ARR_ESC="$(esc "$ARR")"
|
||
KEY_ESC="$(esc "$RUSTDESK_PUB_KEY")"
|
||
|
||
# Патч RENDEZVOUS_SERVERS
|
||
sed -i -E "s|^pub const RENDEZVOUS_SERVERS: &\[&str\] = .*;|pub const RENDEZVOUS_SERVERS: \&[\&str] = ${ARR_ESC};|" "$CFG"
|
||
# Патч RS_PUB_KEY
|
||
sed -i -E "s|^pub const RS_PUB_KEY: &str = .*;|pub const RS_PUB_KEY: \&str = \"${KEY_ESC}\";|" "$CFG"
|
||
|
||
# Проверяем, что патч применился (значения не печатаем целиком — только факт).
|
||
grep -q "^pub const RENDEZVOUS_SERVERS: &\[&str\] = &\[\"" "$CFG" || { echo "ОШИБКА: не удалось пропатчить RENDEZVOUS_SERVERS" >&2; exit 1; }
|
||
if grep -q "OeVuKk5nlHiXp" "$CFG"; then
|
||
echo "ОШИБКА: RS_PUB_KEY остался дефолтным RustDesk" >&2; exit 1
|
||
fi
|
||
|
||
echo "[preconfigure] RENDEZVOUS_SERVERS -> ${#SRV[@]} сервер(ов), RS_PUB_KEY вшит."
|
||
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# Custom-client: сервер/ключ ВИДНЫ и ЗАЛОЧЕНЫ в настройках (override-settings) +
|
||
# опц. preset (постоянный) пароль в HARD_SETTINGS. Механизм RustDesk load_custom_client()
|
||
# читает ПОДПИСАННЫЙ custom.txt (приватного ключа их генератора у нас нет) -> патчим
|
||
# загрузчик под встроенный НЕподписанный конфиг (src/custom_client.json, include_str!),
|
||
# что работает и на Windows, и на Android. Отключить: RUSTDESK_NO_CUSTOM_CLIENT=1.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
if [ "${RUSTDESK_NO_CUSTOM_CLIENT:-}" != "1" ]; then
|
||
# Рабочий python (на Windows git-bash python3 = Store-заглушка -> берём python).
|
||
PY=""; for p in python3 python; do "$p" -c 'import hashlib,base64,json,secrets' 2>/dev/null && { PY="$p"; break; }; done
|
||
[ -n "$PY" ] || { echo "ОШИБКА: не найден рабочий python для custom-client" >&2; exit 1; }
|
||
|
||
FIRST_SRV="$(echo -n "${SRV[0]}" | tr -d '[:space:]')"
|
||
LOCK_PW="${RUSTDESK_LOCK_PASSWORD:-Y}" # залочить смену preset-пароля (по умолчанию да)
|
||
"$PY" - "$SRC/src/custom_client.json" "$FIRST_SRV" "$RUSTDESK_PUB_KEY" "${RUSTDESK_API_SERVER:-}" "${RUSTDESK_PRESET_PASSWORD:-}" "$LOCK_PW" <<'PYEOF'
|
||
import sys, json, hashlib, base64, secrets
|
||
out, server, key, api, preset_pw, lock_pw = sys.argv[1:7]
|
||
override = {
|
||
"custom-rendezvous-server": server,
|
||
"relay-server": server,
|
||
"key": key,
|
||
"enable-check-update": "N", # выключить проверку обновлений
|
||
}
|
||
# Подсказка «set up your own server» гаснет сама: using_public_server()=пуст ли custom-rendezvous-server,
|
||
# а он у нас в override -> непуст -> подсказки нет.
|
||
if api:
|
||
override["api-server"] = api
|
||
cfg = {"override-settings": override}
|
||
if preset_pw:
|
||
override["verification-method"] = "use-both-passwords" # постоянный + временный пароль
|
||
if lock_pw == "Y":
|
||
override["disable-change-permanent-password"] = "Y"
|
||
salt = secrets.token_hex(16)
|
||
h1 = hashlib.sha256(preset_pw.encode() + salt.encode()).digest() # = compute_permanent_password_h1
|
||
cfg["password"] = "00" + base64.b64encode(h1).decode() # HBBS preset storage: "00"+b64(h1)
|
||
cfg["salt"] = salt
|
||
with open(out, "w", encoding="utf-8") as f:
|
||
json.dump(cfg, f, ensure_ascii=False)
|
||
print("[preconfigure] custom_client.json: сервер виден+залочен, preset-пароль=" + ("да" if preset_pw else "нет"))
|
||
PYEOF
|
||
|
||
# Патч common.rs: встроенный неподписанный загрузчик (идемпотентно; клон сбрасывается перед каждой сборкой).
|
||
CM="$SRC/src/common.rs"
|
||
if ! grep -q "read_custom_client_unsigned" "$CM"; then
|
||
sed -i 's|pub fn load_custom_client() {|pub fn load_custom_client() {\n read_custom_client_unsigned(include_str!("custom_client.json"));|' "$CM"
|
||
grep -q 'read_custom_client_unsigned(include_str' "$CM" || { echo "ОШИБКА: не удалось внедрить вызов в load_custom_client" >&2; exit 1; }
|
||
cat >> "$CM" <<'RUSTEOF'
|
||
|
||
// [rustdesk-custom] Встроенный НЕподписанный custom-client конфиг (src/custom_client.json).
|
||
pub fn read_custom_client_unsigned(json: &str) {
|
||
let json = json.trim();
|
||
if json.is_empty() || json == "{}" {
|
||
return;
|
||
}
|
||
let Ok(mut data) =
|
||
serde_json::from_str::<std::collections::HashMap<String, serde_json::Value>>(json)
|
||
else {
|
||
log::error!("Failed to parse embedded custom client config");
|
||
return;
|
||
};
|
||
if let Some(app_name) = data.remove("app-name") {
|
||
if let Some(app_name) = app_name.as_str() {
|
||
*config::APP_NAME.write().unwrap() = app_name.to_owned();
|
||
}
|
||
}
|
||
let mut map_display_settings = HashMap::new();
|
||
for s in keys::KEYS_DISPLAY_SETTINGS {
|
||
map_display_settings.insert(s.replace("_", "-"), s);
|
||
}
|
||
let mut map_local_settings = HashMap::new();
|
||
for s in keys::KEYS_LOCAL_SETTINGS {
|
||
map_local_settings.insert(s.replace("_", "-"), s);
|
||
}
|
||
let mut map_settings = HashMap::new();
|
||
for s in keys::KEYS_SETTINGS {
|
||
map_settings.insert(s.replace("_", "-"), s);
|
||
}
|
||
let mut buildin_settings = HashMap::new();
|
||
for s in keys::KEYS_BUILDIN_SETTINGS {
|
||
buildin_settings.insert(s.replace("_", "-"), s);
|
||
}
|
||
if let Some(default_settings) = data.remove("default-settings") {
|
||
read_custom_client_advanced_settings(
|
||
default_settings,
|
||
&map_display_settings,
|
||
&map_local_settings,
|
||
&map_settings,
|
||
&buildin_settings,
|
||
false,
|
||
);
|
||
}
|
||
if let Some(overwrite_settings) = data.remove("override-settings") {
|
||
read_custom_client_advanced_settings(
|
||
overwrite_settings,
|
||
&map_display_settings,
|
||
&map_local_settings,
|
||
&map_settings,
|
||
&buildin_settings,
|
||
true,
|
||
);
|
||
}
|
||
for (k, v) in data {
|
||
if let Some(v) = v.as_str() {
|
||
config::HARD_SETTINGS.write().unwrap().insert(k, v.to_owned());
|
||
};
|
||
}
|
||
}
|
||
RUSTEOF
|
||
echo "[preconfigure] common.rs пропатчен (встроенный custom-client загрузчик)."
|
||
fi
|
||
fi
|