import json, datetime as dt, os, sys ROOT = sys.argv[1] JST = dt.timezone(dt.timedelta(hours=9)) S = os.path.join(ROOT, "sns/schedule.json") sched = json.load(open(S, encoding="utf-8")) posted = json.load(open(os.path.join(ROOT, "sns/posted.json"), encoding="utf-8")) FROM = dt.datetime(2026, 11, 9, 12, 0, tzinfo=JST) # 11/9 17:00 以降の未投稿の LinkedIn を組み直す pt = lambda s: dt.datetime.fromisoformat(s) RESEARCH = ["LOG393","LOG396","LOG400","LOG401","LOG417","LOG418","LOG423","LOG436","LOG434","LOG450","LOG461","LOG460","LOG465"] READING_LOG = ["LOG406","LOG433","LOG424","LOG438","LOG441","LOG442","LOG443","LOG449","LOG464","LOG467"] AI_VIDEO = {"VIDEO_hakobu-voice-art"} keep, li = [], [] for e in sched["posts"]: if e["platform"] == "linkedin" and e["id"] not in posted and pt(e["post_at"]) >= FROM: li.append(e) else: keep.append(e) def head(e): return e["id"][: -len("-linkedin")] def avail(e): if e["id"].startswith("VIDEO_"): m = json.load(open(os.path.join(ROOT, e["source"]), encoding="utf-8"))["meta"] return pt(m.get("publish_at") or e["post_at"]) return FROM issue = [e for e in li if e["id"].startswith("ISSUE-")] research = sorted([e for e in li if head(e) in RESEARCH], key=lambda e: e["post_at"]) reading = sorted([e for e in li if head(e) in READING_LOG or (e["id"].startswith("VIDEO_") and head(e) not in AI_VIDEO)], key=lambda e: e["post_at"]) ai = [e for e in li if head(e) in AI_VIDEO] placed = {id(e) for q in (issue, research, reading, ai) for e in q} dropped = [e for e in li if id(e) not in placed] out = [] d = dt.date(2026, 11, 10) def take(q, slot): for i, e in enumerate(q): if avail(e) < slot: return q.pop(i) return None while issue or research or reading or ai: slot = dt.datetime(d.year, d.month, d.day, 17, 0, tzinfo=JST) w = d.weekday(); e = None; p = None if w in (0, 3): e, p = take(issue, slot), "issue" elif w == 1: e, p = take(research, slot), "research" elif w == 2: e, p = take(reading, slot), "reading" elif w == 4: e, p = take(ai, slot), "ai" if e is None: e, p = take(reading, slot), "reading" if e: e = dict(e); e["post_at"] = slot.isoformat(); e["pillar"] = p; out.append(e) d += dt.timedelta(days=1) sched["posts"] = sorted(keep + out, key=lambda e: (e["post_at"], e["id"])) json.dump(sched, open(S, "w", encoding="utf-8"), ensure_ascii=False, indent=2); open(S, "a").write("\n") # 金曜の ai 柱の動画には meta.linkedin_pillar を書く(同期が柱を保つため) for e in out: if e["pillar"] == "ai" and e["id"].startswith("VIDEO_"): p = os.path.join(ROOT, e["source"]); j = json.load(open(p, encoding="utf-8")) j["meta"]["linkedin_pillar"] = "ai" json.dump(j, open(p, "w", encoding="utf-8"), ensure_ascii=False, indent=2); open(p, "a").write("\n") print("placed", len(out), "dropped", len(dropped)) for e in out: print(" ", e["post_at"][:10], "月火水木金土日"[pt(e["post_at"]).weekday()], e["pillar"], e["id"]) print("dropped:", " ".join(e["id"].replace("-linkedin","") for e in dropped))