""" Slug generation utilities """ import re from typing import Optional def generate_slug(text: str, max_length: int = 50) -> str: """ Generate a URL-safe slug from text. Examples: "Tweezer Reprise" -> "tweezer-reprise" "You Enjoy Myself" -> "you-enjoy-myself" "The Gorge Amphitheatre" -> "the-gorge-amphitheatre" """ if not text: return "" # Convert to lowercase slug = text.lower() # Replace common special characters replacements = { "'": "", "'": "", '"': "", "&": "and", "+": "and", "@": "at", "#": "", "$": "", "%": "", "!": "", "?": "", ".": "", ",": "", ":": "", ";": "", "/": "-", "\\": "-", "(": "", ")": "", "[": "", "]": "", "{": "", "}": "", "<": "", ">": "", "—": "-", "–": "-", "...": "", } for old, new in replacements.items(): slug = slug.replace(old, new) # Replace any non-alphanumeric characters with dashes slug = re.sub(r'[^a-z0-9]+', '-', slug) # Remove leading/trailing dashes and collapse multiple dashes slug = re.sub(r'-+', '-', slug).strip('-') # Truncate to max length (at word boundary if possible) if len(slug) > max_length: slug = slug[:max_length] # Try to cut at last dash to avoid partial words last_dash = slug.rfind('-') if last_dash > max_length // 2: slug = slug[:last_dash] return slug def generate_unique_slug( base_text: str, existing_slugs: list[str], max_length: int = 50 ) -> str: """ Generate a unique slug, appending numbers if necessary. Examples: "Tweezer" with existing ["tweezer"] -> "tweezer-2" "Tweezer" with existing ["tweezer", "tweezer-2"] -> "tweezer-3" """ base_slug = generate_slug(base_text, max_length - 4) # Leave room for "-999" if base_slug not in existing_slugs: return base_slug # Find next available number counter = 2 while f"{base_slug}-{counter}" in existing_slugs: counter += 1 return f"{base_slug}-{counter}" def generate_show_slug(date_str: str, venue_name: str) -> str: """ Generate a slug for a show based on date and venue. Examples: "2024-12-31", "Madison Square Garden" -> "2024-12-31-msg" "2024-07-04", "The Gorge Amphitheatre" -> "2024-07-04-the-gorge" """ # Common venue abbreviations abbreviations = { "madison square garden": "msg", "red rocks amphitheatre": "red-rocks", "the gorge amphitheatre": "the-gorge", "alpine valley music theatre": "alpine", "dicks sporting goods park": "dicks", "mgm grand garden arena": "mgm", "saratoga performing arts center": "spac", } venue_slug = abbreviations.get(venue_name.lower()) if not venue_slug: # Take first 2-3 words of venue name venue_slug = generate_slug(venue_name, 25) return f"{date_str}-{venue_slug}" def generate_performance_slug(song_title: str, show_date: str) -> str: """ Generate a slug for a specific performance. Examples: "Tweezer", "2024-12-31" -> "tweezer-2024-12-31" """ song_slug = generate_slug(song_title, 30) return f"{song_slug}-{show_date}"