ticktick_setup.py•12.7 kB
#!/usr/bin/env python3
"""
TickTick Setup Script for Health & Marriage Tracking System
This script creates the complete tracking structure in TickTick including:
- Projects (Marriage, Health, Milestones)
- Recurring daily and weekly tasks
- Checklists for protocols
- Tags for organization
Usage:
python ticktick_setup.py --setup # Initial setup - create all projects and tasks
python ticktick_setup.py --add # Add a new task/log entry
python ticktick_setup.py --status # View current status
"""
import os
from datetime import datetime, timedelta
from ticktick.oauth2 import OAuth2
from ticktick.api import TickTickClient
from dotenv import load_dotenv
import argparse
# Load environment variables
load_dotenv()
# Fix for TickTick API endpoint change (signin -> signon)
# See: https://github.com/lazeroffmichael/ticktick-py/issues/56
def new_login(self, username, password):
"""Fixed login method using 'signon' endpoint instead of deprecated 'signin'"""
url = self.BASE_URL + 'user/signon'
user_info = {'username': username, 'password': password}
parameters = {'wc': True, 'remember': True}
response = self.http_post(url, json=user_info, params=parameters, headers=self.HEADERS)
self.access_token = response['token']
self.cookies['t'] = self.access_token
# Monkey patch the login method
TickTickClient._login = new_login
class HealthMarriageTracker:
def __init__(self):
"""Initialize TickTick client with OAuth2"""
# Get OAuth credentials
client_id = os.getenv('TICKTICK_CLIENT_ID')
client_secret = os.getenv('TICKTICK_CLIENT_SECRET')
redirect_uri = os.getenv('TICKTICK_REDIRECT_URI', 'http://127.0.0.1:8080')
# Get account credentials
username = os.getenv('TICKTICK_USERNAME')
password = os.getenv('TICKTICK_PASSWORD')
if not all([client_id, client_secret, username, password]):
raise ValueError(
"Required environment variables:\n"
" TICKTICK_CLIENT_ID (from developer.ticktick.com)\n"
" TICKTICK_CLIENT_SECRET (from developer.ticktick.com)\n"
" TICKTICK_USERNAME (your TickTick email)\n"
" TICKTICK_PASSWORD (your TickTick password)"
)
# Initialize OAuth2 with app credentials
auth_client = OAuth2(
client_id=client_id,
client_secret=client_secret,
redirect_uri=redirect_uri
)
# Initialize client
self.client = TickTickClient(username, password, auth_client)
# Will store project IDs
self.projects = {}
def create_project(self, name, color="#3F51B5"):
"""Create a project/list in TickTick"""
print(f"Creating project: {name}")
project = self.client.project.builder(name=name, color=color)
created = self.client.project.create(project)
self.projects[name] = created['id']
return created['id']
def create_marriage_tasks(self, project_id):
"""Create all marriage-related recurring tasks"""
print("\nCreating Marriage tasks...")
# Sunday Night Check-in (Weekly)
checkin_content = """6 Questions Framework:
1. Connection Score (1-10)
2. What Made Me Feel Loved
3. What Hurt or Frustrated Me
4. Body/Aging Struggle This Week
5. Intimacy Check
6. What I Need Next Week
Process:
- Both write answers (10 min)
- Share and listen (15 min)
- Connect physically (5 min)"""
task = self.client.task.builder(
title="Sunday Marriage Check-in (8pm)",
content=checkin_content,
projectId=project_id,
priority=5, # High priority
repeat="RRULE:FREQ=WEEKLY;BYDAY=SU",
startDate=self._get_next_sunday(20, 0), # 8pm
dueDate=self._get_next_sunday(20, 30) # 8:30pm
)
self.client.task.create(task)
print(" ✓ Sunday Marriage Check-in created")
# Monthly Review
review_content = """Monthly Review Questions:
1. Are connection scores trending up?
2. Is intimacy frequency improving?
3. What patterns are emerging?
4. What needs adjustment?
5. Should we celebrate progress?"""
task = self.client.task.builder(
title="Monthly Marriage Review",
content=review_content,
projectId=project_id,
priority=3,
repeat="RRULE:FREQ=MONTHLY;BYMONTHDAY=1"
)
self.client.task.create(task)
print(" ✓ Monthly Marriage Review created")
def create_health_tasks(self, project_id):
"""Create all health-related recurring tasks"""
print("\nCreating Health tasks...")
# Daily tasks
daily_tasks = [
{
"title": "Morning Movement (30 min)",
"content": "Walk, run, gym, or cycling - minimum 30 minutes",
"priority": 5
},
{
"title": "Track Mood (1-10)",
"content": "Rate mood 1-10 + note any triggers",
"priority": 3
},
{
"title": "Water (64 oz)",
"content": "Track water intake throughout the day",
"priority": 1
},
{
"title": "In Bed by 10:30pm",
"content": "Wind down routine, no screens after 10pm",
"priority": 3
}
]
for task_data in daily_tasks:
task = self.client.task.builder(
title=task_data["title"],
content=task_data["content"],
projectId=project_id,
priority=task_data["priority"],
repeat="RRULE:FREQ=DAILY;INTERVAL=1"
)
self.client.task.create(task)
print(f" ✓ {task_data['title']} created")
# Weekly tasks
# Sunday morning weigh-in
task = self.client.task.builder(
title="Weekly Weigh-in",
content="Weigh in same time, same scale. Record in logs.",
projectId=project_id,
priority=3,
repeat="RRULE:FREQ=WEEKLY;BYDAY=SU",
startDate=self._get_next_sunday(8, 0)
)
self.client.task.create(task)
print(" ✓ Weekly Weigh-in created")
# Sunday meal prep
task = self.client.task.builder(
title="Sunday Meal Prep",
content="Prepare healthy meals for the week",
projectId=project_id,
priority=3,
repeat="RRULE:FREQ=WEEKLY;BYDAY=SU",
startDate=self._get_next_sunday(14, 0)
)
self.client.task.create(task)
print(" ✓ Sunday Meal Prep created")
# Weekly review
review_content = """Weekly Review:
- Weight change: _____
- Exercise days: ___/7
- Average mood: _____
- Patterns noticed: _____
- Next week focus: _____"""
task = self.client.task.builder(
title="Weekly Health Review",
content=review_content,
projectId=project_id,
priority=3,
repeat="RRULE:FREQ=WEEKLY;BYDAY=SU"
)
self.client.task.create(task)
print(" ✓ Weekly Health Review created")
def create_milestone_tasks(self, project_id):
"""Create milestone tracking tasks"""
print("\nCreating Milestone tasks...")
# 30-day milestones
thirty_day_content = """30-Day Targets:
Marriage:
- [ ] 4 consecutive marriage check-ins
- [ ] Intimacy: 2x/week average
- [ ] Connection score: 6 → 7
Health:
- [ ] Weight: -5 lbs (230 → 225)
- [ ] Exercise: 20/30 days
- [ ] Mood: Average 6+"""
task = self.client.task.builder(
title="30-Day Milestone Check",
content=thirty_day_content,
projectId=project_id,
priority=5,
dueDate=datetime.now() + timedelta(days=30)
)
self.client.task.create(task)
print(" ✓ 30-Day Milestone created")
# 90-day milestones
ninety_day_content = """90-Day Targets:
Marriage:
- [ ] 12 consecutive check-ins
- [ ] Marriage quality: 8/10
- [ ] Depression days: <5/month
Health:
- [ ] Weight: -15 lbs (230 → 215)
- [ ] Run 5K without stopping
- [ ] Exercise habit established"""
task = self.client.task.builder(
title="90-Day Milestone Check",
content=ninety_day_content,
projectId=project_id,
priority=5,
dueDate=datetime.now() + timedelta(days=90)
)
self.client.task.create(task)
print(" ✓ 90-Day Milestone created")
# 180-day vision
vision_content = """6-Month Vision:
- [ ] Weight: 195 lbs
- [ ] 10K capability restored
- [ ] Marriage: Consistent 8+/10
- [ ] Aging together, not alone
- [ ] Stress managed proactively"""
task = self.client.task.builder(
title="6-Month Vision Check",
content=vision_content,
projectId=project_id,
priority=5,
dueDate=datetime.now() + timedelta(days=180)
)
self.client.task.create(task)
print(" ✓ 6-Month Vision created")
def setup_complete_system(self):
"""Create entire tracking system in TickTick"""
print("=" * 50)
print("Setting up Health & Marriage Tracking System")
print("=" * 50)
# Create projects
marriage_id = self.create_project("Marriage", "#E91E63") # Pink
health_id = self.create_project("Health", "#4CAF50") # Green
milestones_id = self.create_project("Milestones", "#FF9800") # Orange
# Create tasks in each project
self.create_marriage_tasks(marriage_id)
self.create_health_tasks(health_id)
self.create_milestone_tasks(milestones_id)
print("\n" + "=" * 50)
print("✓ Setup Complete!")
print("=" * 50)
print("\nYour TickTick is now configured with:")
print(" • Marriage project with weekly check-ins")
print(" • Health project with daily/weekly tracking")
print(" • Milestone project with 30/60/90/180-day targets")
print("\nOpen TickTick to start tracking!")
def add_daily_log(self, log_type, data):
"""Add a one-off log entry"""
# Implementation for adding custom logs
pass
def _get_next_sunday(self, hour=0, minute=0):
"""Get next Sunday at specified time"""
today = datetime.now()
days_until_sunday = (6 - today.weekday()) % 7
if days_until_sunday == 0 and today.hour >= hour:
days_until_sunday = 7
next_sunday = today + timedelta(days=days_until_sunday)
return next_sunday.replace(hour=hour, minute=minute, second=0, microsecond=0)
def view_status(self):
"""View current tasks and status"""
print("\n" + "=" * 50)
print("Current Status")
print("=" * 50)
# Get all tasks
tasks = self.client.state['tasks']
# Group by project
by_project = {}
for task in tasks:
project_id = task.get('projectId', 'inbox')
if project_id not in by_project:
by_project[project_id] = []
by_project[project_id].append(task)
# Display
for project_id, project_tasks in by_project.items():
# Get project name
project = self.client.get_by_id(project_id, search='projects')
project_name = project['name'] if project else 'Inbox'
print(f"\n{project_name} ({len(project_tasks)} tasks):")
for task in project_tasks[:5]: # Show first 5
status = "✓" if task.get('status') == 2 else "○"
print(f" {status} {task['title']}")
def main():
parser = argparse.ArgumentParser(
description="Health & Marriage TickTick Tracking System"
)
parser.add_argument(
'--setup',
action='store_true',
help='Initial setup - create all projects and tasks'
)
parser.add_argument(
'--status',
action='store_true',
help='View current status'
)
parser.add_argument(
'--add',
action='store_true',
help='Add a new log entry (interactive)'
)
args = parser.parse_args()
# Initialize tracker
tracker = HealthMarriageTracker()
if args.setup:
tracker.setup_complete_system()
elif args.status:
tracker.view_status()
elif args.add:
print("Interactive log entry coming soon...")
else:
parser.print_help()
if __name__ == "__main__":
main()