chore: scripts Dokploy/BPS (cron secret, Ads MCC, sync y probes)
Incluye utilidades de ops para CRON_SECRET, login customer Google Ads, sync de seguimiento BPS y probes de conexiones. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
121
scripts/dokploy_set_gads_login_cid.py
Normal file
121
scripts/dokploy_set_gads_login_cid.py
Normal file
@@ -0,0 +1,121 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Merge GOOGLE_ADS_LOGIN_CUSTOMER_ID into client-portal Dokploy env."""
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
ROOT = Path("/Users/4ventures/4ventures-client-portal")
|
||||
BPS = Path("/Users/4ventures/Projects/bps-facturacion")
|
||||
BASE = "https://dokploy.4ventures.es"
|
||||
APP_ID = "NZS797t9Rnq9Pj4mHiii3"
|
||||
APP = (
|
||||
f"{BASE}/dashboard/project/Z_4M-uDOH1_--itGSTh4l"
|
||||
f"/environment/bGja70l_a7HQ1dxyXqSuf/services/application/{APP_ID}"
|
||||
)
|
||||
KEY = "GOOGLE_ADS_LOGIN_CUSTOMER_ID"
|
||||
VALUE = "5963150101"
|
||||
|
||||
|
||||
def cred(key: str) -> str:
|
||||
import os
|
||||
|
||||
v = os.environ.get(key, "").strip()
|
||||
if v:
|
||||
return v
|
||||
p = BPS / ".env"
|
||||
if not p.is_file():
|
||||
return ""
|
||||
for line in p.read_text(encoding="utf-8").splitlines():
|
||||
if line.startswith(f"{key}="):
|
||||
return line.split("=", 1)[1].strip().strip('"').strip("'")
|
||||
return ""
|
||||
|
||||
|
||||
def main() -> int:
|
||||
email = cred("DOKPLOY_EMAIL") or "marketing@4ventures.es"
|
||||
password = cred("DOKPLOY_PASSWORD")
|
||||
if not password:
|
||||
print("missing DOKPLOY_PASSWORD", flush=True)
|
||||
return 2
|
||||
|
||||
chromium = Path.home() / "Library/Caches/ms-playwright/chromium-1148/chrome-mac/Chromium.app/Contents/MacOS/Chromium"
|
||||
launch_kwargs = {"headless": True}
|
||||
if chromium.is_file():
|
||||
launch_kwargs["executable_path"] = str(chromium)
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.launch(**launch_kwargs)
|
||||
page = browser.new_page(viewport={"width": 1400, "height": 1000})
|
||||
page.goto(BASE + "/", wait_until="domcontentloaded", timeout=90000)
|
||||
page.wait_for_timeout(600)
|
||||
if "/dashboard" not in page.url:
|
||||
page.locator('input[type="email"], input[name="email"]').first.fill(email)
|
||||
page.locator('input[type="password"]').first.fill(password)
|
||||
page.locator('button[type="submit"]').first.click()
|
||||
page.wait_for_url(re.compile(r"/dashboard"), timeout=90000)
|
||||
print("login ok", flush=True)
|
||||
|
||||
page.goto(APP, wait_until="networkidle", timeout=120000)
|
||||
page.wait_for_timeout(800)
|
||||
|
||||
result = page.evaluate(
|
||||
"""async ({ appId, key, value }) => {
|
||||
const oneUrl = '/api/trpc/application.one?batch=1&input=' + encodeURIComponent(JSON.stringify({ '0': { json: { applicationId: appId } } }));
|
||||
const one = await fetch(oneUrl, { credentials: 'include' });
|
||||
const oneText = await one.text();
|
||||
if (!one.ok) return { ok: false, step: 'one', status: one.status, body: oneText.slice(0, 400) };
|
||||
let envText = '';
|
||||
try {
|
||||
const j = JSON.parse(oneText);
|
||||
const data = j[0]?.result?.data?.json || j[0]?.result?.data || j;
|
||||
envText = data?.env || data?.environment || '';
|
||||
if (typeof envText !== 'string') envText = '';
|
||||
} catch (e) {
|
||||
return { ok: false, step: 'parse', error: String(e), body: oneText.slice(0, 400) };
|
||||
}
|
||||
const lines = envText.split('\\n').filter(Boolean);
|
||||
const map = {};
|
||||
for (const line of lines) {
|
||||
const i = line.indexOf('=');
|
||||
if (i < 0) continue;
|
||||
map[line.slice(0, i)] = line.slice(i + 1);
|
||||
}
|
||||
const prev = map[key] || null;
|
||||
map[key] = value;
|
||||
const merged = Object.keys(map).map(k => k + '=' + map[k]).join('\\n') + '\\n';
|
||||
|
||||
const tries = [];
|
||||
const payloads = [
|
||||
{ path: '/api/application.update', body: { applicationId: appId, env: merged } },
|
||||
{ path: '/api/trpc/application.update?batch=1', body: { '0': { json: { applicationId: appId, env: merged } } } },
|
||||
{ path: '/api/trpc/application.saveEnvironment?batch=1', body: { '0': { json: { applicationId: appId, env: merged } } } },
|
||||
];
|
||||
for (const t of payloads) {
|
||||
const r = await fetch(t.path, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'content-type': 'application/json' },
|
||||
body: JSON.stringify(t.body),
|
||||
});
|
||||
const text = await r.text();
|
||||
tries.push({ path: t.path, status: r.status, body: text.slice(0, 160) });
|
||||
if (r.ok) {
|
||||
return { ok: true, prev, set: value, keys: Object.keys(map).length, tries };
|
||||
}
|
||||
}
|
||||
return { ok: false, step: 'update', prev, tries };
|
||||
}""",
|
||||
{"appId": APP_ID, "key": KEY, "value": VALUE},
|
||||
)
|
||||
browser.close()
|
||||
|
||||
print(result, flush=True)
|
||||
return 0 if result.get("ok") else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user