Spaces:
Sleeping
Sleeping
Commit
·
cc45ea6
1
Parent(s):
7eb9383
Project Uploaded
Browse files- api_server.py +9 -6
api_server.py
CHANGED
|
@@ -12,6 +12,7 @@ from dotenv import load_dotenv
|
|
| 12 |
load_dotenv()
|
| 13 |
|
| 14 |
def decode_base64_with_padding(b64_string: str) -> bytes:
|
|
|
|
| 15 |
missing_padding = len(b64_string) % 4
|
| 16 |
if missing_padding:
|
| 17 |
b64_string += '=' * (4 - missing_padding)
|
|
@@ -21,19 +22,20 @@ def decode_base64_with_padding(b64_string: str) -> bytes:
|
|
| 21 |
print(f"Error decoding base64 string after padding: {e}")
|
| 22 |
return b""
|
| 23 |
|
|
|
|
| 24 |
# Define a writable directory for ALL runtime files
|
| 25 |
WRITABLE_DIR = "/tmp"
|
| 26 |
COOKIES_PATH = os.path.join(WRITABLE_DIR, "facebook_cookies.pkl")
|
| 27 |
SERVICE_ACCOUNT_FILE = os.path.join(WRITABLE_DIR, "service_account.json")
|
| 28 |
|
| 29 |
-
# Decode secrets at startup into the /tmp directory
|
| 30 |
if 'FB_COOKIES_B64' in os.environ:
|
| 31 |
decoded_cookies = decode_base64_with_padding(os.environ['FB_COOKIES_B64'])
|
| 32 |
if decoded_cookies:
|
| 33 |
with open(COOKIES_PATH, 'wb') as f:
|
| 34 |
f.write(decoded_cookies)
|
| 35 |
|
| 36 |
-
#
|
| 37 |
if 'SERVICE_ACCOUNT_B64' in os.environ:
|
| 38 |
decoded_service_account = decode_base64_with_padding(os.environ['SERVICE_ACCOUNT_B64'])
|
| 39 |
if decoded_service_account:
|
|
@@ -45,6 +47,7 @@ FINAL5_PATH = os.environ.get("FINAL5_PATH", "final5.py")
|
|
| 45 |
PYTHON_BIN = os.environ.get("PYTHON_BIN", "python")
|
| 46 |
SENDER_EMAIL = os.environ.get("SENDER_EMAIL", "smahato@hillsidemedicalgroup.com")
|
| 47 |
|
|
|
|
| 48 |
SCRAPE_OUTDIR = os.path.join(WRITABLE_DIR, "scraped")
|
| 49 |
ANALYSIS_OUTDIR = os.path.join(WRITABLE_DIR, "analysis")
|
| 50 |
|
|
@@ -58,7 +61,7 @@ GMAIL_SCOPES = [ "https://www.googleapis.com/auth/gmail.send" ]
|
|
| 58 |
os.makedirs(SCRAPE_OUTDIR, exist_ok=True)
|
| 59 |
os.makedirs(ANALYSIS_OUTDIR, exist_ok=True)
|
| 60 |
|
| 61 |
-
#
|
| 62 |
def build_gmail_service():
|
| 63 |
if not os.path.exists(SERVICE_ACCOUNT_FILE):
|
| 64 |
log("Service account file not found, Gmail unavailable.", "error", "GMAIL")
|
|
@@ -73,13 +76,13 @@ def build_gmail_service():
|
|
| 73 |
return service
|
| 74 |
except Exception as e:
|
| 75 |
log(f"Failed to build Gmail service: {e}", "error", "GMAIL")
|
| 76 |
-
log("CRITICAL: Ensure your service account has Domain-Wide Delegation enabled
|
| 77 |
return None
|
| 78 |
|
| 79 |
gmail_service = build_gmail_service()
|
|
|
|
|
|
|
| 80 |
|
| 81 |
-
# The rest of api_server.py remains unchanged...
|
| 82 |
-
# (Full code omitted for brevity, just replace the top section and the build_gmail_service function)
|
| 83 |
@dataclass
|
| 84 |
class GroupRun:
|
| 85 |
link: str
|
|
|
|
| 12 |
load_dotenv()
|
| 13 |
|
| 14 |
def decode_base64_with_padding(b64_string: str) -> bytes:
|
| 15 |
+
"""Decodes a Base64 string, adding missing padding if necessary."""
|
| 16 |
missing_padding = len(b64_string) % 4
|
| 17 |
if missing_padding:
|
| 18 |
b64_string += '=' * (4 - missing_padding)
|
|
|
|
| 22 |
print(f"Error decoding base64 string after padding: {e}")
|
| 23 |
return b""
|
| 24 |
|
| 25 |
+
# --- START: CRITICAL SECTION ---
|
| 26 |
# Define a writable directory for ALL runtime files
|
| 27 |
WRITABLE_DIR = "/tmp"
|
| 28 |
COOKIES_PATH = os.path.join(WRITABLE_DIR, "facebook_cookies.pkl")
|
| 29 |
SERVICE_ACCOUNT_FILE = os.path.join(WRITABLE_DIR, "service_account.json")
|
| 30 |
|
| 31 |
+
# Decode ALL necessary secrets at startup into the /tmp directory
|
| 32 |
if 'FB_COOKIES_B64' in os.environ:
|
| 33 |
decoded_cookies = decode_base64_with_padding(os.environ['FB_COOKIES_B64'])
|
| 34 |
if decoded_cookies:
|
| 35 |
with open(COOKIES_PATH, 'wb') as f:
|
| 36 |
f.write(decoded_cookies)
|
| 37 |
|
| 38 |
+
# This is the missing piece: decode the Service Account secret
|
| 39 |
if 'SERVICE_ACCOUNT_B64' in os.environ:
|
| 40 |
decoded_service_account = decode_base64_with_padding(os.environ['SERVICE_ACCOUNT_B64'])
|
| 41 |
if decoded_service_account:
|
|
|
|
| 47 |
PYTHON_BIN = os.environ.get("PYTHON_BIN", "python")
|
| 48 |
SENDER_EMAIL = os.environ.get("SENDER_EMAIL", "smahato@hillsidemedicalgroup.com")
|
| 49 |
|
| 50 |
+
# Point the output directories to the writable /tmp directory
|
| 51 |
SCRAPE_OUTDIR = os.path.join(WRITABLE_DIR, "scraped")
|
| 52 |
ANALYSIS_OUTDIR = os.path.join(WRITABLE_DIR, "analysis")
|
| 53 |
|
|
|
|
| 61 |
os.makedirs(SCRAPE_OUTDIR, exist_ok=True)
|
| 62 |
os.makedirs(ANALYSIS_OUTDIR, exist_ok=True)
|
| 63 |
|
| 64 |
+
# Use non-interactive, service-account based authentication
|
| 65 |
def build_gmail_service():
|
| 66 |
if not os.path.exists(SERVICE_ACCOUNT_FILE):
|
| 67 |
log("Service account file not found, Gmail unavailable.", "error", "GMAIL")
|
|
|
|
| 76 |
return service
|
| 77 |
except Exception as e:
|
| 78 |
log(f"Failed to build Gmail service: {e}", "error", "GMAIL")
|
| 79 |
+
log(f"CRITICAL: Ensure your service account has Domain-Wide Delegation enabled for the user {SENDER_EMAIL}", "error", "GMAIL")
|
| 80 |
return None
|
| 81 |
|
| 82 |
gmail_service = build_gmail_service()
|
| 83 |
+
# --- END: CRITICAL SECTION ---
|
| 84 |
+
|
| 85 |
|
|
|
|
|
|
|
| 86 |
@dataclass
|
| 87 |
class GroupRun:
|
| 88 |
link: str
|