Created
October 31, 2026 01:52
-
-
Save chiquimike/0fda14346460f68704dff5ed1a69e242 to your computer and use it in GitHub Desktop.
chiquiwp_check.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """Revisa sitios WordPress: que respondan y que su ultima nota tenga < 24 h. | |
| Uso: python3 wp_check.py sitios.txt (un sitio por linea, # = comentario) | |
| python3 wp_check.py https://a.com b.org | |
| Sale con codigo 1 si algun sitio falla (util para cron o CI).""" | |
| import json | |
| import sys | |
| import urllib.request | |
| from concurrent.futures import ThreadPoolExecutor | |
| from datetime import datetime, timedelta, timezone | |
| from pathlib import Path | |
| MAX_AGE = timedelta(hours=24) | |
| TIMEOUT = 10 # segundos | |
| def check(site): | |
| """Devuelve (sitio, None) si esta bien, o (sitio, motivo) si falla.""" | |
| base = site.strip().rstrip("/") | |
| if not base.startswith(("http://", "https://")): | |
| base = "https://" + base | |
| url = base + "/wp-json/wp/v2/posts?per_page=1&orderby=date&_fields=date_gmt" | |
| req = urllib.request.Request(url, headers={"User-Agent": "wp-check/1.0"}) | |
| try: | |
| with urllib.request.urlopen(req, timeout=TIMEOUT) as resp: | |
| posts = json.load(resp) | |
| except Exception as exc: # DNS, timeout, HTTP != 2xx, JSON invalido | |
| return site, f"no responde ({type(exc).__name__}: {exc})" | |
| if not posts: | |
| return site, "la API no devolvio notas" | |
| # date_gmt viene en UTC sin zona horaria, p. ej. 2026-10-30T14:05:00 | |
| last = datetime.fromisoformat(posts[0]["date_gmt"]).replace(tzinfo=timezone.utc) | |
| age = datetime.now(timezone.utc) - last | |
| if age >= MAX_AGE: | |
| return site, f"ultima nota hace {age.total_seconds() / 3600:.1f} h (>= 24 h)" | |
| return site, None | |
| def main(): | |
| args = sys.argv[1:] | |
| if not args: | |
| sys.exit(__doc__) | |
| if len(args) == 1 and Path(args[0]).is_file(): # lista de sitios en archivo | |
| lines = Path(args[0]).read_text().splitlines() | |
| args = [l.strip() for l in lines if l.strip() and not l.startswith("#")] | |
| with ThreadPoolExecutor(max_workers=10) as pool: | |
| results = list(pool.map(check, args)) | |
| failures = [(site, why) for site, why in results if why] | |
| print(f"Revisados: {len(results)} | Fallan: {len(failures)}") | |
| for site, why in failures: | |
| print(f" FALLA {site}: {why}") | |
| sys.exit(1 if failures else 0) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment