From 6877d1b60a2b1e4bc69615adab833517f2a016ad Mon Sep 17 00:00:00 2001 From: BlafKing Date: Sat, 16 Mar 2024 23:47:19 +0100 Subject: [PATCH] Update to v3.5.0 API Fix --- README.md | 6 + javascript/civitai-html.js | 15 +- scripts/civitai_api.py | 413 +++++++++++++-------------------- scripts/civitai_file_manage.py | 129 +++------- scripts/civitai_global.py | 7 +- scripts/civitai_gui.py | 22 +- 6 files changed, 215 insertions(+), 377 deletions(-) diff --git a/README.md b/README.md index 7582681..22491a5 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,12 @@ https://github.com/BlafKing/sd-civitai-browser-plus/assets/9644716/44c5c7a0-4854 # Changelog 📋 +

v3.5.0

+ +* Bug fix: Extension now works again with the latest CivitAI API version! +* Cleanup: Re-wrote backend API handling code. + +---

v3.4.3

* Bug fix: Hotfix for a change in the public API which broke searching. diff --git a/javascript/civitai-html.js b/javascript/civitai-html.js index 243a2f0..f24a283 100644 --- a/javascript/civitai-html.js +++ b/javascript/civitai-html.js @@ -223,15 +223,12 @@ function pressRefresh() { return; } - - let button = document.querySelector("#refreshBtn"); - if (!button) { - button = document.querySelector("#refreshBtnL"); - } - if (button) { - button.click(); - } else { - console.error("Both buttons with IDs #refreshBtn and #refreshBtnL not found."); + let output = gradioApp().querySelector('#page_slider_trigger textarea'); + if (output) { + const randomNumber = Math.floor(Math.random() * 1000); + const paddedNumber = String(randomNumber).padStart(3, '0'); + output.value = paddedNumber; + updateInput(output); } }, 200); } diff --git a/scripts/civitai_api.py b/scripts/civitai_api.py index e10f39c..53d445b 100644 --- a/scripts/civitai_api.py +++ b/scripts/civitai_api.py @@ -138,79 +138,6 @@ def contenttype_folder(content_type, desc=None, fromCheck=False, custom_folder=N return folder -def api_to_data(content_type, sort_type, period_type, use_search_term, current_page, base_filter, only_liked, tile_count, search_term=None, nsfw=None, timeOut=None, isNext=None, inputs_changed=None): - if current_page in [0, None, ""]: - current_page = 1 - if inputs_changed: - gl.file_scan = False - api_url = f"https://civitai.com/api/v1/models?limit={tile_count}&page=1" - else: - api_url = f"https://civitai.com/api/v1/models?limit={tile_count}&page={current_page}" - - if timeOut: - if isNext: - next_page = str(int(current_page) + 1) - else: - if current_page not in [1, 0, None, ""]: - next_page = str(int(current_page) - 1) - api_url = f"https://civitai.com/api/v1/models?limit={tile_count}&page={next_page}" - - if period_type: - period_type = period_type.replace(" ", "") - query = {'sort': sort_type, 'period': period_type} - - types_query_str = "" - - if content_type: - types_query_str = "".join([f"&types={type}" for type in content_type]) - - query_str = urllib.parse.urlencode(query, quote_via=urllib.parse.quote) - - if types_query_str: - query_str += types_query_str - - if use_search_term != "None" and search_term: - search_term = search_term.replace("\\","\\\\") - if "civitai.com" in search_term: - match = re.search(r'models/(\d+)', search_term) - model_number = match.group(1) - query_str = f"&ids={urllib.parse.quote(model_number)}" - elif use_search_term == "User name": - query_str += f"&username={urllib.parse.quote(search_term)}" - elif use_search_term == "Tag": - query_str += f"&tag={urllib.parse.quote(search_term)}" - else: - query_str += f"&query={urllib.parse.quote(search_term)}" - - if base_filter: - for base in base_filter: - query_str += f"&baseModels={urllib.parse.quote(base)}" - - if only_liked: - query_str += f"&favorites=true" - - if nsfw == False: - query_str += f"&nsfw=false" - - full_url = f"{api_url}&{query_str}" - - if gl.file_scan: - highest_number = max(gl.url_list_with_numbers.keys()) - full_url = gl.url_list_with_numbers.get(int(current_page)) - nextPage = int(current_page) + 1 - prevPage = int(current_page) - 1 - data = request_civit_api(full_url) - data["metadata"]["currentPage"] = current_page - data["metadata"]["totalPages"] = highest_number - if not nextPage > highest_number: - data["metadata"]["nextPage"] = gl.url_list_with_numbers.get(nextPage) - if not prevPage == 0: - data["metadata"]["prevPage"] = gl.url_list_with_numbers.get(prevPage) - else: - data = request_civit_api(full_url) - - return data - def model_list_html(json_data): video_playback = getattr(opts, "video_playback", True) playback = "" @@ -283,10 +210,10 @@ def model_list_html(json_data): baseModel = "Not Found" try: - if 'updatedAt' in item['modelVersions'][0]: - date = item['modelVersions'][0]['updatedAt'].split('T')[0] + if 'publishedAt' in item['modelVersions'][0]: + date = item['modelVersions'][0]['publishedAt'].split('T')[0] except: - baseModel = "Not Found" + date = "Not Found" if gl.sortNewest: if date not in sorted_models: @@ -352,12 +279,45 @@ def model_list_html(json_data): HTML += '' return HTML -def update_prev_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count): - return update_next_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count, isNext=False) - -def update_next_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count, isNext=True): - use_LORA = getattr(opts, "use_LORA", False) +def create_api_url(content_type=None, sort_type=None, period_type=None, use_search_term=None, base_filter=None, only_liked=None, tile_count=None, search_term=None, nsfw=None, isNext=None): + base_url = "https://civitai.com/api/v1/models" + if isNext is not None: + return gl.json_data['metadata']['nextPage' if isNext else 'prevPage'] + + params = {'limit': tile_count, 'sort': sort_type, 'period': period_type.replace(" ", "") if period_type else None} + + if content_type: + for ctype in content_type: + params["types"] = ctype + + if use_search_term != "None" and search_term: + search_term = search_term.replace("\\", "\\\\") + if "civitai.com" in search_term: + model_number = re.search(r'models/(\d+)', search_term).group(1) + params = {'ids': model_number} + else: + key_map = {"User name": "username", "Tag": "tag"} + search_key = key_map.get(use_search_term, "query") + params[search_key] = search_term + + if base_filter: + for base in base_filter: + params["baseModels"] = base + + if only_liked: + params["favorites"] = "true" + + if nsfw is False: + params["nsfw"] = "false" + + query_string = urllib.parse.urlencode(params, doseq=True, quote_via=urllib.parse.quote) + full_url = f"{base_url}?{query_string}" + + return full_url + +def convert_LORA_LoCon(content_type): + use_LORA = getattr(opts, "use_LORA", False) if content_type: if use_LORA and 'LORA & LoCon' in content_type: content_type.remove('LORA & LoCon') @@ -365,104 +325,110 @@ def update_next_page(content_type, sort_type, period_type, use_search_term, sear content_type.append('LORA') if 'LoCon' not in content_type: content_type.append('LoCon') - - if not isinstance(gl.json_data, dict): - timeOut = True - return_values = update_model_list(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, timeOut=timeOut, isNext=isNext) - timeOut = False - - return return_values - + return content_type + +def initial_model_page(content_type=None, sort_type=None, period_type=None, use_search_term=None, search_term=None, current_page=None, base_filter=None, only_liked=None, nsfw=None, tile_count=None, from_update_tab=False): + content_type = convert_LORA_LoCon(content_type) current_inputs = (content_type, sort_type, period_type, use_search_term, search_term, tile_count, base_filter, nsfw) - if current_inputs != gl.previous_inputs and gl.previous_inputs != None: - inputs_changed = True - else: - inputs_changed = False - - if inputs_changed: - return_values = update_model_list(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count) - return return_values - - if not gl.file_scan: - if isNext: - if gl.json_data['metadata']['nextPage'] is not None: - gl.json_data = request_civit_api(gl.json_data['metadata']['nextPage']) - else: - gl.json_data = None - else: - if gl.json_data['metadata']['prevPage'] is not None: - gl.json_data = request_civit_api(gl.json_data['metadata']['prevPage']) - else: - gl.json_data = None - else: - highest_number = max(gl.url_list_with_numbers.keys()) - if isNext: - if gl.json_data['metadata']['nextPage'] is not None: - currentPage = int(gl.json_data['metadata']['currentPage']) - nextPage = currentPage + 2 - prevPage = currentPage - pageCount = currentPage + 1 - gl.json_data = request_civit_api(gl.json_data['metadata']['nextPage']) - - gl.json_data["metadata"]["totalPages"] = highest_number - if not nextPage > highest_number: - gl.json_data["metadata"]["nextPage"] = gl.url_list_with_numbers.get(nextPage) - if not prevPage == 0: - gl.json_data["metadata"]["prevPage"] = gl.url_list_with_numbers.get(prevPage) - gl.json_data["metadata"]["currentPage"] = pageCount - else: - gl.json_data = None - else: - if gl.json_data['metadata']['prevPage'] is not None: - currentPage = int(gl.json_data['metadata']['currentPage']) - nextPage = currentPage - prevPage = currentPage - 2 - pageCount = currentPage - 1 - gl.json_data = request_civit_api(gl.json_data['metadata']['prevPage']) - - gl.json_data["metadata"]["totalPages"] = highest_number - if not nextPage > highest_number: - gl.json_data["metadata"]["nextPage"] = gl.url_list_with_numbers.get(nextPage) - if not prevPage == 0: - gl.json_data["metadata"]["prevPage"] = gl.url_list_with_numbers.get(prevPage) - gl.json_data["metadata"]["currentPage"] = pageCount - else: - gl.json_data = None - - if gl.json_data is None: - return + if current_inputs != gl.previous_inputs and gl.previous_inputs != None or not current_page: + current_page = 1 + gl.previous_inputs = current_inputs - if not isinstance(gl.json_data, dict): - hasPrev = current_page not in [0, 1] - hasNext = current_page == 1 or hasPrev - model_dict = {} + if not from_update_tab: + gl.from_update_tab = False - if gl.json_data == "timeout": - HTML = api_error_msg("timeout") - elif gl.json_data == "offline": - HTML = api_error_msg("offline") - elif gl.json_data == "error": - HTML = api_error_msg("error") + if current_page == 1: + api_url = create_api_url(content_type, sort_type, period_type, use_search_term, base_filter, only_liked, tile_count, search_term, nsfw) + gl.url_list = {1 : api_url} + else: + api_url = gl.url_list.get(current_page) + else: + api_url = gl.url_list.get(current_page) + gl.from_update_tab = True + + gl.json_data = request_civit_api(api_url) + + max_page = 1 + model_list = [] + hasPrev, hasNext = False, False + if not isinstance(gl.json_data, dict): + HTML = api_error_msg(gl.json_data) else: - (hasPrev, hasNext, current_page, total_pages) = pagecontrol(gl.json_data) - model_dict = {} - try: - gl.json_data['items'] - except TypeError: - return gr.Dropdown.update(choices=[], value=None) + gl.json_data = insert_metadata(1) + metadata = gl.json_data['metadata'] + hasNext = 'nextPage' in metadata + hasPrev = 'prevPage' in metadata + + for item in gl.json_data['items']: + model_list.append(f"{item['name']} ({item['id']})") + + max_page = max(gl.url_list.keys()) HTML = model_list_html(gl.json_data) - - page_string = f"Page: {current_page}/{total_pages}" return ( - gr.Dropdown.update(choices=[v for k, v in model_dict.items()], value="", interactive=True), # Model List + gr.Dropdown.update(choices=model_list, value="", interactive=True), # Model List gr.Dropdown.update(choices=[], value=""), # Version List gr.HTML.update(value=HTML), # HTML Tiles gr.Button.update(interactive=hasPrev), # Prev Page Button gr.Button.update(interactive=hasNext), # Next Page Button - gr.Slider.update(value=current_page, maximum=total_pages, label=page_string), # Page Count + gr.Slider.update(value=current_page, maximum=max_page), # Page Slider + gr.Button.update(interactive=False), # Save Tags + gr.Button.update(interactive=False), # Save Images + gr.Button.update(interactive=False, visible=False if gl.isDownloading else True), # Download Button + gr.Button.update(interactive=False, visible=False), # Delete Button + gr.Textbox.update(interactive=False, value=None, visible=True), # Install Path + gr.Dropdown.update(choices=[], value="", interactive=False), # Sub Folder List + gr.Dropdown.update(choices=[], value="", interactive=False), # File List + gr.HTML.update(value='
'), # Preview HTML + gr.Textbox.update(value=None), # Trained Tags + gr.Textbox.update(value=None), # Base Model + gr.Textbox.update(value=None) # Model Filename + ) + +def prev_model_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count): + return next_model_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count, isNext=False) + +def next_model_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count, isNext=True): + content_type = convert_LORA_LoCon(content_type) + + current_inputs = (content_type, sort_type, period_type, use_search_term, search_term, tile_count, base_filter, nsfw) + if current_inputs != gl.previous_inputs and gl.previous_inputs != None: + return initial_model_page(content_type, sort_type, period_type, use_search_term, search_term, current_page, base_filter, only_liked, nsfw, tile_count) + + api_url = create_api_url(isNext=isNext) + gl.json_data = request_civit_api(api_url) + + next_page = current_page + model_list = [] + max_page = 1 + hasPrev, hasNext = False, False + if not isinstance(gl.json_data, dict): + HTML = api_error_msg(gl.json_data) + + else: + next_page = current_page + 1 if isNext else current_page - 1 + + gl.json_data = insert_metadata(next_page, api_url) + + metadata = gl.json_data['metadata'] + hasNext = 'nextPage' in metadata + hasPrev = 'prevPage' in metadata + + for item in gl.json_data['items']: + model_list.append(f"{item['name']} ({item['id']})") + + max_page = max(gl.url_list.keys()) + HTML = model_list_html(gl.json_data) + + return ( + gr.Dropdown.update(choices=model_list, value="", interactive=True), # Model List + gr.Dropdown.update(choices=[], value=""), # Version List + gr.HTML.update(value=HTML), # HTML Tiles + gr.Button.update(interactive=hasPrev), # Prev Page Button + gr.Button.update(interactive=hasNext), # Next Page Button + gr.Slider.update(value=next_page, maximum=max_page), # Current Page gr.Button.update(interactive=False), # Save Tags gr.Button.update(interactive=False), # Save Images gr.Button.update(interactive=False, visible=False if gl.isDownloading else True), # Download Button @@ -476,95 +442,20 @@ def update_next_page(content_type, sort_type, period_type, use_search_term, sear gr.Textbox.update(value=None) # Model Filename ) -def pagecontrol(json_data): - current_page = f"{json_data['metadata']['currentPage']}" - total_pages = f"{json_data['metadata']['totalPages']}" - hasNext = False - hasPrev = False - if 'nextPage' in json_data['metadata']: - hasNext = True - if 'prevPage' in json_data['metadata']: - hasPrev = True - return hasPrev, hasNext, current_page, total_pages - -def update_model_list(content_type=None, sort_type=None, period_type=None, use_search_term=None, search_term=None, current_page=None, base_filter=None, only_liked=None, nsfw=None, tile_count=None, timeOut=None, isNext=None, from_ver=False, from_installed=False): - use_LORA = getattr(opts, "use_LORA", False) - model_list = [] +def insert_metadata(page_nr, api_url=None): + metadata = gl.json_data['metadata'] - if content_type: - if use_LORA and 'LORA & LoCon' in content_type: - content_type.remove('LORA & LoCon') - if 'LORA' not in content_type: - content_type.append('LORA') - if 'LoCon' not in content_type: - content_type.append('LoCon') - - if not from_ver and not from_installed: - gl.ver_json = None - - current_inputs = (content_type, sort_type, period_type, use_search_term, search_term, tile_count, base_filter, nsfw) - if current_inputs != gl.previous_inputs and gl.previous_inputs != None: - inputs_changed = True - else: - inputs_changed = False - - gl.previous_inputs = current_inputs - - gl.json_data = api_to_data(content_type, sort_type, period_type, use_search_term, current_page, base_filter, only_liked, tile_count, search_term, nsfw, timeOut, isNext, inputs_changed) - if gl.json_data is None: - return - - if not isinstance(gl.json_data, dict): - hasPrev = current_page not in [0, 1] - hasNext = current_page == 1 or hasPrev - - if gl.json_data == "timeout": - HTML = api_error_msg("timeout") - elif gl.json_data == "offline": - HTML = api_error_msg("offline") - elif gl.json_data == "error": - HTML = api_error_msg("error") - - if from_installed or from_ver: - gl.json_data = gl.ver_json + if not metadata.get('prevPage', None) and page_nr > 1: + metadata['prevPage'] = gl.url_list.get((page_nr - 1)) - if isinstance(gl.json_data, dict): - if not from_ver: - (hasPrev, hasNext, current_page, total_pages) = pagecontrol(gl.json_data) - else: - current_page = 1 - total_pages = 1 - hasPrev = False - hasNext = False - for item in gl.json_data['items']: - model_list.append(f"{item['name']} ({item['id']})") - - HTML = model_list_html(gl.json_data) - else: - current_page = 1 - total_pages = 1 + if gl.from_update_tab: + if gl.url_list.get((page_nr + 1), None): + metadata['nextPage'] = gl.url_list.get((page_nr + 1)) - page_string = f"Page: {current_page}/{total_pages}" + elif page_nr not in gl.url_list: + gl.url_list[page_nr] = api_url - return ( - gr.Dropdown.update(choices=model_list, value="", interactive=True), # Model List - gr.Dropdown.update(choices=[], value=""), # Version List - gr.HTML.update(value=HTML), # HTML Tiles - gr.Button.update(interactive=hasPrev), # Prev Page Button - gr.Button.update(interactive=hasNext), # Next Page Button - gr.Slider.update(value=current_page, maximum=total_pages, label=page_string), # Page Count - gr.Button.update(interactive=False), # Save Tags - gr.Button.update(interactive=False), # Save Images - gr.Button.update(interactive=False, visible=False if gl.isDownloading else True), # Download Button - gr.Button.update(interactive=False, visible=False), # Delete Button - gr.Textbox.update(interactive=False, value=None, visible=True), # Install Path - gr.Dropdown.update(choices=[], value="", interactive=False), # Sub Folder List - gr.Dropdown.update(choices=[], value="", interactive=False), # File List - gr.HTML.update(value='
'), # Preview HTML - gr.Textbox.update(value=None), # Trained Tags - gr.Textbox.update(value=None), # Base Model - gr.Textbox.update(value=None) # Model Filename - ) + return gl.json_data def update_model_versions(model_id, json_input=None): if json_input: @@ -702,8 +593,13 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in 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'] + creator = item.get('creator', None) + if creator: + model_uploader = creator.get('username', '') + uploader_avatar = creator.get('image', '') + else: + model_uploader = 'User not found' + uploader_avatar = 'https://rawcdn.githack.com/gist/BlafKing/8d3f7a19e3f72cfddab46ae835037ee6/raw/296e81afbdd268200278beef478f3018b15936de/profile_placeholder.svg' if uploader_avatar is None: uploader_avatar = '' else: @@ -887,10 +783,15 @@ def update_model_info(model_string=None, model_version=None, only_html=False, in f'{allow_svg if "Sell" in allowCommercialUse 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'\ '

' + + if creator: + uploader = f'

Uploaded by {escape(str(model_uploader))}{uploader_avatar}

' + else: + uploader = f'

{escape(str(model_uploader))}{uploader_avatar}

' output_html = f'''

{escape(str(model_name))}

-

Uploaded by {escape(str(model_uploader))}{uploader_avatar}

+ {uploader}
Version
@@ -1294,5 +1195,7 @@ def api_error_msg(input_string): return div + "The CivitAI-API has timed out, please try again.
The servers might be too busy or down if the issue persists." elif input_string == "offline": return div + "The CivitAI servers are currently offline.
Please try again later." - elif input_string == "error": + elif input_string == "no_items": + return div + "Failed to retrieve any models from CivitAI
The servers might be too busy or down if the issue persists." + else: return div + "The CivitAI-API failed to respond due to an error.
Check the logs for more details." \ No newline at end of file diff --git a/scripts/civitai_file_manage.py b/scripts/civitai_file_manage.py index 47f42fc..fb4c2aa 100644 --- a/scripts/civitai_file_manage.py +++ b/scripts/civitai_file_manage.py @@ -32,7 +32,6 @@ except ImportError: gl.init() -offlineHTML = '
The Civit-API has timed out, please try again.
The servers might be too busy or the selected model could not be found.
' css_path = Path(__file__).resolve().parents[1] / "style_html.css" no_update = False from_ver = False @@ -912,8 +911,10 @@ def file_scan(folders, ver_finish, tag_finish, installed_finish, preview_finish, metadata = api_response_json.get('metadata', {}) url = metadata.get('nextPage', None) elif response.status_code == 503: + print(f"Error: Received status code: {response.status_code} with URL: {url}") + print(response.text) return ( - gr.HTML.update(value=offlineHTML), + gr.HTML.update(value=_api.api_error_msg("error")), gr.Textbox.update(value=number) ) else: @@ -933,7 +934,7 @@ def file_scan(folders, ver_finish, tag_finish, installed_finish, preview_finish, api_response['items'] = all_items if api_response['items'] == []: return ( - gr.HTML.update(value=offlineHTML), + gr.HTML.update(value=_api.api_error_msg("no_items")), gr.Textbox.update(value=number) ) @@ -965,43 +966,9 @@ def file_scan(folders, ver_finish, tag_finish, installed_finish, preview_finish, model_chunks = list(chunks(all_model_ids, tile_count)) base_url = "https://civitai.com/api/v1/models?limit=100" - gl.url_list_with_numbers = {i+1: f"{base_url}{''.join(chunk)}" for i, chunk in enumerate(model_chunks)} - - url_error = False - api_url = gl.url_list_with_numbers.get(1) + gl.url_list = {i+1: f"{base_url}{''.join(chunk)}" for i, chunk in enumerate(model_chunks)} - if not url_error: - response = requests.get(api_url, timeout=(60,30), proxies=proxies, verify=ssl) - try: - if response.status_code == 200: - response.encoding = "utf-8" - gl.ver_json = json.loads(response.text) - - highest_number = max(gl.url_list_with_numbers.keys()) - gl.ver_json["metadata"]["totalPages"] = highest_number - - if highest_number > 1: - gl.ver_json["metadata"]["nextPage"] = gl.url_list_with_numbers.get(2) - else: - print(f"Error: Received status code {response.status_code} for URL: {url}") - url_error = True - except requests.exceptions.Timeout: - print(f"Request timed out for {url}. Skipping...") - url_error = True - except requests.exceptions.ConnectionError: - print("Failed to connect to the API. The servers might be offline.") - url_error = True - except Exception as e: - print(f"An unexpected error occurred: {e}") - url_error = True - - if url_error: - gl.scan_files = False - return ( - gr.HTML.update(value=offlineHTML), - gr.Textbox.update(value=number) - ) - elif from_ver: + if from_ver: gl.scan_files = False return ( gr.HTML.update(value='
Outdated models have been found.
Please press the button above to load the models into the browser tab
'), @@ -1049,11 +1016,17 @@ def file_scan(folders, ver_finish, tag_finish, installed_finish, preview_finish, gr.HTML.update(value='
'), gr.Textbox.update(value=number) ) + +def finish_returns(): + return ( + gr.Button.update(interactive=True, visible=True), + gr.Button.update(interactive=True, visible=True), + gr.Button.update(interactive=True, visible=True), + gr.Button.update(interactive=True, visible=True), + gr.Button.update(interactive=False, visible=False) + ) -def save_tag_start(tag_start): - global from_tag, from_ver, from_installed, from_preview - from_tag, from_ver, from_installed, from_preview = True, False, False, False - number = _download.random_number(tag_start) +def start_returns(number): return ( gr.Textbox.update(value=number), gr.Button.update(interactive=False, visible=False), @@ -1063,70 +1036,40 @@ def save_tag_start(tag_start): gr.Button.update(interactive=False, visible=True), gr.HTML.update(value='
') ) + +def save_tag_start(tag_start): + global from_tag, from_ver, from_installed, from_preview + from_tag, from_ver, from_installed, from_preview = True, False, False, False + number = _download.random_number(tag_start) + return start_returns(number) def save_preview_start(preview_start): global from_tag, from_ver, from_installed, from_preview from_preview, from_tag, from_ver, from_installed = True, False, False, False number = _download.random_number(preview_start) - return ( - gr.Textbox.update(value=number), - gr.Button.update(interactive=False, visible=False), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.HTML.update(value='
') - ) + return start_returns(number) def installed_models_start(installed_start): global from_installed, from_ver, from_tag, from_preview from_installed, from_ver, from_tag, from_preview = True, False, False, False number = _download.random_number(installed_start) - return ( - gr.Textbox.update(value=number), - gr.Button.update(interactive=False, visible=False), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.HTML.update(value='
') - ) + return start_returns(number) def ver_search_start(ver_start): global from_ver, from_tag, from_installed, from_preview from_ver, from_tag, from_installed, from_preview = True, False, False, False number = _download.random_number(ver_start) - return ( - gr.Textbox.update(value=number), - gr.Button.update(interactive=False, visible=False), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.Button.update(interactive=False, visible=True), - gr.HTML.update(value='
') - ) + return start_returns(number) def save_tag_finish(): global from_tag from_tag = False - return ( - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=False, visible=False) - ) + return finish_returns() def save_preview_finish(): global from_preview from_preview = False - return ( - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=True, visible=True), - gr.Button.update(interactive=False, visible=False) - ) + return finish_returns() def scan_finish(): return ( @@ -1140,24 +1083,8 @@ def scan_finish(): def load_to_browser(content_type, sort_type, period_type, use_search_term, search_term, tile_count, base_filter, nsfw): global from_ver, from_installed - if from_ver: - model_list_return = _api.update_model_list(from_ver=True, tile_count=tile_count) - if from_installed: - model_list_return = _api.update_model_list(from_installed=True, tile_count=tile_count) - use_LORA = getattr(opts, "use_LORA", False) - if content_type: - if use_LORA and 'LORA & LoCon' in content_type: - content_type.remove('LORA & LoCon') - if 'LORA' not in content_type: - content_type.append('LORA') - if 'LoCon' not in content_type: - content_type.append('LoCon') - - current_inputs = (content_type, sort_type, period_type, use_search_term, search_term, tile_count, base_filter, nsfw) - gl.previous_inputs = current_inputs - - gl.file_scan = True + model_list_return = _api.initial_model_page(content_type, sort_type, period_type, use_search_term, search_term, 1, base_filter, False, nsfw, tile_count, True) from_ver, from_installed = False, False return ( *model_list_return, diff --git a/scripts/civitai_global.py b/scripts/civitai_global.py index 71567dd..fc57dc9 100644 --- a/scripts/civitai_global.py +++ b/scripts/civitai_global.py @@ -3,7 +3,7 @@ def init(): from urllib3.exceptions import InsecureRequestWarning warnings.simplefilter('ignore', InsecureRequestWarning) - global download_queue, last_version, cancel_status, recent_model, json_data, json_info, main_folder, previous_inputs, download_fail, sortNewest, isDownloading, old_download, scan_files, ver_json, file_scan, url_list_with_numbers, print + global download_queue, last_version, cancel_status, recent_model, last_url, json_data, json_info, main_folder, previous_inputs, download_fail, sortNewest, isDownloading, old_download, scan_files, from_update_tab, url_list, print cancel_status = None recent_model = None @@ -12,11 +12,10 @@ def init(): main_folder = None previous_inputs = None last_version = None - ver_json = None - url_list_with_numbers = None + url_list = {} download_queue = [] - file_scan = False + from_update_tab = False scan_files = False download_fail = False sortNewest = False diff --git a/scripts/civitai_gui.py b/scripts/civitai_gui.py index 3237ef4..4ac3015 100644 --- a/scripts/civitai_gui.py +++ b/scripts/civitai_gui.py @@ -206,7 +206,7 @@ def on_ui_tabs(): with gr.Row(elem_id=header): with gr.Row(elem_id="pageBox"): get_prev_page = gr.Button(value="Prev page", interactive=False, elem_id="pageBtn1") - page_slider = gr.Slider(label='Current page', step=1, minimum=1, maximum=1, value=1, min_width=80, elem_id="pageSlider") + page_slider = gr.Slider(label='Current page:', step=1, minimum=1, maximum=1, min_width=80, elem_id="pageSlider") get_next_page = gr.Button(value="Next page", interactive=False, elem_id="pageBtn2") with gr.Row(elem_id="pageBoxMobile"): pass # Row used for button placement on mobile @@ -301,6 +301,7 @@ def on_ui_tabs(): dl_url = gr.Textbox(visible=False) civitai_text2img_output = gr.Textbox(visible=False) civitai_text2img_input = gr.Textbox(elem_id="civitai_text2img_input", visible=False) + page_slider_trigger = gr.Textbox(elem_id="page_slider_trigger", visible=False) selected_model_list = gr.Textbox(elem_id="selected_model_list", visible=False) selected_type_list = gr.Textbox(elem_id="selected_type_list", visible=False) html_cancel_input = gr.Textbox(elem_id="html_cancel_input", visible=False) @@ -310,6 +311,7 @@ def on_ui_tabs(): model_select = gr.Textbox(elem_id="model_select", visible=False) model_sent = gr.Textbox(elem_id="model_sent", visible=False) type_sent = gr.Textbox(elem_id="type_sent", visible=False) + empty = gr.Textbox(value="", visible=False) download_start = gr.Textbox(visible=False) download_finish = gr.Textbox(visible=False) tag_start = gr.Textbox(visible=False) @@ -684,6 +686,8 @@ def on_ui_tabs(): tile_count_slider ] + refresh_inputs = [empty if item == page_slider else item for item in page_inputs] + page_outputs = [ list_models, list_versions, @@ -740,19 +744,21 @@ def on_ui_tabs(): # Page Button Functions # page_btn_list = { - refresh.click: _api.update_model_list, - search_term.submit: _api.update_model_list, - get_next_page.click: _api.update_next_page, - get_prev_page.click: _api.update_prev_page + refresh.click: (_api.initial_model_page, True), + search_term.submit: (_api.initial_model_page, True), + page_slider_trigger.change: (_api.initial_model_page, False), + get_next_page.click: (_api.next_model_page, False), + get_prev_page.click: (_api.prev_model_page, False) } - for trigger, function in page_btn_list.items(): - trigger(fn=function, inputs=page_inputs, outputs=page_outputs) + for trigger, (function, use_refresh_inputs) in page_btn_list.items(): + inputs_to_use = refresh_inputs if use_refresh_inputs else page_inputs + trigger(fn=function, inputs=inputs_to_use, outputs=page_outputs) trigger(fn=None, _js="() => multi_model_select()") for button in cancel_btn_list: button.click(fn=_file.cancel_scan) - + # Update model Functions # ver_search.click(