+
+* Feature: New txt2img and img2img model info overlay on CivitAI button press.
+* Feature: Base Model as sub folder option.
+* Feature: Ability to multi-download to selected folder.
+* Feature: Use the same folder as older versions when updating using multi-download.
+* Feature: txt2img and img2img CivitAI buttons can use local HTML file, toggle in settings.
+* New setting: Save API info of model when saving model info.
+* New setting: Automatically save all images after download.
+* New setting: Use local HTML file for model info.
+* Bug fix: better JSON decode, now forces UTF-8
+* Bug fix: Now uses the proper default file when using multi-download
+* Bug fix: Hide early access models fix, now works when published_at does not exist in API.
+* Bug fix: Fix attempt for queue clearing upon download fail.
+
+---
v3.2.5
* Bug fix: Removed default API Key since it gets blocked after many downloads.
diff --git a/javascript/civitai-html.js b/javascript/civitai-html.js
index 440ce6a..d406e08 100644
--- a/javascript/civitai-html.js
+++ b/javascript/civitai-html.js
@@ -432,7 +432,7 @@ function createCardButtons(event) {
newDiv.classList.add('goto-civitbrowser', 'card-button');
newDiv.addEventListener('click', function (event) {
event.stopPropagation();
- sendModelToBrowser(modelName, content_type);
+ modelInfoPopUp(modelName, content_type);
});
const svgIcon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
@@ -468,53 +468,125 @@ function createCardButtons(event) {
document.addEventListener('click', createCardButtons);
// Sends the selected model list to a python function
-function sendModelToBrowser(modelName, content_type) {
- const tabNav = document.querySelector('.tab-nav');
- const buttons = tabNav.querySelectorAll('button');
- for (const button of buttons) {
- if (button.textContent.includes('Browser+')) {
- button.click();
-
- const firstButton = document.querySelector('#tab_civitai_interface > div > div > div > button');
- if (firstButton) {
- firstButton.click();
- }
- }
- }
+function modelInfoPopUp(modelName, content_type) {
select_model(modelName, null, true, content_type);
+
+ // Create the overlay
+ var overlay = document.createElement('div');
+ overlay.classList.add('civitaiOverlayGlobal');
+ overlay.style.position = 'fixed';
+ overlay.style.top = '0';
+ overlay.style.left = '0';
+ overlay.style.width = '100%';
+ overlay.style.height = '100%';
+ overlay.style.backgroundColor = 'rgba(20, 20, 20, 0.95)';
+ overlay.style.zIndex = '1001';
+ overlay.style.overflowY = 'auto';
+
+ // Create the pop-up window
+ var popup = document.createElement('div');
+ popup.classList.add('civitaiOverlay');
+ popup.style.display = 'flex';
+ popup.style.justifyContent = 'center';
+ popup.style.position = 'absolute';
+ popup.style.top = '50%';
+ popup.style.left = '50%';
+ popup.style.width = '56em';
+ popup.style.transform = 'translate(-50%, -50%)';
+ popup.style.background = 'var(--body-background-fill)';
+ popup.style.padding = '2em';
+ popup.style.borderRadius = 'var(--block-radius)';
+ popup.style.borderStyle = 'solid';
+ popup.style.borderWidth = 'var(--block-border-width)';
+ popup.style.borderColor = 'var(--block-border-color)';
+ popup.style.zIndex = '1001';
+
+ // Add content to the popup
+ var popupContent = document.createElement('div'); // Change from
to
+ popupContent.classList.add('civitaiLoadingText');
+ popupContent.textContent = 'Loading model info, please wait!';
+ popupContent.style.fontSize = '24px';
+ popupContent.style.color = 'white';
+ popupContent.style.fontFamily = 'var(--font)';
+ popup.appendChild(popupContent);
+
+ // Create the close button
+ var closeButton = document.createElement('div');
+ closeButton.textContent = '×';
+ closeButton.style.position = 'fixed';
+ closeButton.style.right = '0.25em';
+ closeButton.style.top = '0';
+ closeButton.style.cursor = 'pointer';
+ closeButton.style.color = 'white';
+ closeButton.style.fontSize = '32pt';
+ closeButton.addEventListener('click', hidePopup);
+ document.addEventListener('keydown', handleKeyPress);
+
+ // Append the close button to the overlay
+ overlay.appendChild(closeButton);
+
+ // Append the popup to the overlay
+ overlay.appendChild(popup);
+
+ // Append the overlay to the body
+ document.body.style.overflow = 'hidden'; // Prevent scrolling on the main page
+ document.body.appendChild(overlay);
+
+ overlay.addEventListener('click', function (event) {
+ if (event.target === overlay) {
+ hidePopup();
+ }
+ });
+}
+
+// Function to hide the popup
+function hidePopup() {
+ var overlay = document.querySelector('.civitaiOverlayGlobal');
+ if (overlay) {
+ document.body.removeChild(overlay);
+ document.body.style.overflow = 'auto';
+ }
+}
+
+// Function to handle key presses
+function handleKeyPress(event) {
+ if (event.key === 'Escape') {
+ hidePopup();
+ }
}
// Creates a list of the selected models
var selectedModels = [];
-function multi_model_select(modelName, isChecked) {
+var selectedTypes = [];
+function multi_model_select(modelName, modelType, isChecked) {
if (arguments.length === 0) {
selectedModels = [];
+ selectedTypes = [];
return;
}
if (isChecked) {
if (!selectedModels.includes(modelName)) {
selectedModels.push(modelName);
}
+ selectedTypes.push(modelType)
} else {
- var index = selectedModels.indexOf(modelName);
- if (index > -1) {
- selectedModels.splice(index, 1);
+ var modelIndex = selectedModels.indexOf(modelName);
+ if (modelIndex > -1) {
+ selectedModels.splice(modelIndex, 1);
+ }
+ var typesIndex = selectedTypes.indexOf(modelType);
+ if (typesIndex > -1) {
+ selectedTypes.splice(typesIndex, 1);
}
}
- const output = gradioApp().querySelector('#selected_list textarea');
- output.value = JSON.stringify(selectedModels);
- updateInput(output);
-}
+ const selected_model_list = gradioApp().querySelector('#selected_model_list textarea');
+ selected_model_list.value = JSON.stringify(selectedModels);
-// Clicks the first item in the browser cards list
-function clickFirstFigureInColumn() {
- const columnDiv = document.querySelector('.column.civmodellist');
- if (columnDiv) {
- const firstFigure = columnDiv.querySelector('figure');
- if (firstFigure) {
- firstFigure.click();
- }
- }
+ const selected_type_list = gradioApp().querySelector('#selected_type_list textarea');
+ selected_type_list.value = JSON.stringify(selectedTypes);
+
+ updateInput(selected_model_list);
+ updateInput(selected_type_list);
}
// Metadata button click detector
@@ -533,6 +605,37 @@ document.addEventListener('click', function(event) {
}
}, true);
+function inputHTMLPreviewContent(html_input) {
+ var overlay = document.querySelector('.civitaiOverlay')
+ let startIndex = html_input.indexOf("'value': '");
+ if (startIndex !== -1) {
+ startIndex += "'value': '".length;
+ const endIndex = html_input.indexOf("', 'type': None,", startIndex);
+ if (endIndex !== -1) {
+ let extractedText = html_input.substring(startIndex, endIndex);
+ var modelIdNotFound = extractedText.includes(">Model ID not found. Maybe");
+
+ extractedText = extractedText.replace(/\\n\s* checkbox.checked);
const allUnchecked = checkboxes.every(checkbox => !checkbox.checked);
-
if (allChecked || allUnchecked) {
- checkboxes.forEach(clickCheckbox);
+ checkboxes.forEach(sendClick);
} else {
- checkboxes.filter(checkbox => !checkbox.checked).forEach(clickCheckbox);
- }
-
- function clickCheckbox(checkbox) {
- const clickEvent = new MouseEvent('click', {
- view: window,
- bubbles: true,
- cancelable: true
- });
- checkbox.dispatchEvent(clickEvent);
+ checkboxes.filter(checkbox => !checkbox.checked).forEach(sendClick);
}
}
@@ -601,25 +703,20 @@ function selectAllModels() {
function deselectAllModels() {
setTimeout(() => {
const checkboxes = Array.from(document.querySelectorAll('.model-checkbox'));
- checkboxes.filter(checkbox => checkbox.checked).forEach(uncheckCheckbox);
- function uncheckCheckbox(checkbox) {
- const clickEvent = new MouseEvent('click', {
- view: window,
- bubbles: true,
- cancelable: true
- });
- checkbox.dispatchEvent(clickEvent);
- }
+ checkboxes.filter(checkbox => checkbox.checked).forEach(sendClick);
}, 1000);
}
// Sends Image URL to Python to pull generation info
function sendImgUrl(image_url) {
const randomNumber = Math.floor(Math.random() * 1000);
+ const genButton = gradioApp().querySelector('#txt2img_extra_tabs > div > button')
const paddedNumber = String(randomNumber).padStart(3, '0');
const input = gradioApp().querySelector('#civitai_text2img_input textarea');
input.value = paddedNumber + "." + image_url;
updateInput(input);
+ hidePopup();
+ sendClick(genButton);
}
// Sends txt2img info to txt2img tab
diff --git a/scripts/civitai_api.py b/scripts/civitai_api.py
index 57102c5..a18238b 100644
--- a/scripts/civitai_api.py
+++ b/scripts/civitai_api.py
@@ -228,9 +228,11 @@ def model_list_html(json_data):
if hide_early_access:
early_access_days = version['earlyAccessTimeFrame']
if early_access_days != 0:
- published_at = datetime.datetime.strptime(version['publishedAt'], "%Y-%m-%dT%H:%M:%S.%fZ")
- adjusted_date = published_at + datetime.timedelta(days=early_access_days)
- if not current_time > adjusted_date:
+ published_at_str = version.get('publishedAt')
+ if published_at_str is not None:
+ published_at = datetime.datetime.strptime(version['publishedAt'], "%Y-%m-%dT%H:%M:%S.%fZ")
+ adjusted_date = published_at + datetime.timedelta(days=early_access_days)
+ if not current_time > adjusted_date or not published_at_str:
continue
versions_to_keep.append(version)
@@ -256,7 +258,7 @@ def model_list_html(json_data):
existing_files.add(file)
if file.endswith('.json'):
json_path = os.path.join(root, file)
- with open(json_path, 'r') as f:
+ with open(json_path, 'r', encoding="utf-8") as f:
try:
json_file = json.load(f)
if isinstance(json_file, dict):
@@ -322,7 +324,7 @@ def model_list_html(json_data):
model_string = escape(f"{model_name_js} ({model_id})")
model_card = f''
if installstatus != "civmodelcardinstalled":
- model_card += f'' \
+ model_card += f'' \
+ f''
if len(item["name"]) > 40:
display_name = item["name"][:40] + '...'
@@ -553,62 +555,61 @@ def update_model_list(content_type=None, sort_type=None, period_type=None, use_s
gr.Textbox.update(value=None) # Model Filename
)
-def update_model_versions(model_id):
- item_id_and_types = {item['id']: (item['type'], item['description']) for item in gl.json_data['items']}
- if model_id is not None:
- selected_content_type, desc = item_id_and_types.get(model_id, (None, None))
- if selected_content_type is None:
- return
-
- versions_dict = defaultdict(list)
- installed_versions = set()
-
- model_folder = os.path.join(contenttype_folder(selected_content_type, desc))
- gl.main_folder = model_folder
-
- item = next((item for item in gl.json_data['items'] if item['id'] == model_id), None)
- if item is None:
- return
- versions = item['modelVersions']
-
- version_files = set()
- for version in versions:
- versions_dict[version['name']].append(item["name"])
- for version_file in version['files']:
- file_sha256 = version_file.get('hashes', {}).get('SHA256', "").upper()
- version_filename = version_file['name']
- version_files.add((version['name'], version_filename, file_sha256))
-
- for root, _, files in os.walk(model_folder):
- for file in files:
- if file.endswith('.json'):
- try:
- json_path = os.path.join(root, file)
- with open(json_path, 'r') as f:
- json_data = json.load(f)
- if isinstance(json_data, dict):
- if 'sha256' in json_data and json_data['sha256']:
- sha256 = json_data.get('sha256', "").upper()
- for version_name, _, file_sha256 in version_files:
- if sha256 == file_sha256:
- installed_versions.add(version_name)
- break
- except Exception as e:
- print(f"failed to read: \"{file}\": {e}")
-
- for version_name, version_filename, _ in version_files:
- if file == version_filename:
- installed_versions.add(version_name)
- break
-
- version_names = list(versions_dict.keys())
- display_version_names = [f"{v} [Installed]" if v in installed_versions else v for v in version_names]
- default_installed = next((f"{v} [Installed]" for v in installed_versions), None)
- default_value = default_installed or next(iter(version_names), None)
-
- return gr.Dropdown.update(choices=display_version_names, value=default_value, interactive=True) # Version List
+def update_model_versions(model_id, json_input=None):
+ if json_input:
+ api_json = json_input
else:
- return gr.Dropdown.update(choices=[], value=None, interactive=False) # Version List
+ api_json = gl.json_data
+ for item in api_json['items']:
+ if int(item['id']) == int(model_id):
+ content_type = item['type']
+ desc = item.get('description', "None")
+
+ versions_dict = defaultdict(list)
+ installed_versions = set()
+
+ model_folder = os.path.join(contenttype_folder(content_type, desc))
+ gl.main_folder = model_folder
+ versions = item['modelVersions']
+
+ version_files = set()
+ for version in versions:
+ versions_dict[version['name']].append(item["name"])
+ for version_file in version['files']:
+ file_sha256 = version_file.get('hashes', {}).get('SHA256', "").upper()
+ version_filename = version_file['name']
+ version_files.add((version['name'], version_filename, file_sha256))
+
+ for root, _, files in os.walk(model_folder):
+ for file in files:
+ if file.endswith('.json'):
+ try:
+ json_path = os.path.join(root, file)
+ with open(json_path, 'r', encoding="utf-8") as f:
+ json_data = json.load(f)
+ if isinstance(json_data, dict):
+ if 'sha256' in json_data and json_data['sha256']:
+ sha256 = json_data.get('sha256', "").upper()
+ for version_name, _, file_sha256 in version_files:
+ if sha256 == file_sha256:
+ installed_versions.add(version_name)
+ break
+ except Exception as e:
+ print(f"failed to read: \"{file}\": {e}")
+
+ for version_name, version_filename, _ in version_files:
+ if file == version_filename:
+ installed_versions.add(version_name)
+ break
+
+ version_names = list(versions_dict.keys())
+ display_version_names = [f"{v} [Installed]" if v in installed_versions else v for v in version_names]
+ default_installed = next((f"{v} [Installed]" for v in installed_versions), None)
+ default_value = default_installed or next(iter(version_names), None)
+
+ return gr.Dropdown.update(choices=display_version_names, value=default_value, interactive=True) # Version List
+
+ return gr.Dropdown.update(choices=[], value=None, interactive=False) # Version List
def cleaned_name(file_name):
if platform.system() == "Windows":
@@ -638,22 +639,29 @@ def extract_model_info(input_string):
return name, int(id_number)
-def update_model_info(model_string=None, model_version=None):
+def update_model_info(model_string=None, model_version=None, only_html=False, input_id=None, json_input=None, from_preview=False):
video_playback = getattr(opts, "video_playback", True)
playback = ""
if video_playback: playback = "autoplay loop"
+ if json_input:
+ api_data = json_input
+ else:
+ api_data = gl.json_data
+
BtnDownInt = True
BtnDel = False
BtnImage = False
model_id = None
- model_name = None
- model_name, model_id = extract_model_info(model_string)
+ if not input_id:
+ _, model_id = extract_model_info(model_string)
+ else:
+ model_id = input_id
if model_version and "[Installed]" in model_version:
model_version = model_version.replace(" [Installed]", "")
- if model_id and model_version:
+ if model_id:
output_html = ""
output_training = ""
output_basemodel = ""
@@ -664,12 +672,13 @@ def update_model_info(model_string=None, model_version=None):
default_file = None
model_filename = None
sha256_value = None
- for item in gl.json_data['items']:
- if item['id'] == model_id:
+ for item in api_data['items']:
+ if int(item['id']) == int(model_id):
content_type = item['type']
if content_type == "LORA":
is_LORA = True
desc = item['description']
+ model_name = item['name']
model_folder = os.path.join(contenttype_folder(content_type, desc))
model_uploader = item['creator']['username']
uploader_avatar = item['creator']['image']
@@ -679,173 +688,182 @@ def update_model_info(model_string=None, model_version=None):
uploader_avatar = f'
'
tags = item.get('tags', "")
model_desc = item.get('description', "")
- for model in item['modelVersions']:
- if model['name'] == model_version:
- if model['trainedWords']:
- output_training = ",".join(model['trainedWords'])
- output_training = re.sub(r'<[^>]*:[^>]*>', '', output_training)
- output_training = re.sub(r', ?', ', ', output_training)
- output_training = output_training.strip(', ')
- if model['baseModel']:
- output_basemodel = model['baseModel']
- for file in model['files']:
- dl_dict[file['name']] = file['downloadUrl']
-
- if not model_filename:
- model_filename = file['name']
- dl_url = file['downloadUrl']
- gl.json_info = item
- sha256_value = file['hashes'].get('SHA256', 'Unknown')
-
- size = file['metadata'].get('size', 'Unknown')
- format = file['metadata'].get('format', 'Unknown')
- fp = file['metadata'].get('fp', 'Unknown')
- sizeKB = file.get('sizeKB', 0) * 1024
- filesize = _download.convert_size(sizeKB)
-
- unique_file_name = f"{size} {format} {fp} ({filesize})"
- is_primary = file.get('primary', False)
- file_list.append(unique_file_name)
- if is_primary:
- default_file = unique_file_name
- model_filename = file['name']
- dl_url = file['downloadUrl']
- gl.json_info = item
- sha256_value = file['hashes'].get('SHA256', 'Unknown')
+ if model_version is None:
+ selected_version = item['modelVersions'][0]
+ else:
+ for model in item['modelVersions']:
+ if model['name'] == model_version:
+ selected_version = model
+ break
+
+ if selected_version['trainedWords']:
+ output_training = ",".join(selected_version['trainedWords'])
+ output_training = re.sub(r'<[^>]*:[^>]*>', '', output_training)
+ output_training = re.sub(r', ?', ', ', output_training)
+ output_training = output_training.strip(', ')
+ if selected_version['baseModel']:
+ output_basemodel = selected_version['baseModel']
+ for file in selected_version['files']:
+ dl_dict[file['name']] = file['downloadUrl']
+
+ if not model_filename:
+ model_filename = file['name']
+ dl_url = file['downloadUrl']
+ gl.json_info = item
+ sha256_value = file['hashes'].get('SHA256', 'Unknown')
- if is_LORA and file_list:
- extracted_formats = [file.split(' ')[1] for file in file_list]
+ size = file['metadata'].get('size', 'Unknown')
+ format = file['metadata'].get('format', 'Unknown')
+ fp = file['metadata'].get('fp', 'Unknown')
+ sizeKB = file.get('sizeKB', 0) * 1024
+ filesize = _download.convert_size(sizeKB)
+
+ unique_file_name = f"{size} {format} {fp} ({filesize})"
+ is_primary = file.get('primary', False)
+ file_list.append(unique_file_name)
+ if is_primary:
+ default_file = unique_file_name
+ model_filename = file['name']
+ dl_url = file['downloadUrl']
+ gl.json_info = item
+ sha256_value = file['hashes'].get('SHA256', 'Unknown')
+
+ if is_LORA and file_list:
+ extracted_formats = [file.split(' ')[1] for file in file_list]
- if "SafeTensor" in extracted_formats and "PickleTensor" in extracted_formats:
- if "PickleTensor" in file_list[0].split(' ')[1]:
- if float(file_list[0].split(' ')[0]) <= 100:
- model_folder = os.path.join(contenttype_folder("TextualInversion"))
+ if "SafeTensor" in extracted_formats and "PickleTensor" in extracted_formats:
+ if "PickleTensor" in file_list[0].split(' ')[1]:
+ if float(file_list[0].split(' ')[0]) <= 100:
+ model_folder = os.path.join(contenttype_folder("TextualInversion"))
+
+ model_url = selected_version['downloadUrl']
+ model_main_url = f"https://civitai.com/models/{item['id']}"
+ img_html = '
'
+ for index, pic in enumerate(selected_version['images']):
+ meta_button = False
+ meta = pic['meta']
+ if meta and meta.get('prompt'):
+ meta_button = True
+ BtnImage = True
+ # Change width value in URL to original image width
+ image_url = re.sub(r'/width=\d+', f'/width={pic["width"]}', pic["url"])
+ if pic['type'] == "video":
+ image_url = image_url.replace("width=", "transcode=true,width=")
+ nsfw = 'class="model-block"'
+
+ if pic['nsfw'] not in ["None", "Soft"]:
+ nsfw = 'class="civnsfw model-block"'
+
+ img_html += f'''
+
'
- for index, pic in enumerate(model['images']):
- meta_button = False
- meta = pic['meta']
- if meta and meta.get('prompt'):
- meta_button = True
- BtnImage = True
- # Change width value in URL to original image width
- image_url = re.sub(r'/width=\d+', f'/width={pic["width"]}', pic["url"])
- if pic['type'] == "video":
- image_url = image_url.replace("width=", "transcode=true,width=")
- nsfw = 'class="model-block"'
-
- if pic['nsfw'] not in ["None", "Soft"]:
- nsfw = 'class="civnsfw model-block"'
+ if meta:
+ img_html += '
'
+ # Define the preferred order of keys and convert them to lowercase
+ preferred_order = ["prompt", "negativePrompt", "seed", "Size", "Model", "clipSkip", "sampler", "steps", "cfgScale"]
+ preferred_order_lower = [key.lower() for key in preferred_order]
+ # Loop through the keys in the preferred order and add them to the HTML
+ for key in preferred_order:
+ if key in meta:
+ value = meta[key]
+ img_html += f'
{escape(str(key).capitalize())}
{escape(str(value))}
'
+ # Check if there are remaining keys in meta
+ remaining_keys = [key for key in meta if key.lower() not in preferred_order_lower]
- img_html += f'''
-
'
- # Define the preferred order of keys and convert them to lowercase
- preferred_order = ["prompt", "negativePrompt", "seed", "Size", "Model", "clipSkip", "sampler", "steps", "cfgScale"]
- preferred_order_lower = [key.lower() for key in preferred_order]
- # Loop through the keys in the preferred order and add them to the HTML
- for key in preferred_order:
- if key in meta:
- value = meta[key]
- img_html += f'
{escape(str(key).capitalize())}
{escape(str(value))}
'
- # Check if there are remaining keys in meta
- remaining_keys = [key for key in meta if key.lower() not in preferred_order_lower]
+ img_html += '
'
- # Add the rest
- if remaining_keys:
- img_html += f"""
-
-
-
- More details...
-
- """
- for key in remaining_keys:
- value = meta[key]
- img_html += f'
{escape(str(key).capitalize())}
{escape(str(value))}
'
- img_html = img_html + '
'
-
- img_html += '
'
-
- img_html = img_html + '
'
- img_html = img_html + '
'
- tags_html = ''.join([f'{escape(str(tag))}' for tag in tags])
- def perms_svg(color):
- return f''\
- f''
- deny_svg = f'{perms_svg("red")}'
- perms_html= '
'\
- f'{allow_svg if item.get("allowNoCredit") else deny_svg} Use the model without crediting the creator '\
- f'{allow_svg if item.get("allowCommercialUse") in ["Image", "Rent", "RentCivit", "Sell"] else deny_svg} Sell images they generate '\
- f'{allow_svg if item.get("allowCommercialUse") in ["Rent", "Sell"] else deny_svg} Run on services that generate images for money '\
- f'{allow_svg if item.get("allowCommercialUse") in ["RentCivit", "Rent", "Sell"] else deny_svg} Run on Civitai '\
- f'{allow_svg if item.get("allowDerivatives") else deny_svg} Share merges using this model '\
- f'{allow_svg if item.get("allowCommercialUse") == "Sell" else deny_svg} Sell this model or merges using this model '\
- f'{allow_svg if item.get("allowDifferentLicense") else deny_svg} Have different permissions when sharing merges'\
- '
'
+ tags_html = ''.join([f'{escape(str(tag))}' for tag in tags])
+ def perms_svg(color):
+ return f''\
+ f''
+ deny_svg = f'{perms_svg("red")}'
+ perms_html= '
'\
+ f'{allow_svg if item.get("allowNoCredit") else deny_svg} Use the model without crediting the creator '\
+ f'{allow_svg if item.get("allowCommercialUse") in ["Image", "Rent", "RentCivit", "Sell"] else deny_svg} Sell images they generate '\
+ f'{allow_svg if item.get("allowCommercialUse") in ["Rent", "Sell"] else deny_svg} Run on services that generate images for money '\
+ f'{allow_svg if item.get("allowCommercialUse") in ["RentCivit", "Rent", "Sell"] else deny_svg} Run on Civitai '\
+ f'{allow_svg if item.get("allowDerivatives") else deny_svg} Share merges using this model '\
+ f'{allow_svg if item.get("allowCommercialUse") == "Sell" else deny_svg} Sell this model or merges using this model '\
+ f'{allow_svg if item.get("allowDifferentLicense") else deny_svg} Have different permissions when sharing merges'\
+ '