Symbiomatrix commited on
Commit
076fb4a
·
verified ·
1 Parent(s): 9edba37

Support image upload.

Browse files
Files changed (1) hide show
  1. app.py +115 -33
app.py CHANGED
@@ -52,10 +52,55 @@ def download_file(url, file_path, folder, api_key=None):
52
  except Exception as e:
53
  raise gr.Error(f"Error downloading file: {str(e)}")
54
 
55
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  def get_files_by_username(username, api_key=None, nsfw=None, hidden=None):
57
  url = f"https://civitai.com/api/v1/models?username={username}&limit=100"
58
  output = {}
 
59
  headers = {}
60
  if nsfw is not None:
61
  url = url + f"&nsfw={BOOLPARM[nsfw]}"
@@ -70,20 +115,13 @@ def get_files_by_username(username, api_key=None, nsfw=None, hidden=None):
70
  data = response.json()
71
  # Add current page items to the list
72
  for model in data['items']:
73
- for version in model['modelVersions']:
74
- for file in version['files']:
75
- output[str(model['id']) + '/' + str(version['id']) + '/' + file['name']] = {
76
- 'downloadUrl': file['downloadUrl'],
77
- 'modelId': model['name'] + ' - ' + version['name'],
78
- 'modelUrl': f"https://civitai.com/models/{model['id']}?modelVersionId={version['id']}",
79
- 'author': model['creator']['username'],
80
- 'authorUrl': f"https://civitai.com/user/{model['creator']['username']}",
81
- 'mirrorUrl': f"https://civitaiarchive.com/models/{model['id']}?modelVersionId={version['id']}",
82
- }
83
 
84
  metadata = data.get('metadata', {})
85
  url = metadata.get('nextPage', None)
86
- return output
87
 
88
  def get_files_by_model_id(model_id, api_key=None):
89
  api_url = f"https://civitai.com/api/v1/models/{model_id}"
@@ -97,41 +135,36 @@ def get_files_by_model_id(model_id, api_key=None):
97
  model = response.json()
98
 
99
  output = {}
100
- for version in model['modelVersions']:
101
- for file in version['files']:
102
- output[str(model['id']) + '/' + str(version['id']) + '/' + file['name']] = {
103
- 'downloadUrl': file['downloadUrl'],
104
- 'modelId': model['name'] + ' - ' + version['name'],
105
- 'modelUrl': f"https://civitai.com/models/{model['id']}?modelVersionId={version['id']}",
106
- 'author': model['creator']['username'],
107
- 'authorUrl': f"https://civitai.com/user/{model['creator']['username']}",
108
- 'mirrorUrl': f"https://civitaiarchive.com/models/{model['id']}?modelVersionId={version['id']}",
109
- }
110
- return output
111
 
112
  except requests.exceptions.RequestException as e:
113
  raise gr.Error("Something went wrong in fetching CivitAI API")
114
 
115
- def process_url(url, profile, user_repo_id, oauth_token, folder, api_key=None, nsfw=None, hidden=None):
116
  if url.startswith("https://civitai.com/models/"):
117
  model_id = url.split('/')[4]
118
- files = get_files_by_model_id(model_id, api_key)
119
  elif url.startswith("https://civitai.com/user/"):
120
  username = url.split('/')[4]
121
- files = get_files_by_username(username, api_key, nsfw, hidden)
122
  else:
123
  raise gr.Error("Unknown CivitAI URL format, please provide model URL or user profile URL")
 
 
 
124
 
125
- gr.Info(f"Found {len(files)} files to download")
126
-
127
 
128
  downloaded_files = {}
129
- total_files = len(files)
130
  current_file = 1
131
  for dl_path, data in files.items():
132
  try:
133
  download_url = data['downloadUrl']
