File size: 6,589 Bytes
b08d8a8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env python3
"""
Google Sheets Sync
Downloads data from Google Sheets and saves as CSV files
"""

import json
import os
import sys
from pathlib import Path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google.oauth2 import service_account
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError

# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']

# Paths
BASE_DIR = Path(__file__).parent.parent
CONFIG_FILE = BASE_DIR / "config.json"
SHEETS_OUTPUT_DIR = BASE_DIR / "sheets_output"


def load_config():
    """Load configuration from config.json"""
    if not CONFIG_FILE.exists():
        print(f"❌ Config file not found: {CONFIG_FILE}")
        sys.exit(1)
    
    with open(CONFIG_FILE, 'r') as f:
        return json.load(f)


def get_credentials(config):
    """Get Google Sheets API credentials"""
    creds = None
    credentials_file = BASE_DIR / config['google_sheets']['credentials_file']
    token_file = BASE_DIR / 'token.json'
    
    # Check if credentials file exists
    if not credentials_file.exists():
        print(f"❌ Credentials file not found: {credentials_file}")
        print("\nπŸ“ To set up Google Sheets API:")
        print("1. Go to https://console.cloud.google.com/")
        print("2. Create a new project or select existing")
        print("3. Enable Google Sheets API")
        print("4. Create credentials (OAuth 2.0 or Service Account)")
        print(f"5. Download credentials.json to {BASE_DIR}")
        sys.exit(1)
    
    # Try service account first (recommended for automation)
    try:
        creds = service_account.Credentials.from_service_account_file(
            str(credentials_file), scopes=SCOPES)
        print("βœ… Using service account credentials")
        return creds
    except Exception:
        pass
    
    # Fall back to OAuth flow
    if token_file.exists():
        creds = Credentials.from_authorized_user_file(str(token_file), SCOPES)
    
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                str(credentials_file), SCOPES)
            creds = flow.run_local_server(port=0)
        
        # Save the credentials for the next run
        with open(token_file, 'w') as token:
            token.write(creds.to_json())
    
    print("βœ… Using OAuth credentials")
    return creds


def download_sheet_as_csv(service, spreadsheet_id, sheet_name, output_filename):
    """Download a specific sheet as CSV"""
    try:
        # Get the sheet data
        result = service.spreadsheets().values().get(
            spreadsheetId=spreadsheet_id,
            range=f"{sheet_name}!A:Z"  # Adjust range as needed
        ).execute()
        
        values = result.get('values', [])
        
        if not values:
            print(f"⚠️  No data found in sheet: {sheet_name}")
            return False
        
        # Write to CSV
        output_file = SHEETS_OUTPUT_DIR / output_filename
        SHEETS_OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
        
        import csv
        with open(output_file, 'w', newline='', encoding='utf-8') as f:
            writer = csv.writer(f)
            writer.writerows(values)
        
        print(f"βœ… Downloaded {sheet_name} β†’ {output_filename}")
        print(f"   {len(values)} rows")
        return True
        
    except HttpError as error:
        print(f"❌ Error downloading {sheet_name}: {error}")
        return False


def sync_all_sheets():
    """Sync all configured sheets from Google Sheets"""
    config = load_config()
    
    if not config['google_sheets']['enabled']:
        print("⚠️  Google Sheets sync is disabled in config.json")
        return False
    
    # Check if using new multi-spreadsheet config
    spreadsheets = config['google_sheets'].get('spreadsheets', [])
    
    if not spreadsheets:
        # Fallback to old single spreadsheet config
        spreadsheet_id = config['google_sheets'].get('spreadsheet_id', 'YOUR_SHEET_ID_HERE')
        if spreadsheet_id == "YOUR_SHEET_ID_HERE":
            print("❌ Please update config.json with your spreadsheet IDs")
            print("\nπŸ“ To find your spreadsheet ID:")
            print("Open your Google Sheet and copy the ID from the URL:")
            print("https://docs.google.com/spreadsheets/d/[SPREADSHEET_ID]/edit")
            return False
        
        # Convert old format to new format for processing
        spreadsheets = [{
            'name': 'Main Spreadsheet',
            'spreadsheet_id': spreadsheet_id,
            'sheets': config['google_sheets'].get('sheets', {})
        }]
    
    print("πŸ”„ Starting Google Sheets sync...")
    print(f"πŸ“Š Syncing from {len(spreadsheets)} spreadsheet(s)\n")
    
    try:
        creds = get_credentials(config)
        service = build('sheets', 'v4', credentials=creds)
        
        total_success = 0
        total_sheets = 0
        
        # Process each spreadsheet
        for spreadsheet in spreadsheets:
            spreadsheet_id = spreadsheet.get('spreadsheet_id', '')
            spreadsheet_name = spreadsheet.get('name', 'Unnamed')
            sheets_config = spreadsheet.get('sheets', {})
            
            if not spreadsheet_id or spreadsheet_id.startswith('YOUR_'):
                print(f"⚠️  Skipping '{spreadsheet_name}': ID not configured")
                continue
            
            print(f"πŸ“‹ {spreadsheet_name}")
            print(f"   ID: {spreadsheet_id[:20]}...")
            
            # Download each sheet from this spreadsheet
            for csv_name, sheet_name in sheets_config.items():
                total_sheets += 1
                if download_sheet_as_csv(service, spreadsheet_id, sheet_name, f"{csv_name}.csv"):
                    total_success += 1
            
            print()  # Blank line between spreadsheets
        
        print(f"✨ Sync complete: {total_success}/{total_sheets} sheets downloaded")
        return total_success > 0
        
    except Exception as e:
        print(f"❌ Error during sync: {e}")
        return False


def main():
    """Main entry point"""
    sync_all_sheets()


if __name__ == '__main__':
    main()