https://github.com/ivyleavedtoadflax/googledoc-revision-tracker
Download and track Google Docs revision history with granular time filtering (hourly, daily, weekly, monthly). Python CLI tool with OAuth2 authentication and automatic retry logic.
https://github.com/ivyleavedtoadflax/googledoc-revision-tracker
backup cli document-tracking google-docs google-drive-api oauth2 python revision-history typer version-control
Last synced: 6 months ago
JSON representation
Download and track Google Docs revision history with granular time filtering (hourly, daily, weekly, monthly). Python CLI tool with OAuth2 authentication and automatic retry logic.
- Host: GitHub
- URL: https://github.com/ivyleavedtoadflax/googledoc-revision-tracker
- Owner: ivyleavedtoadflax
- License: mit
- Created: 2025-12-16T15:45:31.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-12-29T22:07:42.000Z (7 months ago)
- Last Synced: 2026-01-02T05:08:02.125Z (7 months ago)
- Topics: backup, cli, document-tracking, google-docs, google-drive-api, oauth2, python, revision-history, typer, version-control
- Language: Python
- Size: 185 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Google Docs Revision Tracker
A Python CLI tool to download and track Google Docs revision history.
## Features
- **Multiple Document Support**: Track revision history for multiple Google Docs simultaneously
- **Revision History Download**: Download all historical revisions as individual timestamped files
- **Granular Time Filtering**: Get final revision per hour, day, week, or month instead of all revisions
- **Custom Folder Names**: Organize revisions with readable folder names
- **Automatic Retry with Backoff**: Handles rate limiting with exponential backoff (up to 5 retries)
- **OAuth Authentication**: Secure authentication with automatic token refresh
- **Flexible Input**: Specify documents via CLI arguments, or config file
- **Simple CLI**: Clean command interface with progress tracking
## Prerequisites
- Python 3.12+
- Google Cloud Project with Drive API enabled
- OAuth 2.0 Client ID credentials
## Setup
### 1. Create Google Cloud Project
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project or select an existing one
3. Navigate to "APIs & Services" > "Library"
4. Enable the **Google Drive API**
### 2. Create OAuth Credentials
1. Go to "APIs & Services" > "Credentials"
2. Click "+ Create Credentials" > "OAuth client ID"
3. Choose "Desktop app" as the application type
4. Download the JSON file and save it (e.g., `client_secrets.json`)
### 3. Configure Documents to Track
You have three options for specifying which documents to track:
**Option 1: YAML Configuration File (Recommended for multiple documents)**
Use the interactive `config` commands to manage your `documents.yaml` file:
```bash
# Initialize a new config file from template
uv run google-sync config init
# Add documents interactively (just paste the URL when prompted)
uv run google-sync config add
# Or add directly with all options
uv run google-sync config add https://docs.google.com/document/d/DOC_ID/edit -n cv-matt -g daily
# List configured documents
uv run google-sync config list
```
Or manually create/edit `documents.yaml`:
```bash
cp documents.yaml.example documents.yaml
# Edit documents.yaml and add your document IDs
```
Example `documents.yaml` with custom folder names and granularity:
```yaml
documents:
- id: 1Q-qMIRexwdCRd38hhCRHEBpXeru2oi54LwfQU7NvWi8
name: cv-matt
granularity: daily # Final revision per day
- id: 2A-bNkPstuvwxCEf45ijKLMNOPabcd6efgh9hijklmno
name: project-proposal
granularity: weekly # Final revision per week
```
**Granularity Options:**
- `all` - Download all revisions (default)
- `hourly` - Final revision per hour
- `daily` - Final revision per day (recommended for active documents)
- `weekly` - Final revision per week (recommended for less active documents)
- `monthly` - Final revision per month (recommended for archived documents)
Simple format (uses document ID, downloads all revisions):
```yaml
documents:
- 1Q-qMIRexwdCRd38hhCRHEBpXeru2oi54LwfQU7NvWi8
```
**Option 2: Environment Variable (Single document)**
Create a `.env` file in the project root:
```bash
# Path to your OAuth client secrets JSON file
GOOGLE_OAUTH_CLIENT_SECRETS=path/to/client_secrets.json
```
**Option 3: CLI Arguments (Ad-hoc usage)**
Pass document IDs or URLs directly when running the download command (see Usage below).
### 4. Install Dependencies
```bash
pip install -r requirements.txt
```
Or if using `uv`:
```bash
uv sync
```
## Usage
### First-Time Setup: Authentication
Before downloading documents, authenticate with Google:
```bash
uv run google-sync auth
```
This will:
1. Open your browser for Google OAuth authorization
2. Ask you to grant access to Google Drive
3. Save credentials to `token.json` for future use
**Re-authenticate (if needed):**
```bash
uv run google-sync auth --force
```
**Custom OAuth timeout:**
```bash
uv run google-sync auth --timeout 300 # 5 minutes instead of default 120s
```
### Managing Configuration
Use the `config` subcommands to manage your `documents.yaml` file:
**Initialize configuration file:**
```bash
uv run google-sync config init # Create from template
uv run google-sync config init --force # Overwrite existing
```
**Add documents to configuration:**
```bash
# Interactive mode - prompts for all fields (paste URL when prompted)
uv run google-sync config add
# Specify document ID, prompt for optional fields
uv run google-sync config add DOC_ID
# Paste full Google Docs URL (from browser)
uv run google-sync config add https://docs.google.com/document/d/DOC_ID/edit
# Non-interactive - provide all options directly
uv run google-sync config add DOC_ID -n my-folder -g daily
uv run google-sync config add DOC_ID --name my-folder --granularity weekly
```
**List configured documents:**
```bash
uv run google-sync config list
```
This shows all documents with their folder names and granularity settings.
### Downloading Documents
Once authenticated, download document revisions:
**Using config file (documents.yaml):**
```bash
uv run google-sync download
```
**Using CLI arguments (one or more documents):**
```bash
# Single document by ID
uv run google-sync download 1Q-qMIRexwdCRd38hhCRHEBpXeru2oi54LwfQU7NvWi8
# Paste full URL from browser
uv run google-sync download https://docs.google.com/document/d/DOC_ID/edit
# Multiple documents (IDs or URLs)
uv run google-sync download DOC_ID_1 DOC_ID_2 https://docs.google.com/document/d/DOC_ID_3/edit
```
**Show all available commands:**
```bash
uv run google-sync --help # Main help
uv run google-sync auth --help # Authentication help
uv run google-sync download --help # Download help
uv run google-sync config --help # Config management help
```
### Output
Revisions are saved to: `revisions/{folder_name}/{timestamp}.txt`
Example folder structure with custom names:
```
revisions/
├── cv-matt/ # Custom name from documents.yaml
│ ├── 2025-07-30T07-18-16-081Z.txt
│ ├── 2025-07-30T07-35-51-386Z.txt
│ └── 2025-12-15T19-31-43-713Z.txt
├── project-proposal/ # Custom name from documents.yaml
│ ├── 2025-08-15T10-22-33-123Z.txt
│ └── 2025-09-20T14-56-12-456Z.txt
└── 1Q-qMIRexwd.../ # Falls back to document ID if no name specified
└── 2025-11-01T09-15-30-500Z.txt
```
- Folders use custom names from `documents.yaml` (if specified)
- If no custom name provided, uses document ID (stable and unique)
- Document titles are displayed in the CLI output for reference
- Each filename is the exact modification timestamp from Google Drive
## Error Messages
The tool provides friendly error messages for common issues:
**Document not found (404):**
```
✗ Document not found: DOC_ID
→ Check that the document ID is correct
→ Ensure you have access to this document
```
**Permission denied (403):**
```
✗ Permission denied: DOC_ID
→ You don't have permission to access this document
→ Ask the owner to share it with you
```
**Authentication error (401):**
```
✗ Authentication error: DOC_ID
→ Try re-authenticating with: google-sync auth --force
```
## Project Structure
```
google-sync-simple/
├── main.py # CLI interface and OAuth flow
├── drive_revisions.py # Core Google Drive API functionality
├── documents.yaml # Document IDs and custom names (not committed)
├── documents.yaml.example # Example document configuration
├── .env # Environment variables (not committed)
├── token.json # OAuth credentials (generated, not committed)
└── revisions/ # Downloaded revision history
├── cv-matt/ # Custom folder name from documents.yaml
└── project-proposal/ # Or document ID if no name specified
```
## How It Works
1. **Resolve Document IDs**: Checks CLI arguments, config file, or environment variable
2. **Authenticate**: Uses Google OAuth 2.0 (opens browser on first run)
3. **For Each Document**:
- Fetches document title via Drive API v3 (for display)
- Creates folder using custom name or document ID
- Uses Drive API v2 to list all document revisions (v3 doesn't support this)
- Filters revisions by granularity (if not 'all')
4. **Download Revisions**: For each filtered revision:
- Gets the plain text export link from the API
- Downloads with OAuth bearer token authentication
- Automatically retries with exponential backoff on rate limiting (429 errors)
- Saves with ISO 8601 timestamp as filename
5. **Save**: Filtered revisions stored in `revisions/{folder_name}/`
**Example with daily granularity:**
```
9 total revisions → 4 daily snapshots (final revision per day)
```
## Troubleshooting
### "Missing required environment variable" Error
Ensure your `.env` file exists and contains both required variables:
- `GOOGLE_OAUTH_CLIENT_SECRETS`
### "Authorization timed out" Error
Increase the timeout:
```bash
python main.py --timeout 300
```
### "Insufficient permissions" or "Access denied"
1. Delete `token.json`
2. Re-run the command to re-authenticate with updated scopes
3. Ensure your Google account has access to the document
### No revisions found
The Drive API v2 only returns "grouped" revisions. Fine-grained revision history visible in the Google Docs UI may not all be accessible via the API.
### "HTTP Error 429: Too Many Requests"
Google API rate limits may be hit when downloading many revisions. The tool will skip failed revisions and continue with the rest. Re-run the command to retry failed downloads.
## Development
### Running Tests
```bash
# TODO: Add test suite
```
### Code Structure
- `drive_revisions.py`: Core functions for Google Drive operations and revision downloads
- `main.py`: Typer CLI interface and OAuth flow management
- `documents.yaml`: Configuration file for tracking multiple documents