Upload main.py
Browse files
main.py
CHANGED
@@ -104,9 +104,8 @@ class CivitAICrawler:
|
|
104 |
|
105 |
def encrypt_with_rclone(self, local_path: str):
|
106 |
"""
|
107 |
-
local_path
|
108 |
-
|
109 |
-
- ファイル → rclone copyto を使って暗号化
|
110 |
"""
|
111 |
if not os.path.exists(local_path):
|
112 |
raise FileNotFoundError(f"[ERROR] Local path not found: {local_path}")
|
@@ -147,8 +146,16 @@ class CivitAICrawler:
|
|
147 |
f"[ERROR] {self.config.ENCRYPTED_DIR} not found. Check rclone config."
|
148 |
)
|
149 |
|
150 |
-
# 例: upload_encrypted_files の中の再試行処理
|
151 |
def upload_encrypted_files(self, repo_id: str, base_path_in_repo: str = ""):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
152 |
max_retries = 5
|
153 |
for root, dirs, files in os.walk(self.config.ENCRYPTED_DIR):
|
154 |
for fn in files:
|
@@ -174,30 +181,21 @@ class CivitAICrawler:
|
|
174 |
attempt += 1
|
175 |
error_message = str(e)
|
176 |
|
177 |
-
#
|
178 |
-
# 429によるrate-limit検出追加
|
179 |
-
# ================================
|
180 |
-
# "You have been rate-limited; you can retry this action in 31 minutes."
|
181 |
-
# のようなメッセージから時間を抽出し、その時間+1分だけ待機後、再試行
|
182 |
if "rate-limited" in error_message and "minutes" in error_message:
|
183 |
-
import re
|
184 |
match = re.search(r"in (\d+) minutes?", error_message)
|
185 |
if match:
|
186 |
minutes = int(match.group(1))
|
187 |
-
# +1分して待機
|
188 |
minutes += 1
|
189 |
logger.warning(f"Rate-limited. Waiting {minutes} minutes before retry...")
|
190 |
time.sleep(minutes * 60)
|
191 |
-
attempt -= 1
|
192 |
continue
|
193 |
|
194 |
-
# ================================
|
195 |
-
# すでにある1時間待機処理
|
196 |
-
# ================================
|
197 |
if "you can retry this action in about 1 hour" in error_message:
|
198 |
logger.warning("Encountered 'retry in 1 hour' error. Waiting 1 hour before retrying...")
|
199 |
time.sleep(3600)
|
200 |
-
attempt -= 1
|
201 |
continue
|
202 |
|
203 |
if "over the limit of 100000 files" in error_message:
|
@@ -255,8 +253,7 @@ class CivitAICrawler:
|
|
255 |
def download_model(self, model_versions: list, folder: str):
|
256 |
"""
|
257 |
- 最新バージョンのファイルを「folder」へまとめてダウンロード
|
258 |
-
-
|
259 |
-
(※今回は「まとめて old_versions フォルダに入れずに、1ファイルずつ別のメソッドで対処する」流れに)
|
260 |
"""
|
261 |
latest_version = model_versions[0]
|
262 |
latest_files = latest_version["files"]
|
@@ -295,12 +292,12 @@ class CivitAICrawler:
|
|
295 |
def download_old_version_file_and_upload(self, file_info, parent_folder: str, encrypted_top_name: str):
|
296 |
"""
|
297 |
古いバージョンのファイルを1つダウンロード→暗号化アップロード→削除。
|
298 |
-
|
299 |
"""
|
300 |
file_name = file_info["name"]
|
301 |
download_url = file_info["downloadUrl"]
|
302 |
|
303 |
-
# old_versions
|
304 |
old_versions_folder = os.path.join(parent_folder, "old_versions")
|
305 |
os.makedirs(old_versions_folder, exist_ok=True)
|
306 |
|
@@ -309,7 +306,6 @@ class CivitAICrawler:
|
|
309 |
login_detected_count = 0
|
310 |
while login_detected_count < 5:
|
311 |
try:
|
312 |
-
# old_versionsフォルダへダウンロード
|
313 |
self.download_file(download_url, old_versions_folder, file_name)
|
314 |
except Exception as e:
|
315 |
logger.error(f"Exception while downloading old file {file_name}: {e}")
|
@@ -326,7 +322,7 @@ class CivitAICrawler:
|
|
326 |
break
|
327 |
|
328 |
if login_detected_count >= 5:
|
329 |
-
# 5
|
330 |
dummy_file_name = f"{file_name}.download_failed"
|
331 |
dummy_file_path = os.path.join(old_versions_folder, dummy_file_name)
|
332 |
try:
|
@@ -337,12 +333,12 @@ class CivitAICrawler:
|
|
337 |
logger.error(f"Failed to create dummy file for old version {file_name}: {e}")
|
338 |
return
|
339 |
|
340 |
-
#
|
341 |
try:
|
342 |
-
# 1)
|
343 |
self.encrypt_with_rclone(local_path)
|
344 |
|
345 |
-
# 2)
|
346 |
self.upload_encrypted_files(
|
347 |
repo_id=self.repo_ids["current"],
|
348 |
base_path_in_repo=f"{encrypted_top_name}/old_versions"
|
@@ -352,7 +348,7 @@ class CivitAICrawler:
|
|
352 |
except Exception as e:
|
353 |
logger.error(f"Error uploading old version file {file_name}: {e}")
|
354 |
|
355 |
-
# 3)
|
356 |
if os.path.exists(local_path):
|
357 |
os.remove(local_path)
|
358 |
logger.info(f"Removed local old version file: {local_path}")
|
@@ -402,7 +398,7 @@ class CivitAICrawler:
|
|
402 |
return f"{repo_id}1"
|
403 |
|
404 |
# =============================================================================
|
405 |
-
#
|
406 |
# =============================================================================
|
407 |
def upload_file_raw(
|
408 |
self,
|
@@ -448,26 +444,7 @@ class CivitAICrawler:
|
|
448 |
raise
|
449 |
|
450 |
# =============================================================================
|
451 |
-
#
|
452 |
-
# =============================================================================
|
453 |
-
def upload_file_encrypted(
|
454 |
-
self,
|
455 |
-
file_path: str,
|
456 |
-
repo_id: Optional[str] = None,
|
457 |
-
path_in_repo: Optional[str] = None
|
458 |
-
):
|
459 |
-
if repo_id is None:
|
460 |
-
repo_id = self.repo_ids['current']
|
461 |
-
base_path = path_in_repo or ""
|
462 |
-
|
463 |
-
self.encrypt_with_rclone(file_path)
|
464 |
-
self.upload_encrypted_files(repo_id=repo_id, base_path_in_repo=base_path)
|
465 |
-
|
466 |
-
if os.path.isdir(self.config.ENCRYPTED_DIR):
|
467 |
-
shutil.rmtree(self.config.ENCRYPTED_DIR, ignore_errors=True)
|
468 |
-
|
469 |
-
# =============================================================================
|
470 |
-
# 暗号化してアップロード (フォルダ)
|
471 |
# =============================================================================
|
472 |
def upload_folder_encrypted(
|
473 |
self,
|
@@ -475,12 +452,18 @@ class CivitAICrawler:
|
|
475 |
repo_id: Optional[str] = None,
|
476 |
path_in_repo: Optional[str] = None
|
477 |
) -> str:
|
|
|
|
|
|
|
|
|
478 |
if repo_id is None:
|
479 |
repo_id = self.repo_ids['current']
|
480 |
base_path = path_in_repo or ""
|
481 |
|
|
|
482 |
self.encrypt_with_rclone(folder_path)
|
483 |
|
|
|
484 |
top_levels = [
|
485 |
d for d in os.listdir(self.config.ENCRYPTED_DIR)
|
486 |
if os.path.isdir(os.path.join(self.config.ENCRYPTED_DIR, d))
|
@@ -491,56 +474,35 @@ class CivitAICrawler:
|
|
491 |
logger.warning(f"Multiple top-level folders found after encryption? {top_levels}. Using the first one.")
|
492 |
|
493 |
encrypted_top_name = top_levels[0]
|
494 |
-
|
495 |
self.upload_encrypted_files(repo_id=repo_id, base_path_in_repo=base_path)
|
496 |
|
|
|
497 |
if os.path.isdir(self.config.ENCRYPTED_DIR):
|
498 |
shutil.rmtree(self.config.ENCRYPTED_DIR, ignore_errors=True)
|
499 |
|
500 |
return encrypted_top_name
|
501 |
|
502 |
# =============================================================================
|
503 |
-
#
|
504 |
# =============================================================================
|
505 |
-
def read_model_list(self):
|
506 |
-
"""
|
507 |
-
model_list.log の各行を
|
508 |
-
"123456: https://huggingface.co/...encrypted_folder_name"
|
509 |
-
の形式で読み込み、 { "123456": "https://huggingface.co/..."} の dict を返す
|
510 |
-
"""
|
511 |
-
model_list = {}
|
512 |
-
try:
|
513 |
-
with open(self.config.LIST_FILE, "r", encoding="utf-8") as f:
|
514 |
-
for line in f:
|
515 |
-
line = line.strip()
|
516 |
-
if not line:
|
517 |
-
continue
|
518 |
-
parts = line.split(": ", 1)
|
519 |
-
if len(parts) == 2:
|
520 |
-
stored_id, stored_url = parts
|
521 |
-
model_list[stored_id] = stored_url
|
522 |
-
return model_list
|
523 |
-
except Exception as e:
|
524 |
-
logger.error(f"Failed to read model list: {e}")
|
525 |
-
return {}
|
526 |
-
|
527 |
def process_model(self, model_url: str):
|
528 |
"""
|
529 |
-
|
530 |
-
|
531 |
"""
|
532 |
try:
|
533 |
model_id = model_url.rstrip("/").split("/")[-1]
|
534 |
model_info = self.get_model_info(model_id)
|
|
|
|
|
|
|
535 |
|
536 |
model_versions = model_info.get("modelVersions", [])
|
537 |
if not model_versions:
|
538 |
logger.warning(f"No versions found for model ID {model_id}")
|
539 |
return
|
540 |
|
541 |
-
#
|
542 |
-
# 1) 「古いコード」と同じロジックでフォルダ名を決定
|
543 |
-
# ==================================================================
|
544 |
latest_version = model_versions[0]
|
545 |
model_file = next(
|
546 |
(file for file in latest_version["files"] if file.get('type') == 'Model'),
|
@@ -550,48 +512,37 @@ class CivitAICrawler:
|
|
550 |
latest_filename = model_file['name']
|
551 |
folder = os.path.splitext(latest_filename)[0]
|
552 |
else:
|
|
|
553 |
first_file = latest_version["files"][0]
|
554 |
latest_filename = first_file['name']
|
555 |
folder = os.path.splitext(latest_filename)[0]
|
556 |
logger.warning(f"No 'Model' type file found for model ID {model_id}. Using first file's name.")
|
557 |
|
|
|
558 |
os.makedirs(folder, exist_ok=True)
|
559 |
|
560 |
-
#
|
561 |
-
# 2) 最新バージョンをまとめてダウンロード (model本体)
|
562 |
-
# + 画像ダウンロード + HTML保存 + info.json保存
|
563 |
-
# ==================================================================
|
564 |
self.download_model(model_versions, folder)
|
565 |
self.download_images(model_versions, folder)
|
566 |
-
self.save_html_content(
|
567 |
self.save_model_info(model_info, folder)
|
568 |
|
569 |
-
#
|
570 |
-
# 3) フォルダ全体(最新バージョン + images + html + info.json)を
|
571 |
-
# まとめて 1 回だけ暗号化→アップロード
|
572 |
-
# ==================================================================
|
573 |
encrypted_top_name = self.upload_folder_encrypted(folder)
|
574 |
logger.info(f"[MAIN] Uploaded latest version folder => {encrypted_top_name}")
|
575 |
|
576 |
-
#
|
577 |
shutil.rmtree(folder, ignore_errors=True)
|
578 |
|
579 |
-
#
|
580 |
-
# 4) 古いバージョンのファイルを 1つずつDL → 即アップロード
|
581 |
-
# ==================================================================
|
582 |
if len(model_versions) > 1:
|
583 |
-
#
|
584 |
for version in model_versions[1:]:
|
585 |
for file_info in version["files"]:
|
586 |
-
#
|
587 |
-
# download_old_version_file_and_upload(file_info, parent_folder, encrypted_top_name)
|
588 |
self.download_old_version_file_and_upload(file_info, folder, encrypted_top_name)
|
589 |
-
# ↑ parent_folder=folder に old_versionsフォルダを作り
|
590 |
-
# そこへダウンロードしてから暗号化アップロード
|
591 |
|
592 |
-
#
|
593 |
-
# 5) model_list.log への登録やその他の処理
|
594 |
-
# ==================================================================
|
595 |
modelpage_name = model_info.get("name", f"Model_{model_id}")
|
596 |
model_hf_url = f"https://huggingface.co/{self.repo_ids['current']}/tree/main/{encrypted_top_name}"
|
597 |
|
@@ -601,13 +552,17 @@ class CivitAICrawler:
|
|
601 |
except Exception as e:
|
602 |
logger.error(f"Unexpected error in process_model ({model_url}): {e}")
|
603 |
|
|
|
|
|
|
|
604 |
async def crawl(self):
|
605 |
"""モデルを定期的にチェックし、更新を行う。"""
|
606 |
while True:
|
607 |
try:
|
|
|
608 |
login(token=self.config.HUGGINGFACE_API_KEY, add_to_git_credential=True)
|
609 |
|
610 |
-
# model_list.log & civitai_backup.log
|
611 |
model_list_path = hf_hub_download(repo_id=self.repo_ids['model_list'], filename=self.config.LIST_FILE)
|
612 |
shutil.copyfile(model_list_path, f"./{self.config.LIST_FILE}")
|
613 |
|
@@ -670,7 +625,7 @@ class CivitAICrawler:
|
|
670 |
f.write(f"{self.repo_ids['current']}\n")
|
671 |
logger.info(f"Updated log file with new model ID: {model_id}")
|
672 |
|
673 |
-
# ログとmodel_list.logをアップロード
|
674 |
self.upload_file_raw(
|
675 |
file_path=self.config.LOG_FILE,
|
676 |
repo_id=self.repo_ids["log"],
|
|
|
104 |
|
105 |
def encrypt_with_rclone(self, local_path: str):
|
106 |
"""
|
107 |
+
local_path がフォルダかファイルかで処理を分け、暗号化(rclone copy or copyto)を行う。
|
108 |
+
暗号化先は self.config.ENCRYPTED_DIR に生成される。
|
|
|
109 |
"""
|
110 |
if not os.path.exists(local_path):
|
111 |
raise FileNotFoundError(f"[ERROR] Local path not found: {local_path}")
|
|
|
146 |
f"[ERROR] {self.config.ENCRYPTED_DIR} not found. Check rclone config."
|
147 |
)
|
148 |
|
|
|
149 |
def upload_encrypted_files(self, repo_id: str, base_path_in_repo: str = ""):
|
150 |
+
"""
|
151 |
+
暗号化後の self.config.ENCRYPTED_DIR を走査し、
|
152 |
+
すべてのファイルを1つずつアップロードする。
|
153 |
+
|
154 |
+
(「最新バージョンのフォルダをまとめてアップロードするとき」は、1回だけこのメソッドを呼び出して
|
155 |
+
フォルダ分のファイルを一括アップロード。
|
156 |
+
old_versions でも 1ファイル暗号化後にこのメソッドを呼び出しているため、
|
157 |
+
そこだけは引き続き個別ファイルのアップロードとなる。)
|
158 |
+
"""
|
159 |
max_retries = 5
|
160 |
for root, dirs, files in os.walk(self.config.ENCRYPTED_DIR):
|
161 |
for fn in files:
|
|
|
181 |
attempt += 1
|
182 |
error_message = str(e)
|
183 |
|
184 |
+
# 429制限等のリトライロジック
|
|
|
|
|
|
|
|
|
185 |
if "rate-limited" in error_message and "minutes" in error_message:
|
|
|
186 |
match = re.search(r"in (\d+) minutes?", error_message)
|
187 |
if match:
|
188 |
minutes = int(match.group(1))
|
|
|
189 |
minutes += 1
|
190 |
logger.warning(f"Rate-limited. Waiting {minutes} minutes before retry...")
|
191 |
time.sleep(minutes * 60)
|
192 |
+
attempt -= 1
|
193 |
continue
|
194 |
|
|
|
|
|
|
|
195 |
if "you can retry this action in about 1 hour" in error_message:
|
196 |
logger.warning("Encountered 'retry in 1 hour' error. Waiting 1 hour before retrying...")
|
197 |
time.sleep(3600)
|
198 |
+
attempt -= 1
|
199 |
continue
|
200 |
|
201 |
if "over the limit of 100000 files" in error_message:
|
|
|
253 |
def download_model(self, model_versions: list, folder: str):
|
254 |
"""
|
255 |
- 最新バージョンのファイルを「folder」へまとめてダウンロード
|
256 |
+
- ここでは古いバージョンはダウンロードしない(後ほど old_versions にて個別にダウンロード)
|
|
|
257 |
"""
|
258 |
latest_version = model_versions[0]
|
259 |
latest_files = latest_version["files"]
|
|
|
292 |
def download_old_version_file_and_upload(self, file_info, parent_folder: str, encrypted_top_name: str):
|
293 |
"""
|
294 |
古いバージョンのファイルを1つダウンロード→暗号化アップロード→削除。
|
295 |
+
old_versions フォルダの中に都度ファイルを落としてアップロード→削除する。
|
296 |
"""
|
297 |
file_name = file_info["name"]
|
298 |
download_url = file_info["downloadUrl"]
|
299 |
|
300 |
+
# old_versions フォルダ作成
|
301 |
old_versions_folder = os.path.join(parent_folder, "old_versions")
|
302 |
os.makedirs(old_versions_folder, exist_ok=True)
|
303 |
|
|
|
306 |
login_detected_count = 0
|
307 |
while login_detected_count < 5:
|
308 |
try:
|
|
|
309 |
self.download_file(download_url, old_versions_folder, file_name)
|
310 |
except Exception as e:
|
311 |
logger.error(f"Exception while downloading old file {file_name}: {e}")
|
|
|
322 |
break
|
323 |
|
324 |
if login_detected_count >= 5:
|
325 |
+
# 5回失敗した場合はダミーファイル化
|
326 |
dummy_file_name = f"{file_name}.download_failed"
|
327 |
dummy_file_path = os.path.join(old_versions_folder, dummy_file_name)
|
328 |
try:
|
|
|
333 |
logger.error(f"Failed to create dummy file for old version {file_name}: {e}")
|
334 |
return
|
335 |
|
336 |
+
# ここから暗号化→アップロード→削除 (1ファイルずつ処理を繰り返す)
|
337 |
try:
|
338 |
+
# 1) 単ファイルを暗号化
|
339 |
self.encrypt_with_rclone(local_path)
|
340 |
|
341 |
+
# 2) アップロード
|
342 |
self.upload_encrypted_files(
|
343 |
repo_id=self.repo_ids["current"],
|
344 |
base_path_in_repo=f"{encrypted_top_name}/old_versions"
|
|
|
348 |
except Exception as e:
|
349 |
logger.error(f"Error uploading old version file {file_name}: {e}")
|
350 |
|
351 |
+
# 3) ローカルの平文ファイルを削除
|
352 |
if os.path.exists(local_path):
|
353 |
os.remove(local_path)
|
354 |
logger.info(f"Removed local old version file: {local_path}")
|
|
|
398 |
return f"{repo_id}1"
|
399 |
|
400 |
# =============================================================================
|
401 |
+
# ログ類のアップロード(生ファイル)
|
402 |
# =============================================================================
|
403 |
def upload_file_raw(
|
404 |
self,
|
|
|
444 |
raise
|
445 |
|
446 |
# =============================================================================
|
447 |
+
# フォルダ全体をまとめて暗号化してアップロード
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
448 |
# =============================================================================
|
449 |
def upload_folder_encrypted(
|
450 |
self,
|
|
|
452 |
repo_id: Optional[str] = None,
|
453 |
path_in_repo: Optional[str] = None
|
454 |
) -> str:
|
455 |
+
"""
|
456 |
+
指定フォルダを暗号化し、暗号化後のファイルを一括アップロードする。
|
457 |
+
戻り値: 暗号化されたトップレベルフォルダ名
|
458 |
+
"""
|
459 |
if repo_id is None:
|
460 |
repo_id = self.repo_ids['current']
|
461 |
base_path = path_in_repo or ""
|
462 |
|
463 |
+
# 1) 全体を一度に暗号化
|
464 |
self.encrypt_with_rclone(folder_path)
|
465 |
|
466 |
+
# 2) 暗号化後フォルダ名を取得し、一括アップロード
|
467 |
top_levels = [
|
468 |
d for d in os.listdir(self.config.ENCRYPTED_DIR)
|
469 |
if os.path.isdir(os.path.join(self.config.ENCRYPTED_DIR, d))
|
|
|
474 |
logger.warning(f"Multiple top-level folders found after encryption? {top_levels}. Using the first one.")
|
475 |
|
476 |
encrypted_top_name = top_levels[0]
|
|
|
477 |
self.upload_encrypted_files(repo_id=repo_id, base_path_in_repo=base_path)
|
478 |
|
479 |
+
# 3) 暗号化用ディレクトリをクリーンアップ
|
480 |
if os.path.isdir(self.config.ENCRYPTED_DIR):
|
481 |
shutil.rmtree(self.config.ENCRYPTED_DIR, ignore_errors=True)
|
482 |
|
483 |
return encrypted_top_name
|
484 |
|
485 |
# =============================================================================
|
486 |
+
# メイン処理:最新バージョンは「フォルダ一括」アップロード、old_versions は1ファイルずつ
|
487 |
# =============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
488 |
def process_model(self, model_url: str):
|
489 |
"""
|
490 |
+
1) 最新バージョン → フォルダにまとめてダウンロードし、1回だけ暗号化&アップロード
|
491 |
+
2) old_versions → 1ファイルずつダウンロード→暗号化アップロード→削除
|
492 |
"""
|
493 |
try:
|
494 |
model_id = model_url.rstrip("/").split("/")[-1]
|
495 |
model_info = self.get_model_info(model_id)
|
496 |
+
if not model_info:
|
497 |
+
logger.warning(f"Cannot get model info: {model_id}")
|
498 |
+
return
|
499 |
|
500 |
model_versions = model_info.get("modelVersions", [])
|
501 |
if not model_versions:
|
502 |
logger.warning(f"No versions found for model ID {model_id}")
|
503 |
return
|
504 |
|
505 |
+
# === フォルダ名決定(最新バージョンのファイル名から取得) ===
|
|
|
|
|
506 |
latest_version = model_versions[0]
|
507 |
model_file = next(
|
508 |
(file for file in latest_version["files"] if file.get('type') == 'Model'),
|
|
|
512 |
latest_filename = model_file['name']
|
513 |
folder = os.path.splitext(latest_filename)[0]
|
514 |
else:
|
515 |
+
# type='Model' がなければ最初のファイルを基準に
|
516 |
first_file = latest_version["files"][0]
|
517 |
latest_filename = first_file['name']
|
518 |
folder = os.path.splitext(latest_filename)[0]
|
519 |
logger.warning(f"No 'Model' type file found for model ID {model_id}. Using first file's name.")
|
520 |
|
521 |
+
# ダウンロード先フォルダ作成
|
522 |
os.makedirs(folder, exist_ok=True)
|
523 |
|
524 |
+
# === 最新バージョンをまとめてダウンロード ===
|
|
|
|
|
|
|
525 |
self.download_model(model_versions, folder)
|
526 |
self.download_images(model_versions, folder)
|
527 |
+
self.save_html_content(self.config.URLS["modelPage"] + str(model_id), folder)
|
528 |
self.save_model_info(model_info, folder)
|
529 |
|
530 |
+
# === フォルダごと暗号化→アップロード ===
|
|
|
|
|
|
|
531 |
encrypted_top_name = self.upload_folder_encrypted(folder)
|
532 |
logger.info(f"[MAIN] Uploaded latest version folder => {encrypted_top_name}")
|
533 |
|
534 |
+
# ローカルのフォルダ削除
|
535 |
shutil.rmtree(folder, ignore_errors=True)
|
536 |
|
537 |
+
# === 古いバージョンは1つずつアップロード ===
|
|
|
|
|
538 |
if len(model_versions) > 1:
|
539 |
+
# 旧バージョンだけ個別ファイル処理
|
540 |
for version in model_versions[1:]:
|
541 |
for file_info in version["files"]:
|
542 |
+
# old_versions フォルダに落としてアップロード
|
|
|
543 |
self.download_old_version_file_and_upload(file_info, folder, encrypted_top_name)
|
|
|
|
|
544 |
|
545 |
+
# === model_list.log への追加など後処理 ===
|
|
|
|
|
546 |
modelpage_name = model_info.get("name", f"Model_{model_id}")
|
547 |
model_hf_url = f"https://huggingface.co/{self.repo_ids['current']}/tree/main/{encrypted_top_name}"
|
548 |
|
|
|
552 |
except Exception as e:
|
553 |
logger.error(f"Unexpected error in process_model ({model_url}): {e}")
|
554 |
|
555 |
+
# =============================================================================
|
556 |
+
# 定期巡回して新しいモデルがあれば処理する
|
557 |
+
# =============================================================================
|
558 |
async def crawl(self):
|
559 |
"""モデルを定期的にチェックし、更新を行う。"""
|
560 |
while True:
|
561 |
try:
|
562 |
+
# HuggingFaceログイン
|
563 |
login(token=self.config.HUGGINGFACE_API_KEY, add_to_git_credential=True)
|
564 |
|
565 |
+
# 既存の model_list.log & civitai_backup.log を取得してローカルへ
|
566 |
model_list_path = hf_hub_download(repo_id=self.repo_ids['model_list'], filename=self.config.LIST_FILE)
|
567 |
shutil.copyfile(model_list_path, f"./{self.config.LIST_FILE}")
|
568 |
|
|
|
625 |
f.write(f"{self.repo_ids['current']}\n")
|
626 |
logger.info(f"Updated log file with new model ID: {model_id}")
|
627 |
|
628 |
+
# ログとmodel_list.logをアップロード (暗号化しない)
|
629 |
self.upload_file_raw(
|
630 |
file_path=self.config.LOG_FILE,
|
631 |
repo_id=self.repo_ids["log"],
|