134
- filename = dl_path.split('/')[-1]
135
  if file_exists(
136
  repo_id = user_repo_id,
137
  filename = dl_path,
@@ -169,8 +202,50 @@ Mirror: [{data['mirrorUrl']}]({data['mirrorUrl']})
169
  finally:
170
  current_file += 1
171
 
172
- return files
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
 
174
 
175
 
176
  def add_mirror(repo_id):
@@ -190,7 +265,7 @@ def add_mirror(repo_id):
190
 
191
 
192
 
193
- def upload_civit_to_hf(profile: Optional[gr.OAuthProfile], oauth_token: gr.OAuthToken, url, destination_repo, civitai_api_key=None, nsfw=None, hidden=None):
194
  if not profile.name:
195
  raise gr.Error("Are you sure you are logged in?")
196
 
@@ -220,11 +295,13 @@ def upload_civit_to_hf(profile: Optional[gr.OAuthProfile], oauth_token: gr.OAuth
220
  gr.Info(f"Repository {user_repo_id} already exists, will update it")
221
  update_repo_visibility(repo_id=user_repo_id, private=False, token=oauth_token.token)
222
 
223
- files = process_url(url, profile, user_repo_id, oauth_token.token, folder, civitai_api_key, nsfw, hidden)
224
  if not files or len(files.keys()) == 0:
225
  raise gr.Error("No files were copied. Something went wrong.")
226
 
227
  gr.Info(f"Copied {len(files)} files")
 
 
228
 
229
  results = []
230
 
@@ -299,6 +376,11 @@ Once uploaded, it will add this repository to CivitaiArchive.com as a mirror.
299
  label="Hidden models",
300
  info="Optional: Include, exclude or do not specify inclusion of hidden models.",
301
  )
 
 
 
 
 
302
 
303
  instructions = gr.HTML("")
304
  submit_button_civit = gr.Button("Upload to Hugging Face", interactive=True)
 
52
  except Exception as e:
53
  raise gr.Error(f"Error downloading file: {str(e)}")
54
 
55
+ def get_model_meta(model):
56
+ """Read model metadata from json (api/models format).
57
+
58
+ Includes all versions, files and images therein.
59
+ """
60
+ dfiles = dict()
61
+ dimages = dict()
62
+ for version in model['modelVersions']:
63
+ mainfile = ""
64
+ for file in version['files']:
65
+ if mainfile == "":
66
+ mainfile = os.path.splitext(file['name'])[0]
67
+ dfiles[str(model['id']) + '/' + str(version['id']) + '/' + file['name']] = {
68
+ 'rawModelId': model['id'],
69
+ 'rawVersionId': version['id'],
70
+ 'rawFilename': file['name'],
71
+ 'downloadUrl': file['downloadUrl'],
72
+ 'modelId': model['name'] + ' - ' + version['name'], # Not used?
73
+ 'modelUrl': f"https://civitai.com/models/{model['id']}?modelVersionId={version['id']}",
74
+ 'author': model['creator']['username'],
75
+ 'authorUrl': f"https://civitai.com/user/{model['creator']['username']}",
76
+ 'mirrorUrl': f"https://civitaiarchive.com/models/{model['id']}?modelVersionId={version['id']}",
77
+ }
78
+ for image in version['images']:
79
+ # Image ids can be used for direct access,
80
+ # but we also need to rename them to the model file to give an indication of attachment.
81
+ vext = os.path.splitext(image['url'])[-1]
82
+ imagename = mainfile + '-ID' + str(image['id']) + '.preview' + vext
83
+ dimages[str(model['id']) + '/' + str(version['id']) + '/' + imagename] = {
84
+ 'rawModelId': model['id'],
85
+ 'rawVersionId': version['id'],
86
+ 'rawFilename': imagename,
87
+ 'downloadUrl': image['url'],
88
+ 'modelId': model['name'] + ' - ' + version['name'], # Not used?
89
+ 'modelUrl': f"https://civitai.com/models/{model['id']}?modelVersionId={version['id']}",
90
+ 'author': model['creator']['username'],
91
+ 'authorUrl': f"https://civitai.com/user/{model['creator']['username']}",
92
+ 'mirrorUrl': f"https://civitaiarchive.com/models/{model['id']}?modelVersionId={version['id']}",
93
+ # Tags which might be used for filtering in future.
94
+ 'nsfwLevel': image['nsfwLevel'], # 1 is sfw, 4 is suggestive, 8+ is explicit.
95
+ 'poi': image['poi'], # Real person. Content was purged.
96
+ 'type': image['type'], # image or video. We already have the extension.
97
+ }
98
+ return (dfiles, dimages)
99
+
100
  def get_files_by_username(username, api_key=None, nsfw=None, hidden=None):
101
  url = f"https://civitai.com/api/v1/models?username={username}&limit=100"
102
  output = {}
103
+ images = {}
104
  headers = {}
105
  if nsfw is not None:
106
  url = url + f"&nsfw={BOOLPARM[nsfw]}"
 
115
  data = response.json()
116
  # Add current page items to the list
117
  for model in data['items']:
118
+ (dfiles, dimages) = get_model_meta(model)
119
+ output.update(dfiles)
120
+ images.update(dimages)
 
 
 
 
 
 
 
121
 
122
  metadata = data.get('metadata', {})
123
  url = metadata.get('nextPage', None)
124
+ return (output, images)
125
 
126
  def get_files_by_model_id(model_id, api_key=None):
127
  api_url = f"https://civitai.com/api/v1/models/{model_id}"
 
135
  model = response.json()
136
 
137
  output = {}
138
+ images = {}
139
+ (dfiles, dimages) = get_model_meta(model)
140
+ output.update(dfiles)
141
+ images.update(dimages)
142
+ return (output, images)
 
 
 
 
 
 
143
 
144
  except requests.exceptions.RequestException as e:
145
  raise gr.Error("Something went wrong in fetching CivitAI API")
146
 
147
+ def process_url(url, profile, user_repo_id, oauth_token, folder, api_key=None, nsfw=None, hidden=None, indimages = False):
148
  if url.startswith("https://civitai.com/models/"):
149
  model_id = url.split('/')[4]
150
+ (files, images) = get_files_by_model_id(model_id, api_key)
151
  elif url.startswith("https://civitai.com/user/"):
152
  username = url.split('/')[4]
153
+ (files, images) = get_files_by_username(username, api_key, nsfw, hidden)
154
  else:
155
  raise gr.Error("Unknown CivitAI URL format, please provide model URL or user profile URL")
156
+
157
+ total_files = len(files)
158
+ total_images = len(images)
159
 
160
+ gr.Info(f"Found {total_files} files to download, {total_images} images")
 
161
 
162
  downloaded_files = {}
 
163
  current_file = 1
164
  for dl_path, data in files.items():
165
  try:
166
  download_url = data['downloadUrl']
167
+ filename = data["rawFilename"]
168
  if file_exists(
169
  repo_id = user_repo_id,
170
  filename = dl_path,
 
202
  finally:
203
  current_file += 1
204
 
205
+ # Download images if the model has been downloaded.
206
+ downloaded_images = {}
207
+ current_image = 1
208
+ if not indimages:
209
+ gr.Info(f"Skipping all images.")
210
+ else:
211
+ for dl_path, data in images.items():
212
+ try:
213
+ download_url = data['downloadUrl']
214
+ filename = data["rawFilename"]
215
+ if not file_exists(
216
+ repo_id = user_repo_id,
217
+ filename = os.path.split(dl_path)[:-1],
218
+ token = oauth_token
219
+ ):
220
+ gr.Info(f"Skipping {filename}, model was not created {dl_path}")
221
+ continue
222
+ if file_exists(
223
+ repo_id = user_repo_id,
224
+ filename = dl_path,
225
+ token = oauth_token
226
+ ):
227
+ gr.Info(f"Skipping {filename}, folder exists {dl_path}")
228
+ continue
229
+ # Image download should be no different.
230
+ gr.Info(f"Downloading {filename} ({current_image}/{total_images})")
231
+ download_file(download_url, dl_path, folder, api_key)
232
+ # Upload the image only.
233
+ gr.Info(f"Uploading {filename} ({current_image}/{total_images})")
234
+ base_folder = os.path.join(folder, os.path.dirname(dl_path))
235
+ upload_folder(
236
+ folder_path=base_folder,
237
+ repo_id=user_repo_id,
238
+ repo_type="model",
239
+ path_in_repo=os.path.dirname(dl_path),
240
+ token=oauth_token
241
+ )
242
+ downloaded_images[dl_path] = download_url
243
+ except Exception as e:
244
+ gr.Warning(f"Failed to download {dl_path}: {str(e)}")
245
+ finally:
246
+ current_image += 1
247
 
248
+ return (files, images)
249
 
250
 
251
  def add_mirror(repo_id):
 
265
 
266
 
267
 
268
+ def upload_civit_to_hf(profile: Optional[gr.OAuthProfile], oauth_token: gr.OAuthToken, url, destination_repo, civitai_api_key=None, nsfw=None, hidden=None, indimages=False):
269
  if not profile.name:
270
  raise gr.Error("Are you sure you are logged in?")
271
 
 
295
  gr.Info(f"Repository {user_repo_id} already exists, will update it")
296
  update_repo_visibility(repo_id=user_repo_id, private=False, token=oauth_token.token)
297
 
298
+ (files, images) = process_url(url, profile, user_repo_id, oauth_token.token, folder, civitai_api_key, nsfw, hidden, indimages)
299
  if not files or len(files.keys()) == 0:
300
  raise gr.Error("No files were copied. Something went wrong.")
301
 
302
  gr.Info(f"Copied {len(files)} files")
303
+ if indimages:
304
+ gr.Info(f"Copied {len(images)} images")
305
 
306
  results = []
307
 
 
376
  label="Hidden models",
377
  info="Optional: Include, exclude or do not specify inclusion of hidden models.",
378
  )
379
+ upload_images = gr.Checkbox(
380
+ value=True,
381
+ label="Upload images",
382
+ info="Optional: Upload images alongside the models for future access. Beware content restrictions."
383
+ )
384
 
385
  instructions = gr.HTML("")
386
  submit_button_civit = gr.Button("Upload to Hugging Face", interactive=True)