import json import os import sys import time from google.oauth2.credentials import Credentials from googleapiclient.discovery import build TOKEN_FILE = os.path.expanduser("~/.hermes/google_token.json") with open(TOKEN_FILE) as f: token_data = json.load(f) creds = Credentials.from_authorized_user_info(token_data) service = build("drive", "v3", credentials=creds) TARGET_NAMES = [ "Case Study-Metro 4", "MPP28_Intro_Phan lop va nhom_Gui hoc vien", "[S] HCMC_Can Doi Ngan Sach Dia Phuong 2025" ] print("=== BẮT ĐẦU DỌN DẸP FILE NHÂN BẢN TRÊN GOOGLE DRIVE ===", flush=True) for target_name in TARGET_NAMES: print(f"\n--- Đang quét: {target_name} ---", flush=True) all_files = [] page_token = None while True: try: res = service.files().list( q=f"name = \"{target_name}\" and trashed = false", fields="nextPageToken, files(id, name, createdTime)", pageSize=1000, pageToken=page_token ).execute() files = res.get("files", []) all_files.extend(files) page_token = res.get("nextPageToken") print(f" Đã quét được {len(all_files)} files...", flush=True) if not page_token: break except Exception as e: print(f" Lỗi khi quét: {e}", flush=True) time.sleep(2) break print(f"Tổng số file tìm thấy cho \"{target_name}\": {len(all_files)}", flush=True) if len(all_files) <= 1: print(" Không có file nhân bản nào cần xoá.", flush=True) continue all_files.sort(key=lambda x: x.get("createdTime", "")) original = all_files[0] duplicates = all_files[1:] orig_id = original.get("id") orig_time = original.get("createdTime") print(f" ✅ GIỮ LẠI BẢN GỐC: ID={orig_id} (Created: {orig_time})", flush=True) print(f" 🗑️ CHUẨN BỊ XOÁ {len(duplicates)} BẢN SAO...", flush=True) batch_size = 100 trashed_counter = [0] def make_callback(counter): def cb(request_id, response, exception): if exception is None: counter[0] += 1 return cb cb_func = make_callback(trashed_counter) for i in range(0, len(duplicates), batch_size): chunk = duplicates[i:i + batch_size] batch = service.new_batch_http_request(callback=cb_func) for f in chunk: batch.add(service.files().update(fileId=f["id"], body={"trashed": True})) retries = 3 while retries > 0: try: batch.execute() break except Exception as e: print(f" Lỗi batch: {e}, đang thử lại...", flush=True) time.sleep(2) retries -= 1 if (i + batch_size) % 1000 == 0 or (i + len(chunk)) == len(duplicates): print(f" -> Đã chuyển vào thùng rác: {trashed_counter[0]}/{len(duplicates)} files", flush=True) print(f"✅ Hoàn thành mục \"{target_name}\"! Đã xoá {trashed_counter[0]} bản sao.", flush=True) print("\n🎉🎉🎉 TOÀN BỘ QUÁ TRÌNH DỌN DẸP ĐÃ HOÀN TẤT! 🎉🎉🎉", flush=True)