ktfb / google_utils.py
geopromini's picture
Upload 7 files
94c1611 verified
import os
import pickle
import base64
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload, MediaIoBaseDownload
import io
import pandas as pd
import google.generativeai as genai
# --- CẤU HÌNH ---
SCOPES = ['https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/spreadsheets']
async def get_drive_credentials_no_chat_id():
"""
Lấy credentials từ biến môi trường PICKLE_TOKEN_B64 (đã mã hóa Base64).
Không cần file vật lý, không cần chat_id để báo lỗi.
"""
creds = None
# 1. Lấy chuỗi Base64 từ Secret
base64_pickle = os.getenv("PICKLE_TOKEN_B64")
if base64_pickle:
try:
# 2. Giải mã Base64 -> Binary -> Object
pickle_data = base64.b64decode(base64_pickle)
creds = pickle.loads(pickle_data)
print("✅ Đã load Credentials từ Secret thành công.")
except Exception as e:
print(f"❌ Lỗi giải mã Pickle: {e}")
return None
else:
print("❌ Lỗi: Chưa cấu hình Secret 'PICKLE_TOKEN_B64' trên Hugging Face.")
return None
# 3. Kiểm tra và Refresh Token nếu hết hạn (Quan trọng)
if creds and creds.expired and creds.refresh_token:
try:
print("🔄 Token hết hạn, đang refresh...")
creds.refresh(Request())
# Lưu ý: Trên môi trường Docker stateless, ta refresh để dùng tạm,
# không cần lưu lại file vì lần sau khởi động lại nó sẽ load từ Secret gốc.
except Exception as e:
print(f"❌ Không thể refresh token: {e}")
return None
return creds
# --- CÁC HÀM XỬ LÝ DRIVE & GEMINI (GIỮ NGUYÊN LOGIC) ---
async def download_file_from_drive(drive_service, file_id, save_path):
try:
if os.path.exists(save_path):
os.remove(save_path)
request = drive_service.files().get_media(fileId=file_id)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while not done:
status, done = downloader.next_chunk()
with open(save_path, 'wb') as f:
f.write(fh.getvalue())
print(f"📥 Đã tải file {file_id} về {save_path}")
except Exception as e:
print(f"❌ Lỗi tải file Drive: {e}")
async def upload_file_to_drive(drive_service, local_path, file_id):
try:
media = MediaFileUpload(local_path, mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
drive_service.files().update(fileId=file_id, media_body=media).execute()
print(f"📤 Đã update file lên Drive ID: {file_id}")
except Exception as e:
print(f"❌ Lỗi upload file Drive: {e}")
# Load key Gemini từ file Excel (sau khi đã tải về)
async def load_gemini_keys(excel_path):
global GEMINI_KEYS
try:
# Đọc sheet APIKey
df = pd.read_excel(excel_path, sheet_name='APIKey', header=None)
# Giả sử key nằm ở cột A, bỏ dòng tiêu đề
GEMINI_KEYS = df.iloc[1:, 0].dropna().astype(str).tolist()
print(f"🔑 Đã load {len(GEMINI_KEYS)} Gemini Keys.")
except Exception as e:
print(f"❌ Lỗi đọc Gemini Keys từ Excel: {e}")
GEMINI_KEYS = []
async def generate_content_with_gemini(product_desc):
# (Giữ nguyên phần import và check key)
import random
if not GEMINI_KEYS: return product_desc
prompt = f"Viết caption Facebook Reels hấp dẫn cho: {product_desc}"
for _ in range(3):
key = random.choice(GEMINI_KEYS)
genai.configure(api_key=key)
try:
# SỬA LẠI TÊN MODEL CHO ĐÚNG VỚI APP.PY CỦA BẠN
model = genai.GenerativeModel('models/gemini-2.5-flash')
response = await model.generate_content_async(prompt)
return response.text.strip()
except Exception as e:
print(f"Lỗi Gemini (Key ...{key[-4:]}): {e}")
continue
return product_desc
async def download_video_by_id(drive_service, file_id, save_path):
# Tái sử dụng hàm download
await download_file_from_drive(drive_service, file_id, save_path)