import random import re _NAMES_USA = [ "Aiko", "Alara", "Amara", "Amira", "Andromeda", "Aoife", "Ara", "Aria", "Ariel", "Arya", "Asel", "Ashira", "Astrid", "Aurora", "Aya", "Ayame", "Bree", "Briar", "Calla", "Calypso", "Celeste", "Clio", "Cora", "Dalia", "Dawn", "Daya", "Delia", "Deva", "Eila", "Eira", "Elara", "Elene", "Elin", "Elira", "Ember", "Era", "Eris", "Estelle", "Eve", "Faye", "Fern", "Fiora", "Fleur", "Flora", "Gaia", "Greer", "Gwen", "Halo", "Haven", "Hera", "Ida", "Indra", "Io", "Iris", "Iva", "Jade", "Jaya", "Juno", "Kai", "Kaia", "Kaya", "Kessa", "Kira", "Laia", "Leda", "Lila", "Lira", "Lirien", "Luma", "Luna", "Lyra", "Maia", "Mara", "Marit", "Maya", "Meira", "Mira", "Miya", "Nadia", "Naia", "Nara", "Neva", "Nia", "Nike", "Nina", "Noor", "Nora", "Nova", "Nyx", "Ora", "Orla", "Petra", "Quinn", "Ren", "Rhea", "Riona", "Rue", "Saga", "Sage", "Sarai", "Selene", "Sera", "Silva", "Sol", "Sora", "Sylva", "Tala", "Tara", "Theia", "Tova", "Ula", "Uma", "Una", "Vega", "Vela", "Vera", "Vesper", "Vira", "Vivi", "Wren", "Xara", "Xena", "Yael", "Yuki", "Zara", "Zita", "Zoe", "Zora", ] _NAMES = [ "Aaf", "Aafje", "Aafke", "Aagje", "Aaltje", "Abby", "Abigail", "Ada", "Adèle", "Adriana", "Agnes", "Aisha", "Ayla", "Alana", "Aletta", "Alexandra", "Alice", "Alicia", "Alida", "Alina", "Alise", "Aliza", "Alma", "Amalia", "Amanda", "Amber", "Amelie", "Amélie", "Amira", "Amy", "An", "Ana", "Anabel", "Anastasia", "Andrea", "Angela", "Angelina", "Aniek", "Anika", "Anissa", "Anja", "Anke", "Anna", "Annabel", "Anne", "Annebel", "Annemarie", "Annet", "Annette", "Annie", "Anouk", "Ans", "Antje", "Antoinette", "Ariane", "Arianna", "Ariana", "Arwen", "Ashley", "Astrid", "Aukje", "Aurora", "Avalon", "Aya", "Babette", "Barbara", "Bea", "Beatrix", "Beau", "Bente", "Berber", "Bernadette", "Bertje", "Betsy", "Bianca", "Bibi", "Bodil", "Bo", "Bobbi", "Bregje", "Brechtje", "Brenda", "Brit", "Britt", "Cato", "Catharina", "Celine", "Céline", "Cemre", "Chantal", "Charlotte", "Chelsey", "Chiara", "Chloë", "Christa", "Christel", "Christina", "Cindy", "Claire", "Clara", "Clarissa", "Claudia", "Cleo", "Coby", "Conny", "Cora", "Cornelia", "Cynthia", "Daantje", "Dafne", "Daisy", "Dana", "Daniëlle", "Daphne", "Debbie", "Demi", "Denise", "Desi", "Diana", "Dide", "Diede", "Dieuwertje", "Dina", "Dinja", "Dionne", "Do", "Dominique", "Doortje", "Dora", "Doris", "Doutzen", "Eef", "Eefje", "Eeke", "Eline", "Elisa", "Elise", "Elisabeth", "Ella", "Elle", "Ellen", "Ellemijn", "Ellis", "Els", "Elsa", "Else", "Elvira", "Emilia", "Emma", "Emmy", "Eva", "Evelien", "Eveline", "Evi", "Fabiënne", "Famke", "Fay", "Faye", "Fem", "Femke", "Fenna", "Fenne", "Fien", "Fiene", "Fieke", "Fleur", "Fleurtje", "Floor", "Floortje", "Flore", "Florianne", "Froukje", "Gabriëlle", "Gea", "Geertje", "Geertruida", "Geke", "Gerda", "Gerdi", "Gerdien", "Gertrude", "Ghislaine", "Gina", "Gitte", "Greet", "Greetje", "Greta", "Grietje", "Guusje", "Gwen", "Hanna", "Hannah", "Hanne", "Hanneke", "Hannelore", "Harriët", "Hedwig", "Heleen", "Helena", "Helene", "Henriëtte", "Hester", "Hilde", "Hinke", "Ilona", "Ilse", "Imke", "Imme", "Ina", "Indy", "Ineke", "Ines", "Inge", "Ingrid", "Iris", "Isa", "Isabel", "Isabella", "Isabelle", "Ise", "Iva", "Ivana", "Jacoba", "Jacqueline", "Jada", "Jade", "Janna", "Janne", "Janneke", "Jantien", "Jasmijn", "Jasmine", "Jayda", "Jelka", "Jelke", "Jente", "Jenthe", "Jet", "Jette", "Jill", "Jo", "Joan", "Joanna", "Johanna", "Jolanda", "Jolie", "Josephine", "Josje", "Judith", "Julia", "Julie", "Juliette", "Juna", "Juni", "Juul", "Juut", "Kaat", "Kaatje", "Karen", "Karin", "Karlijn", "Kiki", "Kim", "Kirsten", "Klara", "Klasina", "Kris", "Kristel", "Lana", "Lara", "Laura", "Laurien", "Lena", "Lene", "Leni", "Lenie", "Lenthe", "Lieke", "Lien", "Lieve", "Linde", "Lindsey", "Lisa", "Lisanne", "Liset", "Liselotte", "Livia", "Liz", "Liza", "Lizzy", "Loïs", "Lola", "Lonneke", "Lotte", "Lou", "Louise", "Lova", "Luca", "Lucia", "Lucie", "Luna", "Maaike", "Maan", "Maartje", "Maayke", "Madeleine", "Madelief", "Maike", "Maja", "Malou", "Manon", "Mara", "Mare", "Margot", "Margriet", "Maria", "Marieke", "Marije", "Marijne", "Marit", "Marja", "Marjan", "Marjolein", "Marleen", "Marloes", "Marlot", "Marly", "Martha", "Marthe", "Mathilde", "Maud", "Mees", "Meike", "Melanie", "Melissa", "Merel", "Mette", "Mia", "Mieke", "Mila", "Milou", "Minke", "Mira", "Mirjam", "Myrthe", "Naomi", "Natasja", "Nathalie", "Nena", "Nienke", "Nina", "Noa", "Noëlle", "Noor", "Nora", "Nova", "Olivia", "Olga", "Pien", "Pleun", "Quinty", "Renske", "Renée", "Rianne", "Riek", "Rika", "Rina", "Rinske", "Rivka", "Robin", "Romy", "Roos", "Roosmarijn", "Rosa", "Rosalie", "Rosanne", "Rose", "Rowena", "Ruby", "Sabine", "Sanne", "Sara", "Sarah", "Sarina", "Saskia", "Selma", "Senna", "Sera", "Sharon", "Silke", "Sjoukje", "Sofie", "Sophie", "Soraya", "Sterre", "Susan", "Susanne", "Suzan", "Suzanne", "Suze", "Sylvia", "Tamar", "Tara", "Tess", "Tessa", "Teuntje", "Thea", "Theodora", "Thera", "Theresa", "Thirza", "Tine", "Tineke", "Tirza", "Tjitske", "Toos", "Trijntje", "Truus", "Valerie", "Veerle", "Vera", "Vera-Lynn", "Veronique", "Victoria", "Vienna", "Vieve", "Vita", "Vivian", "Vivienne", "Wende", "Wendy", "Wiep", "Wietske", "Wies", "Wiesje", "Willeke", "Wilma", "Yara", "Yfke", "Ymkje", "Yolanda", "Yuna", "Zara", "Zoë", "Zofia", "Zonne", "Zwaantje", ] def generate_associative_name(tags=None): """Return a random evocative name for a new group.""" return random.choice(_NAMES) def clean_tag(tag): return tag.replace("_", " ").strip() def generate_associative_description(tags): """ Generate a 'real-alike' associative name based on WD tagger tags. tags: list of dicts {'tag': str, 'score': float, 'cat': int} """ if not tags: return None # Filter by score high_score_tags = [t for t in tags if t['score'] > 0.4] if not high_score_tags: high_score_tags = tags[:5] # Categories: 0=general, 4=character characters = [clean_tag(t['tag']) for t in high_score_tags if t['cat'] == 4] general = [clean_tag(t['tag']) for t in high_score_tags if t['cat'] == 0] # Key attributes subject = None if characters: subject = characters[0].title() elif "1girl" in [t['tag'] for t in high_score_tags]: subject = "Maiden" elif "1boy" in [t['tag'] for t in high_score_tags]: subject = "Youth" else: subject = "Subject" # Actions/Poses actions = ["standing", "sitting", "lying", "running", "walking", "dancing", "sleeping"] found_action = next((clean_tag(t['tag']) for t in high_score_tags if t['tag'] in actions), None) # Setting/Background settings = ["forest", "beach", "city", "space", "room", "garden", "ocean", "mountain", "sky", "underwater", "street"] found_setting = next((clean_tag(t['tag']) for t in high_score_tags if t['tag'] in settings), None) # Appearance colors = ["red", "blue", "green", "white", "black", "gold", "silver", "pink", "purple", "yellow"] found_color = next((clean_tag(t['tag']) for t in high_score_tags if clean_tag(t['tag']).split()[0] in colors), None) if not found_color: found_color = next((clean_tag(t['tag']) for t in high_score_tags if any(c in t['tag'] for c in colors)), None) # Styles/Atmosphere styles = ["cyberpunk", "fantasy", "realistic", "ethereal", "dark", "bright", "sketch", "oil painting"] found_style = next((clean_tag(t['tag']) for t in high_score_tags if t['tag'] in styles), None) # Build the name templates = [] if found_style and subject: templates.append(f"{found_style.title()} {subject}") if found_color and subject: templates.append(f"The {found_color.title()} {subject}") if subject and found_action: if found_action.endswith("ing"): templates.append(f"{subject} {found_action.title()}") else: # Basic attempt at present participle action_ing = found_action if action_ing.endswith("e"): action_ing = action_ing[:-1] + "ing" else: action_ing += "ing" templates.append(f"{subject} {action_ing.title()}") if subject and found_setting: templates.append(f"{subject} in the {found_setting.title()}") if found_style and found_setting: templates.append(f"{found_style.title()} {found_setting.title()}") if not templates: # Fallback: combine two random general tags if len(general) >= 2: return f"{general[0].title()} {general[1].title()}" elif general: return general[0].title() else: return "Untitled Artwork" # Return a random template result return random.choice(templates) def get_base_name(name: str) -> str: """Remove timestamp prefixes from filename.""" return re.sub(r'^(\d{8}_\d{6}_)+', '', name)