chore: add community bot deploy/health tooling and Cordn web caveat
This commit is contained in:
parent
5536eee2ff
commit
f94abcf33e
28 changed files with 99 additions and 0 deletions
53
scripts/deploy-community-bot.sh
Executable file
53
scripts/deploy-community-bot.sh
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/usr/bin/env bash
|
||||
# Build + deploy the SkateSpots Community Cordn bot to the relay host.
|
||||
#
|
||||
# scripts/deploy-community-bot.sh
|
||||
# scripts/deploy-community-bot.sh --no-build
|
||||
#
|
||||
# The host defaults to the ssh alias `skatespots-cvm` (same VPS as the relay).
|
||||
# Override with SKATESPOTS_COMMUNITY_HOST / SKATESPOTS_COMMUNITY_DIR.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
HOST="${SKATESPOTS_COMMUNITY_HOST:-skatespots-cvm}"
|
||||
REMOTE_DIR="${SKATESPOTS_COMMUNITY_DIR:-/opt/skatespots-community}"
|
||||
REMOTE_STATE="${SKATESPOTS_COMMUNITY_STATE:-/var/lib/skatespots-community/state.json}"
|
||||
ARTIFACT="build/community-bot.cjs"
|
||||
|
||||
if [[ "${1:-}" != "--no-build" ]]; then
|
||||
scripts/build-community-bot.sh
|
||||
fi
|
||||
[[ -f "$ARTIFACT" ]] || { echo "missing $ARTIFACT (run without --no-build first)" >&2; exit 1; }
|
||||
|
||||
echo "→ uploading to $HOST:$REMOTE_DIR"
|
||||
scp -q "$ARTIFACT" "$HOST:/tmp/community-bot.cjs.new"
|
||||
|
||||
echo "→ installing + restarting skatespots-community"
|
||||
ssh "$HOST" "REMOTE_DIR='$REMOTE_DIR' bash -s" <<'REMOTE'
|
||||
set -euo pipefail
|
||||
cd "$REMOTE_DIR"
|
||||
sudo -n cp community-bot.cjs "community-bot.cjs.bak-$(date +%Y%m%d-%H%M%S)"
|
||||
sudo -n mv /tmp/community-bot.cjs.new community-bot.cjs
|
||||
sudo -n chmod 644 community-bot.cjs
|
||||
# Keep the five newest backups.
|
||||
ls -1t community-bot.cjs.bak-* 2>/dev/null | tail -n +6 | xargs -r sudo -n rm -f
|
||||
sudo -n systemctl restart skatespots-community
|
||||
sleep 3
|
||||
if ! systemctl is-active --quiet skatespots-community; then
|
||||
echo "✗ skatespots-community is not active" >&2
|
||||
journalctl -u skatespots-community -n 30 --no-pager >&2 || true
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ skatespots-community active"
|
||||
journalctl -u skatespots-community -n 8 --no-pager | tail -8
|
||||
REMOTE
|
||||
|
||||
echo "→ refreshing the 0600 state backup in ~/.config/skatespots"
|
||||
mkdir -p "$HOME/.config/skatespots"
|
||||
chmod 700 "$HOME/.config/skatespots"
|
||||
if scp -q "$HOST:$REMOTE_STATE" "$HOME/.config/skatespots/community-state.json"; then
|
||||
chmod 600 "$HOME/.config/skatespots/community-state.json"
|
||||
echo "✓ state backup updated"
|
||||
else
|
||||
echo "⚠ could not copy the bot state (service is still running)" >&2
|
||||
fi
|
||||
|
|
@ -213,6 +213,23 @@ if [ -f "$RUN_FILE" ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# ── Community Cordn bot ─────────────────────────────────────────────────────
|
||||
p ""
|
||||
p "${B}Community bot${N}"
|
||||
COMMUNITY_HOST="${SKATESPOTS_COMMUNITY_HOST:-skatespots-cvm}"
|
||||
if command -v ssh >/dev/null 2>&1 && grep -qsE "^Host[[:space:]]+${COMMUNITY_HOST}([[:space:]]|$)" "$HOME/.ssh/config"; then
|
||||
community_state="$(timeout 8 ssh -o BatchMode=yes -o ConnectTimeout=5 "$COMMUNITY_HOST" 'systemctl is-active skatespots-community' 2>/dev/null || true)"
|
||||
if [ "$community_state" = "active" ]; then
|
||||
p " ${G}✓${N} skatespots-community active"
|
||||
else
|
||||
p " ${R}✗${N} skatespots-community: ${community_state:-unreachable}"
|
||||
problems+=("community Cordn bot is ${community_state:-unreachable}")
|
||||
signature+="community-bot;"
|
||||
fi
|
||||
else
|
||||
p " ${DIM}ssh alias ${COMMUNITY_HOST} not configured — skipped${N}"
|
||||
fi
|
||||
|
||||
# ── Dependency job ──────────────────────────────────────────────────────────
|
||||
p ""
|
||||
p "${B}Dependency job${N}"
|
||||
|
|
|
|||
|
|
@ -1314,6 +1314,9 @@ function AdvancedPanel({
|
|||
<ExternalLink className="h-3 w-3" />{' '}
|
||||
{t('socialUi.crewCoordinator.openCordnGroup')}
|
||||
</a>
|
||||
<span className="text-[10px] text-gray-600">
|
||||
{t('cordnUi.cordnWebCaveat')}
|
||||
</span>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
|
|
|
|||
|
|
@ -919,6 +919,7 @@ const batch1 = {
|
|||
"create": "Crea el xat privat",
|
||||
"requestJoin": "Demana d'unir-t'hi",
|
||||
"requestAgain": "Request again",
|
||||
"cordnWebCaveat": "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
"checkInvite": "Comprova si hi ha invitació",
|
||||
"requested": "Sol·licitud enviada: un administrador de la colla l'aprovarà.",
|
||||
"noInvite": "Encara no hi ha cap invitació. Demana a un administrador que aprovi la teva sol·licitud.",
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ const drift = {
|
|||
"create": "Vytvořit soukromý chat",
|
||||
"requestJoin": "Požádat o připojení",
|
||||
"requestAgain": "Request again",
|
||||
"cordnWebCaveat": "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
"checkInvite": "Zkontrolovat pozvánku",
|
||||
"requested": "Žádost odeslána — administrátor crew ji schválí.",
|
||||
"noInvite": "Zatím nečeká žádná pozvánka. Požádej administrátora o schválení žádosti.",
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ const drift = {
|
|||
create: "Privaten Chat erstellen",
|
||||
requestJoin: "Um Beitritt bitten",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Nach Einladung suchen",
|
||||
requested: "Anfrage gesendet – ein Crew-Admin wird sie genehmigen.",
|
||||
noInvite: "Noch keine Einladung. Bitte einen Admin, deine Anfrage zu genehmigen.",
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ const drift = {
|
|||
create: "Δημιουργία ιδιωτικής συνομιλίας",
|
||||
requestJoin: "Ζήτα συμμετοχή",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Έλεγχος πρόσκλησης",
|
||||
requested: "Το αίτημα στάλθηκε — ένας διαχειριστής του crew θα το εγκρίνει.",
|
||||
noInvite: "Δεν περιμένει ακόμη πρόσκληση. Ζήτα από έναν διαχειριστή να εγκρίνει το αίτημά σου.",
|
||||
|
|
|
|||
|
|
@ -919,6 +919,7 @@ const batch1 = {
|
|||
create: "Sortu txat pribatua",
|
||||
requestJoin: "Eskatu sartzea",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Egiaztatu gonbidapena",
|
||||
requested: "Eskaera bidali da — taldeko administratzaile batek onartuko du.",
|
||||
noInvite: "Oraindik ez dago gonbidapenik zain. Eskatu administratzaile bati zure eskaera onartzeko.",
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ const drift = {
|
|||
create: "Créer le chat privé",
|
||||
requestJoin: "Demander à rejoindre",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Vérifier l'invitation",
|
||||
requested: "Demande envoyée — un admin de la Crew l'approuvera.",
|
||||
noInvite: "Aucune invitation en attente. Demandez à un admin d'approuver votre demande.",
|
||||
|
|
|
|||
|
|
@ -919,6 +919,7 @@ const batch1 = {
|
|||
create: "Crear o chat privado",
|
||||
requestJoin: "Pedir acceso",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Comprobar se hai invitación",
|
||||
requested: "Solicitude enviada: un administrador da crew aprobaraa.",
|
||||
noInvite: "Aínda non hai ningunha invitación. Pídele a un administrador que aprobe a túa solicitude.",
|
||||
|
|
|
|||
|
|
@ -919,6 +919,7 @@ const batch1 = {
|
|||
"create": "निजी चैट बनाएँ",
|
||||
"requestJoin": "शामिल होने का अनुरोध करें",
|
||||
"requestAgain": "Request again",
|
||||
"cordnWebCaveat": "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
"checkInvite": "निमंत्रण जाँचें",
|
||||
"requested": "अनुरोध भेजा गया — क्रू एडमिन इसे स्वीकृत करेगा।",
|
||||
"noInvite": "अभी कोई निमंत्रण प्रतीक्षा में नहीं। एडमिन से अपना अनुरोध स्वीकृत करने को कहें।",
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ const driftStrings = {
|
|||
create: 'Buat chat privat',
|
||||
requestJoin: 'Minta gabung',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: 'Periksa undangan',
|
||||
requested: 'Permintaan terkirim — admin crew akan menyetujuinya.',
|
||||
noInvite: 'Belum ada undangan menunggu. Minta admin menyetujui permintaanmu.',
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ const drift = {
|
|||
create: "Crea la chat privata",
|
||||
requestJoin: "Chiedi di unirti",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Controlla l'invito",
|
||||
requested: "Richiesta inviata — un admin della crew la approverà.",
|
||||
noInvite: "Nessun invito in attesa. Chiedi a un admin di approvare la tua richiesta.",
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ const drift: Dict = {
|
|||
create: 'プライベートチャットを作成',
|
||||
requestJoin: '参加をリクエスト',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: '招待を確認',
|
||||
requested: 'リクエストを送信しました — クルー管理者が承認します。',
|
||||
noInvite: 'まだ招待はありません。管理者にリクエストの承認を依頼してください。',
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ const drift: Dict = {
|
|||
create: '비공개 채팅 만들기',
|
||||
requestJoin: '참여 요청',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: '초대 확인',
|
||||
requested: '요청을 보냈습니다 — 크루 관리자가 승인합니다.',
|
||||
noInvite: '아직 대기 중인 초대가 없습니다. 관리자에게 요청 승인을 부탁하세요.',
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const cordnUi = {
|
|||
create: 'Create the private chat',
|
||||
requestJoin: 'Ask to join',
|
||||
requestAgain: 'Request again',
|
||||
cordnWebCaveat: 'Cordn web may stall after sign-in; the in-app join is more reliable.',
|
||||
checkInvite: 'Check for invite',
|
||||
requested: 'Request sent — a crew admin will approve it.',
|
||||
noInvite: 'No invite waiting yet. Ask an admin to approve your request.',
|
||||
|
|
@ -120,6 +121,7 @@ const cordnUi = {
|
|||
create: 'Crear el chat privado',
|
||||
requestJoin: 'Pedir entrar',
|
||||
requestAgain: 'Volver a pedir',
|
||||
cordnWebCaveat: 'Cordn web puede quedarse colgado tras iniciar sesión; entrar desde la app es más fiable.',
|
||||
checkInvite: 'Buscar invitación',
|
||||
requested: 'Solicitud enviada: un administrador la aprobará.',
|
||||
noInvite: 'Aún no hay invitación. Pide a un administrador que apruebe tu solicitud.',
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ const drift = {
|
|||
"create": "De privéchat aanmaken",
|
||||
"requestJoin": "Vragen om deel te nemen",
|
||||
"requestAgain": "Request again",
|
||||
"cordnWebCaveat": "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
"checkInvite": "Op uitnodiging controleren",
|
||||
"requested": "Verzoek verzonden — een crew-admin keurt het goed.",
|
||||
"noInvite": "Nog geen uitnodiging. Vraag een admin je verzoek goed te keuren.",
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ const drift = {
|
|||
"create": "Utwórz prywatny czat",
|
||||
"requestJoin": "Poproś o dołączenie",
|
||||
"requestAgain": "Request again",
|
||||
"cordnWebCaveat": "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
"checkInvite": "Sprawdź zaproszenie",
|
||||
"requested": "Prośba wysłana — administrator crew ją zatwierdzi.",
|
||||
"noInvite": "Brak oczekującego zaproszenia. Poproś administratora o zatwierdzenie prośby.",
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ const drift = {
|
|||
create: "Criar o chat privado",
|
||||
requestJoin: "Pedir para entrar",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Verificar convite",
|
||||
requested: "Solicitação enviada — um admin da crew vai aprovar.",
|
||||
noInvite: "Nenhum convite aguardando. Peça a um admin para aprovar sua solicitação.",
|
||||
|
|
|
|||
|
|
@ -308,6 +308,7 @@ const drift = {
|
|||
"create": "Creează chatul privat",
|
||||
"requestJoin": "Cere să te alături",
|
||||
"requestAgain": "Request again",
|
||||
"cordnWebCaveat": "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
"checkInvite": "Verifică invitația",
|
||||
"requested": "Cerere trimisă — un admin de crew o va aproba.",
|
||||
"noInvite": "Nicio invitație în așteptare încă. Cere unui admin să aprobe cererea ta.",
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ const drift = {
|
|||
create: "Создать приватный чат",
|
||||
requestJoin: "Попросить присоединиться",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Проверить приглашение",
|
||||
requested: "Запрос отправлен — администратор Crew одобрит его.",
|
||||
noInvite: "Приглашение пока не ждёт. Попросите администратора одобрить ваш запрос.",
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ const drift = {
|
|||
create: "Skapa den privata chatten",
|
||||
requestJoin: "Be om att gå med",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Kontrollera inbjudan",
|
||||
requested: "Begäran skickad — en crewadmin godkänner den.",
|
||||
noInvite: "Ingen inbjudan väntar än. Be en admin godkänna din begäran.",
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ const driftStrings = {
|
|||
create: 'สร้างแชทส่วนตัว',
|
||||
requestJoin: 'ขอเข้าร่วม',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: 'ตรวจสอบคำเชิญ',
|
||||
requested: 'ส่งคำขอแล้ว — แอดมิน crew จะอนุมัติ',
|
||||
noInvite: 'ยังไม่มีคำเชิญที่รออยู่ ขอให้แอดมินอนุมัติคำขอของคุณ',
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ const driftStrings = {
|
|||
create: 'Özel sohbeti oluştur',
|
||||
requestJoin: 'Katılmayı iste',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: 'Davetiye kontrol et',
|
||||
requested: 'İstek gönderildi — bir crew yöneticisi onaylayacak.',
|
||||
noInvite: 'Henüz bekleyen davetiye yok. Bir yöneticiden isteğini onaylamasını iste.',
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ const drift = {
|
|||
create: "Створити приватний чат",
|
||||
requestJoin: "Попросити приєднатися",
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: "Перевірити запрошення",
|
||||
requested: "Запит надіслано — адміністратор команди його схвалить.",
|
||||
noInvite: "Запрошення ще не чекає. Попросіть адміністратора схвалити ваш запит.",
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ const driftStrings = {
|
|||
create: 'Tạo chat riêng tư',
|
||||
requestJoin: 'Xin tham gia',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: 'Kiểm tra lời mời',
|
||||
requested: 'Đã gửi yêu cầu — quản trị viên crew sẽ duyệt.',
|
||||
noInvite: 'Chưa có lời mời nào. Hãy nhờ quản trị viên duyệt yêu cầu của bạn.',
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ const drift: Dict = {
|
|||
create: '创建私密聊天',
|
||||
requestJoin: '请求加入',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: '检查邀请',
|
||||
requested: '请求已发送——Crew 管理员会批准。',
|
||||
noInvite: '还没有等待中的邀请。请管理员批准你的请求。',
|
||||
|
|
|
|||
|
|
@ -320,6 +320,7 @@ const drift: Dict = {
|
|||
create: '建立私密聊天',
|
||||
requestJoin: '要求加入',
|
||||
requestAgain: "Request again",
|
||||
cordnWebCaveat: "Cordn web may stall after sign-in; the in-app join is more reliable.",
|
||||
checkInvite: '檢查邀請',
|
||||
requested: '要求已送出——Crew 管理員會批准。',
|
||||
noInvite: '還沒有等待中的邀請。請管理員批准你的要求。',
|
||||
|
|
|
|||
Loading…
Reference in a new issue