import json, os, sys, urllib.request, urllib.parse, urllib.error PAGE = 1000 # the relay's largest page DEFAULT_LIMIT = 10000 # the relay's default max_pending per source def _cfg(): s = json.loads(os.environ.get("INTEGRATION_SECRETS", "{}")) base = str(s.get("base_url") or "").strip().rstrip("/") if not base.startswith("https://"): raise ValueError("base_url must be the relay's https:// address") return base, {"Authorization": "Bearer " + str(s.get("read_token") or "").strip(), "Accept": "application/json"} def _get(path, params): base, headers = _cfg() url = base + path + "?" + urllib.parse.urlencode({k: v for k, v in params.items() if v not in (None, "")}) req = urllib.request.Request(url, headers=headers, method="GET") with urllib.request.urlopen(req, timeout=60) as r: return json.loads(r.read() or b"{}") def run(): inp = json.loads(os.environ.get("INTEGRATION_INPUTS", "{}")) source = str(inp.get("source") or "").strip() if not source: raise ValueError("source is required: the relay source id, e.g. r7-acme") try: limit = int(inp.get("limit") or DEFAULT_LIMIT) except (TypeError, ValueError): limit = DEFAULT_LIMIT since = str(inp.get("since") or "").strip() # Every page is read within this one run. The next run's watermark is the # instant of this one, so a page left for later would never be asked for. messages, after = [], "" while True: page = _get("/relay/v1/messages", {"source": source, "since": since, "after": after, "limit": PAGE}) messages.extend(page.get("messages") or []) if not page.get("more"): break after = page.get("next") or "" if not after: break if len(messages) >= limit: # Failing keeps the watermark where it is; returning a truncated # list would move it past what was never read. raise RuntimeError( "more than %d messages wait on source %s since %s: raise this command's limit " "(nothing was ingested; the next run reads the same window)" % (limit, source, since or "the beginning")) print(json.dumps({"messages": messages, "count": len(messages), "source": source, "since": since})) try: run() except urllib.error.HTTPError as e: detail = e.read().decode("utf-8", "replace") out = {"error": "HTTP " + str(e.code), "detail": detail} if e.code == 401: out["hint"] = "The relay refused the read token, or this Riposte's address is not in RELAY_CONSUMER_ALLOW_IPS." elif e.code == 404: out["hint"] = ("Unknown source on this relay, or this Riposte's address is not allowed by the proxy in front " "of it (it answers 404 to readers it does not know). Run test_connection.") print(json.dumps(out)) sys.exit(1) except Exception as e: print(json.dumps({"error": str(e)})) sys.exit(1)