import org.serviio.library.metadata.*import org.serviio.library.online.*import org.serviio.util.*import java.util.regex.Matcherimport java.util.regex.Patternimport groovy.json.JsonSlurper/* * digitallyimported.groovy * Purpose: Serviio plugin for di.fm, sky.fm and jazzradio.com (Free and Premium) *  * @author abeloin * @version 1.0 *  * History: * 0.1 di.fm free * 0.2 Added di.fm premium * 0.3 Added di.fm thumbnails * 0.4 Added automatic thumbnail retrieval if not in cache * 0.5 Added sky.fm support * 0.6 Added sky.fm thumbnails * 0.7 Added jazzradio.com support * 0.8 Added jazzradio.com thumbnails * 0.9 Thumbnails fixes * 1.0 Added the ability to input a pls * 2.0 Implemented getVersion and updated thumbnails cache info *  * Usage: In Serviio's console, add an online source with the following(for mp3): *  *       Source Type: Web Ressource *       Media Type: Audio *        *       --For full listing: *       Source URL(di.fm free): http://listen.di.fm/public3 *       Source URL(di.fm premium): http://listen.di.fm/premium?listen_key=000000000000000000000 *       Source URL(di.fm premium-high): http://listen.di.fm/premium_high?listen_key=000000000000000000000 *       Source URL(sky.fm free): http://listen.sky.fm/public3 *       Source URL(sky.fm premium): http://listen.sky.fm/premium?listen_key=000000000000000000000 *       Source URL(sky.fm premium-high): http://listen.sky.fm/premium_high?listen_key=000000000000000000000 *       Source URL(jazzradio.com free): http://listen.jazzradio.com/public3 *       Source URL(jazzradio.com premium-high): http://listen.jazzradio.com/premium_high?listen_key=000000000000000000000 *        *       --Single channel example: *       Source URL(di.fm free): http://listen.di.fm/public3/vocalchillout.pls *       Source URL(di.fm premium): http://listen.di.fm/premium/vocalchillout.pls?000000000000000000000 *       Source URL(di.fm premium-high): http://listen.di.fm/premium_high/vocalchillout.pls?000000000000000000000 *        */class digitallyimported extends WebResourceUrlExtractor {		// Plugin name	String getExtractorName() {		return 'DI.FM - SKY.FM - JAZZRADIO.COM'	}		// Plugin version	int getVersion() {		return 2	}		// URL regex	final VALID_FEED_URL = '^(?:http?://)??listen\\.di\\.fm/.*$|^(?:http?://)??listen\\.sky\\.fm/.*$|^(?:http?://)??listen\\.jazzradio\\.com/.*$'		// Validate URL	boolean extractorMatches(URL resourceUrl) {		return resourceUrl ==~ VALID_FEED_URL	}		// Website for thumbnail	final di = 'http://www.di.fm/'	final sky = 'http://www.sky.fm/'	final jazz = 'http://www.jazzradio.com/'		// Channels Extractor	WebResourceContainer extractItems(URL resourceUrl, int maxItemsToRetrieve) {		List<WebResourceItem> items = []		def listenKey = null		def premiumUrl = null		String provider = null				// Check if DI, Sky or Jazz		if (resourceUrl ==~ '^(?:http?://)??listen\\.di\\.fm/.*$') {			provider = di		} else if (resourceUrl ==~ '^(?:http?://)??listen\\.sky\\.fm/.*$') {			provider = sky		} else if (resourceUrl ==~ '^(?:http?://)??listen\\.jazzradio\\.com/.*$') {		provider = jazz		}				// Check if it's a single pls and if public3, premium*		Matcher diIsPremium = resourceUrl =~ /premium/		Matcher diIsPublic = resourceUrl =~ /public3/		Matcher diIsPls = resourceUrl =~ '^(?:http?://).*\\.pls'				if (diIsPls) {			if (diIsPremium) {				listenKey = resourceUrl =~ '.*\\.pls\\?(.*)'				assert listenKey != null				listenKey = listenKey[0][1].trim()				premiumUrl = resourceUrl =~ '(.*)\\?.*'				assert premiumUrl != null				premiumUrl = premiumUrl[0][1].trim()				resourceUrl = new URL(premiumUrl)				def chPremiumName = premiumUrl =~ '.*/([^/]+)\\.[^\\.]+$'				assert chPremiumName != null				chPremiumName = chPremiumName[0][1].trim()								WebResourceItem PremiumPls = new WebResourceItem(title: chPremiumName, additionalInfo: ['playlist': resourceUrl, 'key': chPremiumName, 'listenKey': listenKey, 'provider': provider])				items << PremiumPls			} else if (diIsPublic) {				def chPublicName = resourceUrl =~ '.*/([^/]+)\\.[^\\.]+$'				assert chPublicName != null				chPublicName = chPublicName[0][1].trim()								WebResourceItem PublicPls = new WebResourceItem(title: chPublicName, additionalInfo: ['playlist': resourceUrl, 'key': chPublicName, 'listenKey': listenKey, 'provider': provider])				items << PublicPls			}		} else {			if (diIsPremium) {				listenKey = resourceUrl =~ '.*listen_key=(.*)'				assert listenKey != null				listenKey = listenKey[0][1].trim()				premiumUrl = resourceUrl =~ '(.*)\\?.*'				assert premiumUrl != null				premiumUrl = premiumUrl[0][1].trim()				resourceUrl = new URL(premiumUrl)			}						// Parse JSON from web			def slurper = new JsonSlurper()			def content = resourceUrl.getText()			def json = slurper.parseText(content)			json.each {				assert it.name != null				assert it.playlist != null				assert it.key != null				WebResourceItem item = new WebResourceItem(title: it.name, additionalInfo: ['playlist': it.playlist, 'key': it.key, 'listenKey': listenKey, 'provider': provider])				items << item			}		}		return new WebResourceContainer(title: 'Di.FM, Sky.FM and JazzRadio.com', items: items)	}		// Channels URL Extractor	ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) { 		String stationPls = item.getAdditionalInfo()['playlist']		String key = item.getAdditionalInfo()['key']		String listenKey = item.getAdditionalInfo()['listenKey']		String provider = item.getAdditionalInfo()['provider']				// Find url		def html = new URL(stationPls).getText()		def linkMatcher = html =~ '(?s)playlist.*?File1=(.*?)Title.'		assert linkMatcher != null		String streamLink = linkMatcher[0][1].trim()				// If Premium, add listen key		if (listenKey) {			streamLink = streamLink + '?' + listenKey		}				// Add thumbnail, if available		URL thumb = thumbnail(key, provider)				return new ContentURLContainer(fileType: MediaFileType.AUDIO, contentUrl: streamLink, thumbnailUrl:thumb, live: true)	}		// Main - Test	static void main(String[] args) {				WebResourceUrlExtractor extractor = new digitallyimported()				assert !extractor.extractorMatches(new URL('http://www.test.fm/public3'))				//assert extractor.extractorMatches(new URL('http://listen.di.fm/public3'))		//assert extractor.extractorMatches(new URL('http://listen.di.fm/premium'))		//assert extractor.extractorMatches(new URL('http://listen.di.fm/premium_high'))		assert extractor.extractorMatches(new URL('http://listen.di.fm/public3/vocalchillout.pls'))				//assert extractor.extractorMatches(new URL('http://listen.sky.fm/public3'))		//assert extractor.extractorMatches(new URL('http://listen.sky.fm/premium'))		//assert extractor.extractorMatches(new URL('http://listen.sky.fm/premium_high'))				//assert extractor.extractorMatches(new URL('http://listen.jazzradio.com/public3'))		//assert extractor.extractorMatches(new URL('http://listen.jazzradio.com/premium_high'))						//WebResourceContainer container = extractor.extractItems(new URL('http://listen.di.fm/public3'), -1)		//WebResourceContainer container = extractor.extractItems(new URL('http://listen.di.fm/premium?listen_key=0000000000000000'), -1)		//WebResourceContainer container = extractor.extractItems(new URL('http://listen.di.fm/premium_high?listen_key=0000000000000000'), -1)		WebResourceContainer container = extractor.extractItems(new URL('http://listen.di.fm/public3/vocalchillout.pls'), -1)				//WebResourceContainer container = extractor.extractItems(new URL('http://listen.sky.fm/public3'), -1)		//WebResourceContainer container = extractor.extractItems(new URL('http://listen.sky.fm/premium?listen_key=0000000000000000'), -1)		//WebResourceContainer container = extractor.extractItems(new URL('http://listen.sky.fm/premium_high?listen_key=0000000000000000'), -1)				//WebResourceContainer container = extractor.extractItems(new URL('http://listen.jazzradio.com/public3'), -1)		//WebResourceContainer container = extractor.extractItems(new URL('http://listen.jazzradio.com/premium_high?listen_key=0000000000000000'), -1)				container.items.each {			ContentURLContainer results = extractor.extractUrl(it, null)			println results		}				//ContentURLContainer results = extractor.extractUrl(container.getItems()[2], null)		//println results	}		// Static thumbnail link	URL thumbnail(String key, String provider) {		if (provider == di) {					switch (key) {				case "deeptech":					return new URL('http://static.audioaddict.com/8/7/d/3/b/2/87d3b2ee913e6ac75882329971d58be4.png')				case "liquiddubstep":					return new URL('http://static.audioaddict.com/d/f/2/5/8/a/df258a92e9d5152cb182b439f1d0eb2b.png')				case "glitchhop":					return new URL('http://static.audioaddict.com/e/a/6/4/7/f/ea647f64af96d86d206bc0a575e4e63b.png')				case "darkdnb":					return new URL('http://static.audioaddict.com/1/5/6/1/b/a/1561ba009eb79c68b9de141f8685c927.png')				case "classiceurodisco":					return new URL('http://static.audioaddict.com/f/9/c/6/c/d/f9c6cdb880da74aa74ec581dc3f09dbd.png')				case "trance":					return new URL('http://static.audioaddict.com/befc1043f0a216128f8570d3664856f7.png')				case "vocaltrance":					return new URL('http://static.audioaddict.com/009b4fcdb032cceee6f3da5efd4a86e9.png')				case "lounge":					return new URL('http://static.audioaddict.com/58f7afca5a6883c063f8642bfd2cef80.png')				case "chillout":					return new URL('http://static.audioaddict.com/8f7ce44aa749a97563c98dc5b69053aa.png')				case "vocalchillout":					return new URL('http://static.audioaddict.com/a5b0bd27de43d04e1da9acf5b8883e85.png')				case "house":					return new URL('http://static.audioaddict.com/6f8a0b3279c24b1c5fa1c6c1397b9b56.png')				case "progressive":					return new URL('http://static.audioaddict.com/fcea7c9d9a16314103a41f66bd6dfd15.png')				case "minimal":					return new URL('http://static.audioaddict.com/5c29e3063f748d156260fb874634b602.png')				case "harddance":					return new URL('http://static.audioaddict.com/a67b19cab6cdb97ec77f8264f9c4c562.png')				case "eurodance":					return new URL('http://static.audioaddict.com/a42ae2b9810acb81c6003915113c7d9d.png')				case "electro":					return new URL('http://static.audioaddict.com/387bfe3c7d50b4edd1408135596a03df.png')				case "techhouse":					return new URL('http://static.audioaddict.com/a1cb226c2170a74ed0fdb4839dafe869.png')				case "psychill":					return new URL('http://static.audioaddict.com/f301e3e597472b3edbf50a770a52c087.png')				case "goapsy":					return new URL('http://static.audioaddict.com/b5b22bf5232f246bf63b25914bd369e3.png')				case "progressivepsy":					return new URL('http://static.audioaddict.com/4aeae25360c3792e8e9fd6f2e5cdf39e.jpg')				case "hardcore":					return new URL('http://static.audioaddict.com/14f1a4484dc88e0df006e9cd71407bcb.png')				case "djmixes":					return new URL('http://static.audioaddict.com/5a0a6603d9a3f151b9eced1629e77d66.png')				case "ambient":					return new URL('http://static.audioaddict.com/9760862fcf5601c05c3581d6c0984128.png')				case "drumandbass":					return new URL('http://static.audioaddict.com/f2ed26a932bdb5cd0a0eac576aebfa3f.png')				case "classictechno":					return new URL('http://static.audioaddict.com/ad112b71e9682c79343a4df45d419297.png')				case "epictrance":					return new URL('http://static.audioaddict.com/5a76739725cd2106a3e2f30a1461a9bd.jpg')				case "ukgarage":					return new URL('http://static.audioaddict.com/c0ce1fbfe33a144e298d1bbec53406a3.png')				case "breaks":					return new URL('http://static.audioaddict.com/5fe8da68c08afeba771f1c0a5ba6bc2f.png')				case "cosmicdowntempo":					return new URL('http://static.audioaddict.com/e98aea320629ce07814e0546f7c39ba1.png')				case "techno":					return new URL('http://static.audioaddict.com/cedaa3b495a451bdd6ee4b21311e155c.png')				case "soulfulhouse":					return new URL('http://static.audioaddict.com/950ff823b9989f18f19ba65fb149fcad.png')				case "deephouse":					return new URL('http://static.audioaddict.com/8dd90c88b4ee5399e6182204a2ede8ed.jpg')				case "tribalhouse":					return new URL('http://static.audioaddict.com/4af36061eb3e97a0aa21b746b51317dd.png')				case "funkyhouse":					return new URL('http://static.audioaddict.com/45d5aa9e246fd59fe03e601171059581.png')				case "deepnudisco":					return new URL('http://static.audioaddict.com/3896ecff86795302304c64386ff2c5db.png')				case "spacemusic":					return new URL('http://static.audioaddict.com/4531d1656bc302d4f1898f779a988c17.png')				case "hardstyle":					return new URL('http://static.audioaddict.com/b27a7b020806ce4428307b30b44734ec.png')				case "chilloutdreams":					return new URL('http://static.audioaddict.com/7a0a070cca01976ea62c9e1c5a19e9b1.png')				case "liquiddnb":					return new URL('http://static.audioaddict.com/75b2b5e697e7948f5fcd64a1c54f3f72.png')				case "classiceurodance":					return new URL('http://static.audioaddict.com/a272766a55dc1d3c5b63e688d7a3d0de.png')				case "handsup":					return new URL('http://static.audioaddict.com/9d04d9b20de5378994fa8653a1dc69f3.jpg')				case "club":					return new URL('http://static.audioaddict.com/6620a82bb6a6d0bc281260645b996b0a.png')				case "classictrance":					return new URL('http://static.audioaddict.com/53906dc786e7f3d55536defca56a4b5f.png')				case "classicvocaltrance":					return new URL('http://static.audioaddict.com/6c59bb5709a2e2ecae99765d64ce57e6.png')				case "dubstep":					return new URL('http://static.audioaddict.com/e0614d304c8fd5879a1278dd626d8769.png')				case "clubdubstep":					return new URL('http://static.audioaddict.com/29b1b727e81f9dc1c6ca40926ac8ae34.jpg')				case "discohouse":					return new URL('http://static.audioaddict.com/0ea9396414430256ffb76cd6148bf88a.png')				case "futuresynthpop":					return new URL('http://static.audioaddict.com/f4b0f3c30b34cf76de0955652ae5664a.png')				case "latinhouse":					return new URL('http://static.audioaddict.com/fb8908953ab95d2f01402660e2cc0883.png')				case "oldschoolacid":					return new URL('http://static.audioaddict.com/7edf76e784f740c1a20904309bbc7080.png')				case "chiptunes":					return new URL('http://static.audioaddict.com/ab17e2f15ebe382d78d744726408b668.png')			}		}		if (provider == sky) {			switch (key) {				case "hit90s":					return new URL('http://static.audioaddict.com/2/4/8/7/d/6/2487d65f7b584e92c73f5fbb3d6cb979.png')				case "cafedeparis":					return new URL('http://static.audioaddict.com/3/0/6/2/3/4/3062348e97fe268f62ba94ccbcfdcc57.png')				case "mellowjazz":					return new URL('http://static.audioaddict.com/c/4/a/7/e/c/c4a7ec91601ac6ce18859c2edeff9c80.png')				case "smoothjazz":					return new URL('http://static.audioaddict.com/ea944543ab6247d58e1703d84e451e4f.png')				case "lovemusic":					return new URL('http://static.audioaddict.com/9feee3db11b67dee318c8f36a99adb9b.png')				case "tophits":					return new URL('http://static.audioaddict.com/a9778d4dec931485c25f5ac182ac71e2.png')				case "the80s":					return new URL('http://static.audioaddict.com/1421021696b692c52f8d753925d1668a.png')				case "smoothlounge":					return new URL('http://static.audioaddict.com/8a8c05b2da5d78ddaf9e453236e311ff.jpg')				case "newage":					return new URL('http://static.audioaddict.com/ee90d885488f0d224c9cabe5d2ea770b.png')				case "solopiano":					return new URL('http://static.audioaddict.com/657f189ce01b74b7734063154775ca31.png')				case "relaxation":					return new URL('http://static.audioaddict.com/df99e575070665e78685364ce35a26b8.png')				case "classical":					return new URL('http://static.audioaddict.com/e3302f3ef1f85c53f3a13d0209102b26.png')				case "80srock":					return new URL('http://static.audioaddict.com/3318d27fbfcf6c699fe235e6f1ceb467.png')				case "softrock":					return new URL('http://static.audioaddict.com/3d79cb01a53e1795728d112c1bb00e0b.jpg')				case "poprock":					return new URL('http://static.audioaddict.com/c2bf1bfc843db7bc6ccf7563bd5ade7f.png')				case "modernrock":					return new URL('http://static.audioaddict.com/cdcf2c3754d96c41b8bcd81414451770.jpg')				case "hardrock":					return new URL('http://static.audioaddict.com/7d3e6634592359e2a0c1d6e5f3f5ddaf.jpg')				case "metal":					return new URL('http://static.audioaddict.com/9be3c5b65f9274df72b78b6ecddf5bb2.png')				case "modernblues":					return new URL('http://static.audioaddict.com/61457ec9c9b71e483c67b8482c010403.png')				case "smoothjazz247":					return new URL('http://static.audioaddict.com/4cb303531bcbff5ef8b61dbfe995568c.png')				case "compactdiscoveries":					return new URL('http://static.audioaddict.com/630a58761c8b70dd0f1af9ebb5c339c1.jpg')				case "vocalnewage":					return new URL('http://static.audioaddict.com/09885117eb43050f5a64e790a684426d.png')				case "nature":					return new URL('http://static.audioaddict.com/7501be44c9536cbd48968b2d7a2f4d81.png')				case "soundtracks":					return new URL('http://static.audioaddict.com/7b648b3c6789173a12666a63d421aa96.png')				case "relaxingexcursions":					return new URL('http://static.audioaddict.com/9f0f2fa09ba90c3947e945b62c8c6e99.png')				case "hit70s":					return new URL('http://static.audioaddict.com/6fe772afcb2ea44eab2048f1f60af18d.png')				case "ska":					return new URL('http://static.audioaddict.com/24ca2ef63079535f489606143b81ef0c.png')				case "oldies":					return new URL('http://static.audioaddict.com/b2f77e0f416e1396721b44f9f4b73374.png')				case "dreamscapes":					return new URL('http://static.audioaddict.com/8ca99e36c4854358d1ce76c30ccae16a.png')				case "classicalpianotrios":					return new URL('http://static.audioaddict.com/ae73ffca4235946a6bc958609b3632da.png')				case "guitar":					return new URL('http://static.audioaddict.com/47e1f6acc1b1fd8947eb63053389c228.png')				case "country":					return new URL('http://static.audioaddict.com/25bc8f07c1cfd7d90eea968724105082.png')				case "rootsreggae":					return new URL('http://static.audioaddict.com/cbf2c683fa84e16f6a03a178070d32cb.png')				case "bossanova":					return new URL('http://static.audioaddict.com/42b7913c019bbe47ee258d13a7dbf5bb.png')				case "vocalsmoothjazz":					return new URL('http://static.audioaddict.com/beb3e04b65b282052419bd15c81e1be4.png')				case "uptemposmoothjazz":					return new URL('http://static.audioaddict.com/16f9c144baa98176ab4f98dc3538adf4.png')				case "datempolounge":					return new URL('http://static.audioaddict.com/9145b6ea36ca63b0911dc6c537de89cb.png')				case "pianojazz":					return new URL('http://static.audioaddict.com/3a78648bbc729bd4dc9ca944ce89d0df.png')				case "salsa":					return new URL('http://static.audioaddict.com/01e8dabaa5c29e58b7f6515d309481f5.png')				case "world":					return new URL('http://static.audioaddict.com/a2ffcb17080207ca578d00f5c7eff1f0.png')				case "romantica":					return new URL('http://static.audioaddict.com/7e66489ebd3e3229d3fdfd10e950d262.png')				case "classicrock":					return new URL('http://static.audioaddict.com/243efc74a39092c1b2c1f5eb3b6ee0e2.png')				case "altrock":					return new URL('http://static.audioaddict.com/4c1e38925a1d195686c180d7fdd355bb.png')				case "indierock":					return new URL('http://static.audioaddict.com/3c1d60925ae8dac00ef4da3beaa7d371.png')				case "dancehits":					return new URL('http://static.audioaddict.com/cdb89061045f4207b909558ca01b8637.png')				case "urbanjamz":					return new URL('http://static.audioaddict.com/05f8add3c89ba75d1b1dfca9cc8e5df9.png')				case "poppunk":					return new URL('http://static.audioaddict.com/14dbce26651d1c8f7703794c8e730227.png')				case "classicrap":					return new URL('http://static.audioaddict.com/c54b89c96b6917acf4ec3ddd9d8e5f7c.png')				case "bebop":					return new URL('http://static.audioaddict.com/3df6292d6a6cbc2b04d007703ab2f7b2.png')				case "jazzclassics":					return new URL('http://static.audioaddict.com/30b34af272931d0e032f148a013439dd.png')				case "americansongbook":					return new URL('http://static.audioaddict.com/3fbd5add268ebd2aff68bf963ea59660.png')				case "beatles":					return new URL('http://static.audioaddict.com/b8a4f059a9a05a7c99a646d4af7d1d28.png')				case "jpop":					return new URL('http://static.audioaddict.com/61251c16fe02215ab58207577efd71d0.png')				case "clubbollywood":					return new URL('http://static.audioaddict.com/ac488cfbc1ddcf62947b71bc51a7b808.png')				case "christian":					return new URL('http://static.audioaddict.com/9ed827ddee44c35e34b9de2bdf425048.png')			}		}				if (provider == jazz) {			switch (key) {				case "bassjazz":					return new URL('http://static.audioaddict.com/0ecb36a21b56961dc17a4238bdbc8ef4.png')				case "vibraphonejazz":					return new URL('http://static.audioaddict.com/f6ad2772b240e4b7aebe784bef8714dc.png')				case "smoothjazz247":					return new URL('http://static.audioaddict.com/911ca46b66b1c50ad6167dd1da183fb3.png')				case "currentjazz":					return new URL('http://static.audioaddict.com/7b9f423bb312b2775fd3678fe6c3d4da.png')				case "gypsyjazz":					return new URL('http://static.audioaddict.com/0c25c18afdee7301a9772a448dbeb24a.png')				case "pariscafe":					return new URL('http://static.audioaddict.com/a2b045b0147f9125d1b1b9bd8ae6a72e.png')				case "trumpetjazz":					return new URL('http://static.audioaddict.com/420798739106bbacd1c38c931214cee5.png')				case "saxophonejazz":					return new URL('http://static.audioaddict.com/d7e929bb8cce04c5fe8062352a20f31c.png')				case "cooljazz":					return new URL('http://static.audioaddict.com/7bbe970517a8140c10e2bfcebed0dd8a.png')				case "classicjazz":					return new URL('http://static.audioaddict.com/6f05681fe275e06e2ce0a5231190b1b4.png')				case "mellowjazz":					return new URL('http://static.audioaddict.com/4f62e86dd8514028ade4b204050d6b79.png')				case "smoothjazz":					return new URL('http://static.audioaddict.com/b7af4587ffcff49c7930ac88fcf9f711.png')				case "straightahead":					return new URL('http://static.audioaddict.com/16b5f5fa7940f687d8003119f6506cdc.png')				case "pianojazz":					return new URL('http://static.audioaddict.com/adad09d59c4f7348b1148cc9791636f8.png')				case "guitarjazz":					return new URL('http://static.audioaddict.com/d675746d1d4f83fc54a31a7d21748ea0.png')				case "bebop":					return new URL('http://static.audioaddict.com/ee8ae50ca460d96b14fe60c06ad4fa76.png')				case "hardbop":					return new URL('http://static.audioaddict.com/b784b141aff28fa00982295555c5fe1d.png')				case "pianotrios":					return new URL('http://static.audioaddict.com/7c22f01344d1950da09a0ff8186593cb.png')				case "bossanova":					return new URL('http://static.audioaddict.com/f37ec4c15239f47cc62f5102102c7926.png')				case "fusionlounge":					return new URL('http://static.audioaddict.com/527213685ef138ca5ea6c3f71bbb8531.png')				case "vocaljazz":					return new URL('http://static.audioaddict.com/464a58cef2d07a3c19b3cd6d4b540a0a.png')				case "smoothvocals":					return new URL('http://static.audioaddict.com/9df076d503ce55eec902a10e2d852925.png')				case "vocallegends":					return new URL('http://static.audioaddict.com/036f741129e25fe38ab82efe6a6ab0e4.png')				case "smoothuptempo":					return new URL('http://static.audioaddict.com/9f95e88e85575b2cbdab1c4def14a72d.png')				case "swingnbigband":					return new URL('http://static.audioaddict.com/f5b869b49b939ad3d862c4e1c49f956b.png')				case "latinjazz":					return new URL('http://static.audioaddict.com/80189d153dd38df150f98c171f443719.png')				case "timelessclassics":					return new URL('http://static.audioaddict.com/614b9e8f72ed053e5cac66ee7f9c23b0.png')				case "sinatrastyle":					return new URL('http://static.audioaddict.com/6232f6891797b8435ba4fc8833352c6b.png')				case "blues":					return new URL('http://static.audioaddict.com/7eb6e8f021df91680057969b53a8fac3.png')				case "avantgarde":					return new URL('http://static.audioaddict.com/70edddf34bc4617bfae510bfbcffd93c.png')				case "smoothlounge":					return new URL('http://static.audioaddict.com/8a8c05b2da5d78ddaf9e453236e311ff.jpg')			}		}				URL diUrl = null		def logoMatcher = null		def pattern = null				// Exception for jazzradio.com		if (provider == jazz) {			diUrl = new URL(provider)			pattern = '<a href="/' + key + '\" (?:.*)? src=\"(.*?)\" title='		} else {			diUrl = new URL(provider + key)			pattern = 'id=\"logo\" src=\"(.*?)\" title='		}				def diHtml = diUrl.getText()		logoMatcher = diHtml =~ pattern				if (logoMatcher) {			logoMatcher = logoMatcher[0][1].trim()			log('Found missing thumbnail. Consider adding the following to the script:')			log('case \"' + key + '\":')			log ('	return new URL(\'' + logoMatcher + '\')')			//println 'case \"' + key + '\":'			//println '	return new URL(\'' + logoMatcher + '\')'			return new URL(logoMatcher)		} else {			log('No thumbnail found for key: ' + key + '   Provider: ' + provider)			//println 'No thumbnail found for key: ' + key + '   Provider: ' + provider			return null		}	}}