Spaces:
Running
Running
| import streamlit as st | |
| from google.oauth2.credentials import Credentials | |
| from google_auth_oauthlib.flow import Flow | |
| from googleapiclient.discovery import build | |
| from googleapiclient.errors import HttpError | |
| from google.auth.transport.requests import Request | |
| import pandas as pd | |
| from datetime import datetime | |
| import os | |
| import json | |
| import hashlib | |
| import re | |
| from io import BytesIO | |
| SCOPES = ['https://www.googleapis.com/auth/spreadsheets', 'https://www.googleapis.com/auth/drive.file'] | |
| TOKEN_FILE = 'token.json' | |
| def get_redirect_uri(): | |
| return st.get_option("server.baseUrlPath") or "http://localhost:8501" | |
| def initiate_google_auth(): | |
| if not os.path.exists('client_secret.json'): | |
| st.error("Google Sheets integration is not set up correctly.") | |
| st.markdown( | |
| "Please follow the setup guide for Google Sheets integration in the " | |
| "[CyberScraper-2077 README](https://github.com/itsOwen/CyberScraper-2077/blob/main/README.md#setup-google-sheets-authentication)." | |
| ) | |
| st.info("Once you've completed the setup, restart the application.") | |
| return | |
| flow = Flow.from_client_secrets_file( | |
| 'client_secret.json', | |
| scopes=SCOPES, | |
| redirect_uri=get_redirect_uri() | |
| ) | |
| authorization_url, state = flow.authorization_url(prompt='consent') | |
| st.session_state['oauth_state'] = state | |
| st.markdown(f"Please visit this URL to authorize the application: [Auth URL]({authorization_url})") | |
| st.info("After authorizing, you'll be redirected back to this app. Then you can proceed with uploading.") | |
| def get_google_sheets_credentials(): | |
| if not os.path.exists('client_secret.json'): | |
| return None | |
| creds = None | |
| if os.path.exists(TOKEN_FILE): | |
| try: | |
| creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES) | |
| except Exception as e: | |
| print(f"Error loading credentials from file: {str(e)}") | |
| if not creds or not creds.valid: | |
| if creds and creds.expired and creds.refresh_token: | |
| try: | |
| creds.refresh(Request()) | |
| save_credentials(creds) | |
| except Exception as e: | |
| print(f"Error refreshing credentials: {str(e)}") | |
| creds = None | |
| else: | |
| creds = None | |
| if not creds: | |
| if 'google_auth_token' in st.session_state: | |
| try: | |
| creds = Credentials.from_authorized_user_info(json.loads(st.session_state['google_auth_token']), SCOPES) | |
| save_credentials(creds) | |
| except Exception as e: | |
| print(f"Error creating credentials from session state: {str(e)}") | |
| return creds | |
| def save_credentials(creds): | |
| try: | |
| with open(TOKEN_FILE, 'w') as token: | |
| token.write(creds.to_json()) | |
| except Exception as e: | |
| print(f"Error saving credentials: {str(e)}") | |
| def clean_data_for_sheets(df): | |
| def clean_value(val): | |
| if pd.isna(val): | |
| return "" | |
| if isinstance(val, (int, float)): | |
| return str(val) | |
| return str(val).replace('\n', ' ').replace('\r', '') | |
| for col in df.columns: | |
| df[col] = df[col].map(clean_value) | |
| if 'comments' in df.columns: | |
| df['comments'] = df['comments'].astype(str) | |
| return df | |
| def upload_to_google_sheets(data): | |
| creds = get_google_sheets_credentials() | |
| if not creds: | |
| return None | |
| try: | |
| service = build('sheets', 'v4', credentials=creds) | |
| spreadsheet = { | |
| 'properties': { | |
| 'title': f"CyberScraper Data {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" | |
| } | |
| } | |
| spreadsheet = service.spreadsheets().create(body=spreadsheet, fields='spreadsheetId').execute() | |
| spreadsheet_id = spreadsheet.get('spreadsheetId') | |
| if isinstance(data, pd.DataFrame): | |
| df = clean_data_for_sheets(data) | |
| else: | |
| return None | |
| values = [df.columns.tolist()] + df.values.tolist() | |
| body = {'values': values} | |
| result = service.spreadsheets().values().update( | |
| spreadsheetId=spreadsheet_id, range='Sheet1', | |
| valueInputOption='RAW', body=body).execute() | |
| return spreadsheet_id | |
| except HttpError as error: | |
| print(f"An HTTP error occurred: {error}") | |
| return None | |
| except Exception as e: | |
| print(f"An error occurred: {str(e)}") | |
| return None | |
| def display_google_sheets_button(data, unique_key): | |
| if not os.path.exists('client_secret.json'): | |
| st.warning("Google Sheets integration is not set up.") | |
| st.markdown( | |
| "To enable Google Sheets integration, please follow the setup guide in the " | |
| "[CyberScraper-2077 README](https://github.com/itsOwen/CyberScraper-2077/blob/main/README.md#setup-google-sheets-authentication)." | |
| ) | |
| return | |
| creds = get_google_sheets_credentials() | |
| if not creds: | |
| auth_button = '🔑 Authorize Google Sheets' | |
| if st.button(auth_button, key=f"auth_sheets_{unique_key}", help="Authorize access to Google Sheets"): | |
| initiate_google_auth() | |
| else: | |
| upload_button = '✅ Upload to Google Sheets' | |
| if st.button(upload_button, key=f"upload_{unique_key}", help="Upload data to Google Sheets"): | |
| with st.spinner("Uploading to Google Sheets..."): | |
| spreadsheet_id = upload_to_google_sheets(data) | |
| if spreadsheet_id: | |
| st.success(f"Hey Choom! Data uploaded successfully. Spreadsheet ID: {spreadsheet_id}") | |
| st.markdown(f"[Open Spreadsheet](https://docs.google.com/spreadsheets/d/{spreadsheet_id})") | |
| else: | |
| st.error("Failed to upload data to Google Sheets. Check the console for error details.") | |