From 27370df93a336114ade36ba702d6abd5c4764f13 Mon Sep 17 00:00:00 2001 From: Will Miao <13051207myq@gmail.com> Date: Mon, 13 Oct 2025 19:27:56 +0800 Subject: [PATCH] feat(download): add support to download models from civarchive, fixes #381 --- py/services/download_manager.py | 9 ++------- static/js/api/baseModelApi.js | 15 ++++++++++---- static/js/managers/DownloadManager.js | 28 +++++++++++++++++++-------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/py/services/download_manager.py b/py/services/download_manager.py index bcff61ad..d15642b7 100644 --- a/py/services/download_manager.py +++ b/py/services/download_manager.py @@ -212,13 +212,8 @@ class DownloadManager: # Check embedding scanner if await embedding_scanner.check_model_version_exists(model_version_id): return {'success': False, 'error': 'Model version already exists in embedding library'} - - # Get metadata provider based on source parameter - if source == 'civarchive': - from .metadata_service import get_metadata_provider - metadata_provider = await get_metadata_provider('civarchive') - else: - metadata_provider = await get_default_metadata_provider() + + metadata_provider = await get_default_metadata_provider() # Get version info based on the provided identifier version_info = await metadata_provider.get_model_version(model_id, model_version_id) diff --git a/static/js/api/baseModelApi.js b/static/js/api/baseModelApi.js index 2d24efe4..315a0895 100644 --- a/static/js/api/baseModelApi.js +++ b/static/js/api/baseModelApi.js @@ -569,9 +569,15 @@ export class BaseModelApiClient { } } - async fetchCivitaiVersions(modelId) { + async fetchCivitaiVersions(modelId, source = null) { try { - const response = await fetch(`${this.apiConfig.endpoints.civitaiVersions}/${modelId}`); + let requestUrl = `${this.apiConfig.endpoints.civitaiVersions}/${modelId}`; + if (source) { + const params = new URLSearchParams({ source }); + requestUrl = `${requestUrl}?${params.toString()}`; + } + + const response = await fetch(requestUrl); if (!response.ok) { const errorData = await response.json().catch(() => ({})); if (errorData && errorData.error && errorData.error.includes('Model type mismatch')) { @@ -639,7 +645,7 @@ export class BaseModelApiClient { } } - async downloadModel(modelId, versionId, modelRoot, relativePath, useDefaultPaths = false, downloadId) { + async downloadModel(modelId, versionId, modelRoot, relativePath, useDefaultPaths = false, downloadId, source = null) { try { const response = await fetch(DOWNLOAD_ENDPOINTS.download, { method: 'POST', @@ -650,7 +656,8 @@ export class BaseModelApiClient { model_root: modelRoot, relative_path: relativePath, use_default_paths: useDefaultPaths, - download_id: downloadId + download_id: downloadId, + ...(source ? { source } : {}) }) }); diff --git a/static/js/managers/DownloadManager.js b/static/js/managers/DownloadManager.js index 091c72d1..bfd96906 100644 --- a/static/js/managers/DownloadManager.js +++ b/static/js/managers/DownloadManager.js @@ -14,6 +14,7 @@ export class DownloadManager { this.modelInfo = null; this.modelVersionId = null; this.modelId = null; + this.source = null; this.initialized = false; this.selectedFolder = ''; @@ -126,6 +127,7 @@ export class DownloadManager { this.modelInfo = null; this.modelId = null; this.modelVersionId = null; + this.source = null; this.selectedFolder = ''; @@ -150,7 +152,7 @@ export class DownloadManager { throw new Error(translate('modals.download.errors.invalidUrl')); } - this.versions = await this.apiClient.fetchCivitaiVersions(this.modelId); + this.versions = await this.apiClient.fetchCivitaiVersions(this.modelId, this.source); if (!this.versions.length) { throw new Error(translate('modals.download.errors.noVersions')); @@ -170,13 +172,22 @@ export class DownloadManager { } extractModelId(url) { - const modelMatch = url.match(/civitai\.com\/models\/(\d+)/); - const versionMatch = url.match(/modelVersionId=(\d+)/); - - if (modelMatch) { - this.modelVersionId = versionMatch ? versionMatch[1] : null; - return modelMatch[1]; + const versionMatch = url.match(/modelVersionId=(\d+)/i); + this.modelVersionId = versionMatch ? versionMatch[1] : null; + + const civarchiveMatch = url.match(/https?:\/\/(?:www\.)?(?:civitaiarchive|civarchive)\.com\/models\/(\d+)/i); + if (civarchiveMatch) { + this.source = 'civarchive'; + return civarchiveMatch[1]; } + + const civitaiMatch = url.match(/https?:\/\/(?:www\.)?civitai\.com\/models\/(\d+)/i); + if (civitaiMatch) { + this.source = null; + return civitaiMatch[1]; + } + + this.source = null; return null; } @@ -484,7 +495,8 @@ export class DownloadManager { modelRoot, targetFolder, useDefaultPaths, - downloadId + downloadId, + this.source ); showToast('toast.loras.downloadCompleted', {}, 'success');