← All ivy-nodes
IVYXSTUDIO · IVY NODE
S
Social: which platforms this run has
ivy.node.social-plan · v0.1.0
ivyx✓
Reads an IVYX Social collect or inbox agent's input (a connection and an id per platform) and says which platforms are there, so the agent's if-branches run only those steps. No model, no network.
#social#plan#ivyx-social
Inputs
| Field | Type | Description |
|---|---|---|
| client | string | The brand's name, as IVYX Social knows it. |
| days | integer | How many days back the collectors read. |
| ig_connection | Not declared | The platform's connection (connection.<id>), handed on by the agent's input. |
| ig_user_id | string | The Instagram professional account's id. |
| fb_connection | Not declared | The platform's connection (connection.<id>), handed on by the agent's input. |
| fb_page_id | string | The Facebook Page's id. |
| li_connection | Not declared | The platform's connection (connection.<id>), handed on by the agent's input. |
| li_organization_id | string | The LinkedIn company page's id or URN. |
| li_handle | string | Its vanity name. |
| x_connection | Not declared | The platform's connection (connection.<id>), handed on by the agent's input. |
| x_handle | string | The X handle. |
| yt_connection | Not declared | The platform's connection (connection.<id>), handed on by the agent's input. |
Outputs
| Field | Type | Description |
|---|---|---|
| has_instagram | boolean | Not declared |
| has_facebook | boolean | Not declared |
| has_linkedin | boolean | Not declared |
| has_x | boolean | Not declared |
| has_youtube | boolean | Not declared |
| platforms | array | Not declared |
| countrequired | integer | How many platforms. |
| client | string | Not declared |
| days | integer | Not declared |
Source
python
# Input preparation
inp = __ivy_ctx__["nodes"][__ivy_node_id__]["input"]
# Compute
# Shared by every social node (built into each by build.mjs): dates, blocks, merging.
import datetime, json, re, statistics
def day(s):
s = str(s or "")[:10]
return s if re.fullmatch(r"\d{4}-\d{2}-\d{2}", s) else None
def now_iso():
return datetime.datetime.utcnow().replace(microsecond=0).isoformat() + "Z"
def ms_of(s):
if s is None or s == "":
return None
if isinstance(s, (int, float)):
return int(s * 1000) if s < 1e12 else int(s)
t = str(s).replace("Z", "+00:00")
t = re.sub(r"([+-]\d{2})(\d{2})$", r"\1:\2", t)
try:
return int(datetime.datetime.fromisoformat(t).timestamp() * 1000)
except ValueError:
return None
def rows_of(block):
"""A {fields, rows} block as dicts."""
if not isinstance(block, dict) or not block.get("fields"):
return []
f = block["fields"]
return [dict(zip(f, r)) for r in block.get("rows") or []]
def block_of(dicts, first):
fields = list(first)
for d in dicts:
for k in d:
if k not in fields:
fields.append(k)
return {"fields": fields, "rows": [[d.get(k) for k in fields] for d in dicts]}
def listed(v):
return [x for x in (v if isinstance(v, list) else [v] if v else []) if x is not None]
def text_of(v, limit=4000):
s = " ".join(str(v).split()) if isinstance(v, (str, int, float)) else ""
return s[:limit]
class SocialPlan:
"Social: which platforms this run has"
def run(self, inp):
out = {}
# Which platforms this run has: a connection and an id per platform, so the agent's if-branches skip the rest.
def has(conn, *ids):
return bool(inp.get(conn)) and all(bool(inp.get(i)) for i in ids)
out["has_instagram"] = has("ig_connection", "ig_user_id")
out["has_facebook"] = has("fb_connection")
out["has_linkedin"] = has("li_connection", "li_organization_id")
out["has_x"] = has("x_connection")
out["has_youtube"] = has("yt_connection")
out["platforms"] = [p for p, ok in (("instagram", out["has_instagram"]), ("facebook", out["has_facebook"]), ("linkedin", out["has_linkedin"]), ("x", out["has_x"]), ("youtube", out["has_youtube"])) if ok]
out["count"] = len(out["platforms"])
out["client"] = inp.get("client") or ""
out["days"] = int(inp.get("days") or 7)
return out
result = SocialPlan().run(inp)
# Output collection (the runner reads it here)
out = __ivy_ctx__["nodes"][__ivy_node_id__]["output"]
out.update(result)Tests
Requires: python:3.9
- two
Instagram with its id and X are there; LinkedIn is not, so its branch is skipped.
- none
An empty input has no platform and reads seven days.
- id-missing
A LinkedIn connection without the company page's id is not a platform this run can read.