final_project / app /google_oauth.py
Ana2012's picture
Update app/google_oauth.py
c7832ca verified
Raw
History Blame Contribute Delete
4.86 kB
import json
import os
import tempfile
from pathlib import Path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive.file",
]
TOKEN_FILENAME = "google_token.json"
DATA_DIR = Path("/data")
FALLBACK_DATA_DIR = Path(tempfile.gettempdir()) / "tcc2_agent"
class GoogleOAuthError(RuntimeError):
pass
class GoogleAuthRequiredError(GoogleOAuthError):
pass
def _resolve_data_dir():
preferred_dir = os.environ.get("GOOGLE_TOKEN_DIR", "").strip()
candidates = [Path(preferred_dir)] if preferred_dir else []
candidates.extend([DATA_DIR, FALLBACK_DATA_DIR])
for directory in candidates:
try:
directory.mkdir(parents=True, exist_ok=True)
return directory
except OSError:
continue
raise GoogleOAuthError(
"Nao foi possivel criar um diretorio para armazenar o token OAuth."
)
def get_token_path():
return _resolve_data_dir() / TOKEN_FILENAME
def _client_config():
client_id = os.environ.get("GOOGLE_CLIENT_ID", "").strip()
client_secret = os.environ.get("GOOGLE_CLIENT_SECRET", "").strip()
redirect_uri = os.environ.get("GOOGLE_REDIRECT_URI", "").strip()
missing = [
name
for name, value in {
"GOOGLE_CLIENT_ID": client_id,
"GOOGLE_CLIENT_SECRET": client_secret,
"GOOGLE_REDIRECT_URI": redirect_uri,
}.items()
if not value
]
if missing:
raise GoogleOAuthError("Variaveis OAuth ausentes: " + ", ".join(missing))
return {
"web": {
"client_id": client_id,
"client_secret": client_secret,
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"redirect_uris": [redirect_uri],
}
}
def build_flow(state=None):
flow = Flow.from_client_config(_client_config(), scopes=SCOPES, state=state)
flow.redirect_uri = os.environ.get("GOOGLE_REDIRECT_URI")
return flow
def get_authorization_url():
flow = build_flow()
authorization_url, state = flow.authorization_url(
access_type="offline",
prompt="consent",
include_granted_scopes="true",
)
return authorization_url, state # importante retornar state
def save_credentials(credentials):
if not credentials.refresh_token:
raise GoogleOAuthError(
"Refresh token nao recebido. Revogue o acesso e autorize novamente."
)
token_path = get_token_path()
token_path.write_text(credentials.to_json(), encoding="utf-8")
def load_credentials():
token_path = get_token_path()
if not token_path.exists():
return None
try:
payload = json.loads(token_path.read_text(encoding="utf-8"))
credentials = Credentials.from_authorized_user_info(payload, SCOPES)
except Exception:
return None
if credentials.expired and credentials.refresh_token:
try:
credentials.refresh(Request())
save_credentials(credentials)
except Exception:
return None
if not credentials.valid:
return None
return credentials
def get_sheets_service():
credentials = load_credentials()
if credentials is None:
raise GoogleAuthRequiredError(
"Google Sheets nao autorizado. Acesse /auth/google primeiro."
)
return build("sheets", "v4", credentials=credentials, cache_discovery=False)
def append_feedback_to_sheet(feedback_data):
spreadsheet_id = os.environ.get("GOOGLE_SPREADSHEET_ID", "").strip()
if not spreadsheet_id:
raise GoogleOAuthError("GOOGLE_SPREADSHEET_ID nao configurado.")
service = get_sheets_service()
fields = [
"timestamp",
"search_id",
"query",
"rank",
"product_id",
"product_name",
"categoria_inferida",
"categoria_produto",
"rating",
"is_helpful",
"feedback",
"motivo",
"score_final",
"score_semantico",
"bonus_lexical",
"penalidade_feedback",
"user_message",
"note",
]
row = [[str(feedback_data.get(field, "") or "") for field in fields]]
try:
return service.spreadsheets().values().append(
spreadsheetId=spreadsheet_id,
range="Feedback!A1:R1",
valueInputOption="USER_ENTERED",
insertDataOption="INSERT_ROWS",
body={"values": row},
).execute()
except Exception as e:
raise GoogleOAuthError(f"Erro ao enviar para Google Sheets: {e}")