import gradio as gr from huggingface_hub import HfApi from huggingface_hub.utils import HfHubHTTPError # --- Core Functions --- def get_my_spaces(hf_token): """Fetches a list of the user's public Hugging Face Spaces.""" if not hf_token: # Return empty values for all outputs return [], "Please enter your Hugging Face token.", [] try: api = HfApi(token=hf_token) # Get the username to list spaces accurately username = api.whoami()["name"] spaces = api.list_spaces(author=username) # Filter for only public spaces public_spaces = [space.id for space in spaces if not space.private] if not public_spaces: return [], "Successfully connected, but you have no public spaces.", [] # Return the list of spaces for the checkboxes and the state return public_spaces, f"Successfully listed {len(public_spaces)} public spaces.", public_spaces except HfHubHTTPError as e: # Handle common authentication errors return [], f"Authentication error: Please check your token. Details: {e}", [] except Exception as e: return [], f"An error occurred: {e}", [] def make_spaces_private(hf_token, selected_spaces, progress=gr.Progress()): """Sets the visibility of selected Hugging Face Spaces to private.""" if not hf_token: return "Please enter your Hugging Face token." if not selected_spaces: return "Please select at least one space to make private." progress(0, desc="Starting...") try: api = HfApi(token=hf_token) log_messages = [] total_spaces = len(selected_spaces) for i, space_id in enumerate(selected_spaces): progress((i + 1) / total_spaces, desc=f"Processing '{space_id}'...") try: # --- THIS IS THE FIX --- # We must explicitly tell the API that this is a 'space'. api.update_repo_settings(repo_id=space_id, private=True, repo_type="space") log_messages.append(f"✅ Successfully made '{space_id}' private.") except Exception as e: log_messages.append(f"❌ Failed to make '{space_id}' private: {e}") return "\n".join(log_messages) except HfHubHTTPError as e: return f"Authentication error: Please check your token. Details: {e}" except Exception as e: return f"An error occurred: {e}" # --- Gradio UI --- with gr.Blocks(theme=gr.themes.Soft()) as demo: gr.Markdown( """ # 🛡️ Hugging Face Space Privacy Control Quickly make your public Hugging Face Spaces private. 1. Create and paste a Hugging Face access token with **write** permission. 2. Click "List My Public Spaces". 3. Select the spaces you want to make private (or use "Select All"). 4. Click the final button to update their privacy settings. """ ) with gr.Row(): hf_token_input = gr.Textbox( label="Hugging Face Write Token", type="password", placeholder="hf_...", scale=3, ) list_spaces_button = gr.Button("List My Public Spaces", variant="secondary", scale=1) with gr.Group(): # This (invisible) state component is the key to the select_all fix spaces_list_state = gr.State([]) select_all_checkbox = gr.Checkbox(label="Select All / Deselect All") spaces_checkboxes = gr.CheckboxGroup( label="Your Public Spaces", info="Only your public spaces are shown here." ) make_private_button = gr.Button("Make Selected Spaces Private", variant="primary") status_output = gr.Textbox(label="Status", interactive=False, lines=5) # --- Event Listeners --- def list_spaces_action(token): """Called when the list button is clicked. Updates the checkboxes and the state.""" spaces, message, state_list = get_my_spaces(token) # Also reset the select_all checkbox to unchecked return gr.update(choices=spaces, value=[]), message, state_list, gr.update(value=False) list_spaces_button.click( fn=list_spaces_action, inputs=hf_token_input, outputs=[spaces_checkboxes, status_output, spaces_list_state, select_all_checkbox] ) def select_all_action(select_all_checked, full_list_of_spaces): """ Called when the "Select All" checkbox is changed. Uses the list from the state to update the checkbox group. """ if select_all_checked: return gr.update(value=full_list_of_spaces) # Select all else: return gr.update(value=[]) # Deselect all select_all_checkbox.change( fn=select_all_action, inputs=[select_all_checkbox, spaces_list_state], # Input is from the state now outputs=spaces_checkboxes ) make_private_button.click( fn=make_spaces_private, inputs=[hf_token_input, spaces_checkboxes], outputs=status_output ) demo.launch()