"""Bundled station list. Only used when somafm.com cannot be reached *and* no cache exists yet, so the app is still useful on a plane. The live list from ``channels.json`` always wins. Stream links are built from SomaFM's well-known ``.pls`` naming scheme and are additionally resolved at runtime. """ from __future__ import annotations from typing import Any # (id, title, genre, description) _CHANNELS: tuple[tuple[str, str, str, str], ...] = ( ("groovesalad", "Groove Salad", "ambient|electronic", "A nicely chilled plate of ambient/downtempo beats and grooves."), ("dronezone", "Drone Zone", "ambient", "Served best chilled, safe with most medications. Atmospheric textures with minimal beats."), ("deepspaceone", "Deep Space One", "ambient", "Deep ambient electronic, experimental and space music. For inner and outer space exploration."), ("spacestation", "Space Station Soma", "electronic", "Tune in, turn on, space out. Spaced-out ambient and mid-tempo electronica."), ("missioncontrol", "Mission Control", "ambient|electronic", "Celebrating NASA and Space Explorers everywhere."), ("darkzone", "The Dark Zone", "ambient", "The darker side of deep ambient. Music for staring into the Abyss."), ("dz2", "Drone Zone 2", "ambient", "A more eclectic alternative mix of atmospheric textures with minimal beats."), ("synphaera", "Synphaera Radio", "ambient|electronic", "Featuring the music from an independent record label focused on modern electronic ambient and space music."), ("secretagent", "Secret Agent", "lounge", "The soundtrack for your stylish, mysterious, dangerous life. For Spies and PIs too!"), ("illstreet", "Illinois Street Lounge", "lounge", "Classic bachelor pad, playful exotica and vintage music of tomorrow."), ("tikitime", "Tiki Time", "tiki|world", "Classic Tiki music and Vintage island rhythms to sip cocktails by."), ("bossa", "Bossa Beyond", "bossanova|world", "Silky-smooth, laid-back Brazilian-style rhythms of Bossa Nova, Samba and beyond"), ("suburbsofgoa", "Suburbs of Goa", "world", "Desi-influenced Asian world beats and beyond."), ("thistle", "ThistleRadio", "celtic|world", "Exploring music from Celtic roots and branches"), ("indiepop", "Indie Pop Rocks!", "alternative|rock", "New and classic favorite indie pop tracks."), ("digitalis", "Digitalis", "electronic|alternative", "Digitally affected analog rock to calm the agitated heart."), ("poptron", "PopTron", "alternative", "Electropop and indie dance rock with sparkle and pop."), ("u80s", "Underground 80s", "alternative|electronic", "Early 80s UK Synthpop and a bit of New Wave."), ("seventies", "Left Coast 70s", "70s|rock", "Mellow album rock from the Seventies. Yacht not required."), ("reggae", "Heavyweight Reggae", "reggae", "Reggae, Ska, Rocksteady classic and deep tracks."), ("bootliquor", "Boot Liquor", "americana", "Americana Roots music for Cowhands, Cowpokes and Cowtippers"), ("folkfwd", "Folk Forward", "folk|alternative", "Indie Folk, Alt-folk and the occasional folk classics."), ("lush", "Lush", "electronic", "Sensuous and mellow female vocals, many with an electronic influence."), ("fluid", "Fluid", "electronic|hiphop", "Drown in the electronic sound of instrumental hiphop, future soul and liquid trap."), ("beatblender", "Beat Blender", "electronic", "A late night blend of deep-house and downtempo chill."), ("cliqhop", "cliqhop idm", "electronic", "Blips'n'beeps backed mostly w/beats. Intelligent Dance Music."), ("thetrip", "The Trip", "electronic", "Progressive house / trance. Tip top tunes."), ("defcon", "DEF CON Radio", "electronic|specials", "Music for Hacking. The DEF CON Year-Round Channel."), ("dubstep", "Dub Step Beyond", "electronic", "Dubstep, Dub and Deep Bass. May damage speakers at high volume."), ("vaporwaves", "Vaporwaves", "electronic", "All Vaporwave. All the time."), ("sonicuniverse", "Sonic Universe", "jazz", "Transcending the world of jazz with eclectic, avant-garde takes on tradition."), ("metal", "Metal Detector", "metal", "From black to doom, prog to sludge, thrash to post, stoner to crossover, punk to industrial."), ("doomed", "Doomed", "ambient|industrial", "Where every day is Halloween: Dark industrial/ambient music for tortured souls."), ("covers", "Covers", "eclectic", "Just covers. Songs you know by artists you don't. We've got you covered."), ("brfm", "Black Rock FM", "eclectic", "From the Black Rock Desert playa to the world, year round!"), ("7soul", "Seven Inch Soul", "oldies", "Vintage soul tracks from the original 45 RPM vinyl."), ("insound", "The In-Sound", "oldies", "60s/70s Hipster Euro Pop where psychedelic melodies meets groovy vibes."), ("sf1033", "SF 10-33", "ambient|news", "Ambient music mixed with the sounds of San Francisco public safety radio traffic."), ("scanner", "SF Police Scanner", "live|news", "San Francisco Public Safety Scanner Feed"), ("sfinsf", "SF in SF", "spoken", "Author readings and discussions from the science fiction, fantasy, horror, and genre literary fields."), ("live", "SomaFM Live", "live|specials", "Special Live Events and rebroadcasts of past live events"), ("specials", "SomaFM Specials", "specials", "Now featuring Afternoon Jazz, Wavepool, DubX, The Surf Report & More!"), ("n5md", "n5MD Radio", "specials", "Emotional Experiments in Music: Ambient, modern composition, post-rock, & experimental electronic music"), ("chillits", "Chillits Radio", "chill|live", "Celebrating 25 years of music, chilling and camping"), ("groovesalad2", "Groove Salad 2", "ambient|electronic", "A different mix of nicely chilled ambient/downtempo beats and grooves."), ("gsclassic", "Groove Salad Classic", "ambient|electronic", "The classic (early 2000s) version of a nicely chilled plate of ambient/downtempo beats and grooves."), ("christmas", "Christmas Lounge", "holiday", "Chilled holiday grooves and classic winter lounge tracks."), ("xmasrocks", "Christmas Rocks!", "holiday", "Have yourself an indie/alternative holiday season!"), ("jollysoul", "Jolly Ol' Soul", "holiday", "Where we cut right to the soul of the season."), ("deptstore", "Department Store Christmas", "holiday", "Holiday Elevator Music from a more innocent time."), ("xmasinfrisko", "Xmas in Frisko", "holiday", "SomaFM's wacky and eclectic holiday mix. Not for the easily offended."), ) def _playlists(channel_id: str) -> list[dict[str, str]]: return [ {"url": f"https://somafm.com/{channel_id}.pls", "format": "mp3", "quality": "highest"}, {"url": f"https://somafm.com/{channel_id}130.pls", "format": "aac", "quality": "highest"}, {"url": f"https://somafm.com/{channel_id}64.pls", "format": "aacp", "quality": "high"}, {"url": f"https://somafm.com/{channel_id}32.pls", "format": "aacp", "quality": "low"}, ] def fallback_channels() -> list[dict[str, Any]]: """Return a channels.json-shaped payload so the normal parser can eat it.""" payload: list[dict[str, Any]] = [] for channel_id, title, genre, description in _CHANNELS: payload.append( { "id": channel_id, "title": title, "description": description, "dj": "SomaFM", "genre": genre, "image": f"https://somafm.com/logos/256/{channel_id}256.png", "largeimage": f"https://somafm.com/logos/512/{channel_id}512.png", "playlists": _playlists(channel_id), "listeners": "0", "lastPlaying": "", } ) return payload