Docs Client
GoogleDocsService pulls the key from Secret Manager and builds a read-only Docs client.
import os, json
import google.auth
from google.cloud import secretmanager
from google.oauth2 import service_account
from googleapiclient.discovery import build
class GoogleDocsService:
def __init__(self):
self.credentials, self.project_id = google.auth.default()
self.scopes = ['https://www.googleapis.com/auth/documents.readonly']
self._docs = None
def get_secret(self, secret_id: str) -> dict:
client = secretmanager.SecretManagerServiceClient()
name = f"projects/{self.project_id}/secrets/{secret_id}/versions/latest"
data = client.access_secret_version(request={"name": name}).payload.data
return json.loads(data.decode("UTF-8"))
@property
def docs(self):
if not self._docs:
info = self.get_secret(os.environ['SERVICE_ACCOUNT_SECRET_ID'])
creds = service_account.Credentials.from_service_account_info(
info, scopes=self.scopes)
self._docs = build('docs', 'v1', credentials=creds)
return self._docs
GoogleDoc takes a URL or ID, fetches the document, and walks its JSON to collect every textRun. Formatting is dropped. Only the words remain.
class GoogleDoc:
def __init__(self, service: GoogleDocsService, file_id_or_uri: str):
self.service = service
self.file_id_or_uri = file_id_or_uri
@property
def id(self) -> str:
if '/d/' in self.file_id_or_uri:
return self.file_id_or_uri.split('/d/')[1].split('/')[0]
return self.file_id_or_uri
@property
def text(self) -> str:
doc = self.service.docs.documents().get(documentId=self.id).execute()
out = ""
for block in doc.get('body', {}).get('content', []):
for elem in block.get('paragraph', {}).get('elements', []):
out += elem.get('textRun', {}).get('content', '')
return out