CheddahBot/scripts/clickup_feb26_query.py

121 lines
4.0 KiB
Python

"""Query ClickUp 'to do' tasks tagged feb26 in OPT/LINKS/Content categories."""
import sys
from pathlib import Path
from datetime import datetime, timezone
# Add project root to path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
from cheddahbot.config import load_config
from cheddahbot.clickup import ClickUpClient
def ms_to_date(ms_str: str) -> str:
"""Convert Unix-ms timestamp string to YYYY-MM-DD."""
if not ms_str:
return ""
try:
ts = int(ms_str) / 1000
return datetime.fromtimestamp(ts, tz=timezone.utc).strftime("%Y-%m-%d")
except (ValueError, OSError):
return ""
def main():
cfg = load_config()
if not cfg.clickup.api_token or not cfg.clickup.space_id:
print("ERROR: CLICKUP_API_TOKEN or CLICKUP_SPACE_ID not set.")
return
client = ClickUpClient(
api_token=cfg.clickup.api_token,
workspace_id=cfg.clickup.workspace_id,
task_type_field_name=cfg.clickup.task_type_field_name,
)
# Step 1: Get folders, find OPT/LINKS/Content
target_folders = {"opt", "links", "content"}
try:
folders = client.get_folders(cfg.clickup.space_id)
except Exception as e:
print(f"ERROR fetching folders: {e}")
client.close()
return
print(f"All folders: {[f['name'] for f in folders]}")
matched_lists = [] # (list_id, list_name, folder_name)
for folder in folders:
if folder["name"].lower() in target_folders:
for lst in folder["lists"]:
matched_lists.append((lst["id"], lst["name"], folder["name"]))
if not matched_lists:
print(f"No folders matching {target_folders}. Falling back to full space scan.")
try:
tasks = client.get_tasks_from_space(cfg.clickup.space_id, statuses=["to do"])
finally:
client.close()
else:
print(f"Querying lists: {[(ln, fn) for _, ln, fn in matched_lists]}")
tasks = []
for list_id, list_name, folder_name in matched_lists:
try:
batch = client.get_tasks(list_id, statuses=["to do"])
# Stash folder name on each task for display
for t in batch:
t._folder = folder_name
tasks.extend(batch)
except Exception as e:
print(f" Error fetching {list_name}: {e}")
client.close()
print(f"Total 'to do' tasks from target folders: {len(tasks)}")
# Filter by "feb26" tag (case-insensitive)
tagged = [t for t in tasks if any(tag.lower() == "feb26" for tag in t.tags)]
if not tagged:
print(f"No 'to do' tasks with 'feb26' tag found.")
all_tags = set()
for t in tasks:
all_tags.update(t.tags)
print(f"Tags found across all to-do tasks: {sorted(all_tags)}")
return
filtered = tagged
# Sort by due date (oldest first), tasks without due date go last
def sort_key(t):
if t.due_date:
return (0, int(t.due_date))
return (1, 0)
filtered.sort(key=sort_key)
# Take top 10
top10 = filtered[:10]
# Build table
print(f"\n## ClickUp 'to do' — feb26 tag — OPT/LINKS/Content ({len(filtered)} total, showing top 10)\n")
print(f"{'#':<3} | {'ID':<12} | {'Keyword/Name':<40} | {'Due':<12} | {'Customer':<20} | Tags")
print(f"{''*3} | {''*12} | {''*40} | {''*12} | {''*20} | {''*15}")
for i, t in enumerate(top10, 1):
customer = t.custom_fields.get("Customer", "") or ""
due = ms_to_date(t.due_date)
tags = ", ".join(t.tags) if t.tags else ""
name = t.name[:38] + ".." if len(t.name) > 40 else t.name
print(f"{i:<3} | {t.id:<12} | {name:<40} | {due:<12} | {customer:<20} | {tags}")
print(f"\nCategory breakdown:")
from collections import Counter
cats = Counter(t.task_type for t in filtered)
for cat, count in cats.most_common():
print(f" {cat or '(none)'}: {count}")
if __name__ == "__main__":
main()