diff --git a/workflowy-helper/main.py b/workflowy-helper/main.py new file mode 100644 index 0000000..8925bdf --- /dev/null +++ b/workflowy-helper/main.py @@ -0,0 +1,4 @@ +from constants import Constants + + + diff --git a/workflowy-helper/storage.py b/workflowy-helper/storage.py new file mode 100644 index 0000000..6595646 --- /dev/null +++ b/workflowy-helper/storage.py @@ -0,0 +1,36 @@ +import json +import os + +from .logging import logger +from .constants import Constants + + +def load_storage(): + if os.path.exists(Constants.STORAGE): + logger.debug(f"Loading storage from {Constants.STORAGE}") + with open(Constants.STORAGE, "r") as f: + return json.load(f) + return {} + + +def save_storage(data): + with open(Constants.STORAGE, "w") as f: + json.dump(data, f) + + +def save_to_storage(key, value): + storage = load_storage() + storage[key] = value + save_storage(storage) + + +def load_from_storage(key): + storage = load_storage() + if key in storage: + return storage[key] + return {} + + +def clear_storage(): + if os.path.exists(Constants.STORAGE): + os.remove(Constants.STORAGE) diff --git a/workflowy-helper/wf/archive/constants.py b/workflowy-helper/wf/archive/constants.py new file mode 100644 index 0000000..00bf892 --- /dev/null +++ b/workflowy-helper/wf/archive/constants.py @@ -0,0 +1,17 @@ +import os + +class Constants: + STORAGE = os.path.join(os.path.expanduser('~'), 'wf.json') + INBOX_ID = "13859f14-79ab-b758-7224-8dad0236f1e2" + TASKS_ID = "042d7e11-f613-856c-fb97-c0e6ee7ece05" + DIARY_ID = "01205285-f5b1-8026-0cfa-942f514e297e" + LIFE_IDS = { + "life": "f6f993a3-c696-c070-296e-6e5055fc834f", + "admin": "d3911123-138e-8eb3-f2ba-2495d8169660", + "art": "c2e9f4b2-59ce-d127-4da6-949e54ec1442", + "health": "4fc929b8-f04b-0dde-9a1a-9d889a13316d", + "mind": "c6db70a1-72e3-dbcc-f4b9-bfb10a1b4280", + "social": "60e3d667-eb40-3d26-cc3f-6b151cc5efa4", + "church": "5c68fad5-ad2b-8018-6535-b1462aed1277", + "work": "4c4970fc-9023-f861-1392-dbf88dd89187", + } diff --git a/workflowy-helper/wf/archive/helpers.py b/workflowy-helper/wf/archive/helpers.py new file mode 100644 index 0000000..a710d5a --- /dev/null +++ b/workflowy-helper/wf/archive/helpers.py @@ -0,0 +1,32 @@ +import json +import os +import uuid +from datetime import datetime, timedelta +from constants import Constants +from logging import logger + + +def get_ordinal(n): + if 10 <= n % 100 <= 20: + suffix = 'th' + else: + suffix = {1: 'st', 2: 'nd', 3: 'rd'}.get(n % 10, 'th') + return str(n) + suffix + + +def get_today(): + now = datetime.now() + return now.strftime("%a, %b %d, %Y") + + +def get_sunday(): + now = datetime.now() + sunday = now - timedelta(days=now.weekday()) - timedelta(days=1) + return sunday.strftime("%a, %b %d, %Y") + + +def generate_uuid(): + return str(uuid.uuid4()) + + + diff --git a/workflowy-helper/wf/archive/main.py b/workflowy-helper/wf/archive/main.py new file mode 100644 index 0000000..e69de29 diff --git a/workflowy-helper/wf/archive/theme.py b/workflowy-helper/wf/archive/theme.py new file mode 100644 index 0000000..b8acd59 --- /dev/null +++ b/workflowy-helper/wf/archive/theme.py @@ -0,0 +1,36 @@ +from rich.theme import Theme + +solarized_theme = Theme({ + "base03": "bright_black", + "base02": "black", + "base01": "bright_green", + "base00": "bright_yellow", + "base0": "bright_blue", + "base1": "bright_cyan", + "base2": "white", + "base3": "bright_white", + "orange": "bright_red", + "violet": "bright_magenta", + "red": "red", + "bold red": "bold red", + "underline base03": "underline bright_black", + "underline base02": "underline black", + "underline base01": "underline bright_green", + "underline base00": "underline bright_yellow", + "underline base0": "underline bright_blue", + "underline base1": "underline bright_cyan", + "underline base2": "underline white", + "underline base3": "underline bright_white", + "underline orange": "bright_red underline", + "underline violet": "bright_magenta underline", + "bold base03": "bold bright_black", + "bold base02": "bold black", + "bold base01": "bold bright_green", + "bold base00": "bold bright_yellow", + "bold base0": "bold bright_blue", + "bold base1": "bold bright_cyan", + "bold base2": "bold white", + "bold base3": "bold bright_white", + "bold orange": "bright_red bold", + "bold violet": "bright_magenta bold", +}) diff --git a/workflowy-helper/wf/console.py b/workflowy-helper/wf/console.py new file mode 100644 index 0000000..311e9be --- /dev/null +++ b/workflowy-helper/wf/console.py @@ -0,0 +1,9 @@ +import logging +from rich.console import Console +from rich.logging import RichHandler +from theme import solarized_theme + +console = Console(highlight=False, theme=solarized_theme) +logging.basicConfig(handlers=[RichHandler(level="NOTSET", console=console)]) +logger = logging.getLogger('rich') +logger.setLevel(logging.INFO) diff --git a/workflowy-helper/wf/main.py b/workflowy-helper/wf/main.py new file mode 100644 index 0000000..1b1dab5 --- /dev/null +++ b/workflowy-helper/wf/main.py @@ -0,0 +1,70 @@ +# main.py + +import os +import json +import requests +import browser_cookie3 + +from .console import console, logger + +class WF: + + def __init__(self): + self._data = {} + self._path = None + + @property + def _cookie(self): + return self._data.get('cookie', None) + + def _load(self): + if os.path.exists(self.path): + logger.info(f'Loading data from {self.path}') + with open(self.path, 'r') as f: + self._data = json.load(f) + else: + logger.warning(f'No data found at {self.path}') + self._data = {} + + def _save(self): + logger.info(f'Saving data to {self.path}') + with open(self.path, 'w') as f: + json.dump(self._data, f) + + def _refresh_cookie(self): + logger.info('Refreshing cookies') + cookies = browser_cookie3.chrome() + for cookie in cookies: + if cookie.name == "sessionid" and "workflowy.com" in cookie.domain: + self._data['cookie'] = cookie.value + break + logger.warning('No cookie found') + + def _refresh_data(self): + if not self._cookie: + logger.warning('No cookie found') + return + logger.info('Refreshing data') + + url = "https://workflowy.com/get_initialization_data?client_version=15" + headers = {"Cookie": f"sessionid={self._cookie}"} + response = requests.get(url, headers=headers) + + if response.status_code == 200: + data = response.json() + data_globals = {item[0]: item[1] for item in data["globals"]} + + self._data["userid"] = data_globals["USER_ID"] + self._data["joined"] = data["projectTreeData"]["mainProjectTreeInfo"]["dateJoinedTimestampInSeconds"] + self._data["transid"] = data["projectTreeData"]["mainProjectTreeInfo"]["initialMostRecentOperationTransactionId"] + self._data["pollid"] = generate_uuid() # Simulate g() + g() + storage["root"] = {"nm": "root", "ch": data["projectTreeData"]["mainProjectTreeInfo"]["rootProjectChildren"]} + save_storage(storage) + console.log("Successfully refreshed and saved Workflowy data.") + + + + + + + diff --git a/workflowy-helper/wf/script.py b/workflowy-helper/wf/script.py index 894c900..7507a66 100755 --- a/workflowy-helper/wf/script.py +++ b/workflowy-helper/wf/script.py @@ -30,7 +30,6 @@ PLANNER_IDS = { "social": "60e3d667-eb40-3d26-cc3f-6b151cc5efa4", "church": "5c68fad5-ad2b-8018-6535-b1462aed1277", "work": "4c4970fc-9023-f861-1392-dbf88dd89187", - "affirm": "a1412d52-c72c-0612-f5b1-48874ef03943", } solarized_theme = Theme({ @@ -357,25 +356,6 @@ def flatten_project(project_data): # {{{ # }}} -# def filter_project_any(project_data, filters): # {{{ -# filtered_project = { -# "name": project_data["name"], -# "id": project_data.get("id", ""), -# # "description": project_data["description"], -# "children": [], -# "format": project_data["format"] -# } -# children = project_data.get("children", []) -# for child in children: -# include = False -# for filter_text in filters: -# if filter_text.lower() in child["name"].lower(): -# include = True -# break -# if include: -# filtered_project["children"].append(filter_project_any(child, filters)) -# return filtered_project - def filter_project_any(project_data, filters, include_headers=False, all_children=False): # {{{ include = False if include_headers: @@ -420,6 +400,7 @@ def filter_project_all(project_data, filters, include_headers=False, all_childre logger.debug(f"Including {project_data['name']}") logger.debug(f"all_children: {all_children}") children = [] + logger.debug(f"children: {project_data.get('children', [])}") for child in project_data.get("children", []): if all_children and include: logger.debug(f"Not filtering children of {project_data['name']}") @@ -862,6 +843,7 @@ def tasks(filter, hide_comments, hide_headers, show_id): def today(filter): """Today commands""" t = get_today() + logger.debug(f"Today: {t}") if filter: show( TASKS_ID, @@ -914,7 +896,6 @@ def refresh_cmd(): refresh_workflowy_data() -# Dynamically add commands for each planner in PLANNER_IDS. def create_planner_command(planner_name, planner_id): @click.command(name=planner_name, help=f"{planner_name.capitalize()} commands") @click.option("--hide-comments", is_flag=True, help="Do not show comments")