1"""
2Brand Mention Monitor (Multi-Platform) — Premium Multi-API Actor
3
4This actor is a thin wrapper that calls the multi-api-orchestrator with the
5'brand_mention_monitor' workflow. The orchestrator handles all multi-step
6conditional logic via LangGraph (or async fallback).
7
8AI-DLC: Part of multi-api-orchestration-spec.md
9"""
10import asyncio
11import json
12import os
13import time
14
15import httpx
16from apify import Actor
17
18ORCHESTRATOR_ACTOR_ID = "multi-api-orchestrator"
19APIFY_API = "https://api.apify.com/v2"
20
21
22def get_token() -> str:
23 return os.environ.get("APIFY_TOKEN", os.environ.get("APIFY_API_TOKEN", ""))
24
25
26async def call_orchestrator(workflow: str, query: dict) -> list[dict]:
27 """Call the multi-api-orchestrator actor and return results."""
28 token = get_token()
29 headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
30 input_data = {"workflow": workflow, "query": query}
31
32 async with httpx.AsyncClient(timeout=180) as client:
33 resp = await client.post(
34 f"{APIFY_API}/acts/{ORCHESTRATOR_ACTOR_ID}/runs?token={token}",
35 json=input_data,
36 headers=headers,
37 )
38 resp.raise_for_status()
39 run_id = resp.json()["data"]["id"]
40
41
42 started = time.time()
43 while time.time() - started < 150:
44 await asyncio.sleep(5)
45 status_resp = await client.get(f"{APIFY_API}/actor-runs/{run_id}?token={token}")
46 status_resp.raise_for_status()
47 status = status_resp.json()["data"]["status"]
48 if status in ("SUCCEEDED", "FAILED", "TIMED-OUT", "ABORTED"):
49 if status != "SUCCEEDED":
50 raise RuntimeError(f"Orchestrator run {status}")
51 dataset_id = status_resp.json()["data"]["defaultDatasetId"]
52 items_resp = await client.get(
53 f"{APIFY_API}/datasets/{dataset_id}/items?token={token}&clean=true"
54 )
55 items_resp.raise_for_status()
56 return items_resp.json() or []
57 raise TimeoutError("Orchestrator timed out")
58
59
60async def main() -> None:
61 async with Actor:
62 actor_input = await Actor.get_input() or {}
63 query = {k: v for k, v in actor_input.items() if k != "webhookUrl"}
64 results = await call_orchestrator("brand_mention_monitor", query)
65 await Actor.push_data(results)
66
67if __name__ == "__main__":
68 asyncio.run(main())