98 lines
2.9 KiB
Python
98 lines
2.9 KiB
Python
"""Query ClickUp for feb26-tagged to-do tasks in OPT/LINKS/Content categories."""
|
|
|
|
from datetime import datetime, UTC
|
|
from cheddahbot.config import load_config
|
|
from cheddahbot.clickup import ClickUpClient
|
|
|
|
cfg = load_config()
|
|
client = ClickUpClient(
|
|
api_token=cfg.clickup.api_token,
|
|
workspace_id=cfg.clickup.workspace_id,
|
|
task_type_field_name=cfg.clickup.task_type_field_name,
|
|
)
|
|
|
|
tasks = client.get_tasks_from_overall_lists(cfg.clickup.space_id, statuses=["to do"])
|
|
client.close()
|
|
|
|
# Filter: tagged feb26
|
|
feb26 = [t for t in tasks if "feb26" in t.tags]
|
|
|
|
# Filter: OPT / LINKS / Content categories (by Work Category or name prefix)
|
|
def is_target(t):
|
|
cat = (t.task_type or "").lower()
|
|
name = t.name.upper()
|
|
if cat in ("on page optimization", "link building", "content creation"):
|
|
return True
|
|
if name.startswith("OPT") or name.startswith("LINKS") or name.startswith("NEW -"):
|
|
return True
|
|
return False
|
|
|
|
filtered = [t for t in feb26 if is_target(t)]
|
|
|
|
# Sort by due date ascending (no due date = sort last)
|
|
def sort_key(t):
|
|
if t.due_date:
|
|
return int(t.due_date)
|
|
return float("inf")
|
|
|
|
filtered.sort(key=sort_key)
|
|
top10 = filtered[:10]
|
|
|
|
def fmt_due(ms_str):
|
|
if not ms_str:
|
|
return "No due"
|
|
ts = int(ms_str) / 1000
|
|
return datetime.fromtimestamp(ts, tz=UTC).strftime("%b %d")
|
|
|
|
def fmt_customer(t):
|
|
c = t.custom_fields.get("Customer", "")
|
|
if c and str(c) != "None":
|
|
return str(c)
|
|
return t.list_name
|
|
|
|
def fmt_cat(t):
|
|
cat = t.task_type
|
|
name = t.name.upper()
|
|
if not cat or cat.strip() == "":
|
|
if name.startswith("LINKS"):
|
|
return "LINKS"
|
|
elif name.startswith("OPT"):
|
|
return "OPT"
|
|
elif name.startswith("NEW"):
|
|
return "Content"
|
|
return "?"
|
|
mapping = {
|
|
"On Page Optimization": "OPT",
|
|
"Link Building": "LINKS",
|
|
"Content Creation": "Content",
|
|
}
|
|
return mapping.get(cat, cat)
|
|
|
|
def fmt_tags(t):
|
|
return ", ".join(t.tags) if t.tags else ""
|
|
|
|
print(f"## feb26 To-Do: OPT / LINKS / Content ({len(filtered)} total, showing top 10 oldest)")
|
|
print()
|
|
print("| # | ID | Keyword/Name | Due | Customer | Tags |")
|
|
print("|---|-----|-------------|-----|----------|------|")
|
|
for i, t in enumerate(top10, 1):
|
|
name = t.name[:55]
|
|
tid = t.id
|
|
due = fmt_due(t.due_date)
|
|
cust = fmt_customer(t)
|
|
tags = fmt_tags(t)
|
|
print(f"| {i} | {tid} | {name} | {due} | {cust} | {tags} |")
|
|
|
|
if len(filtered) > 10:
|
|
print()
|
|
remaining = filtered[10:]
|
|
print(f"### Remaining {len(remaining)} tasks:")
|
|
print("| # | ID | Keyword/Name | Due | Customer | Tags |")
|
|
print("|---|-----|-------------|-----|----------|------|")
|
|
for i, t in enumerate(remaining, 11):
|
|
name = t.name[:55]
|
|
print(f"| {i} | {t.id} | {name} | {fmt_due(t.due_date)} | {fmt_customer(t)} | {fmt_tags(t)} |")
|
|
|
|
print()
|
|
print(f"*{len(filtered)} matching tasks, {len(feb26)} total feb26 tasks, {len(tasks)} total to-do*")
|