]+>([^<]+)'
title = stationMatcher[0][1]
//println title
}
if (url.contains("-s")) {
WebResourceItem item = new WebResourceItem(title: title, additionalInfo: ['stationUrl':url])
items << item
}
}
}
return new WebResourceContainer(title: pageTitle, items: items)
}
ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {
String stationTitle = item.title
String stationUrl = item.getAdditionalInfo()['stationUrl']
assert stationUrl != null
def idMatcher = stationUrl =~ '-(s\\d+)';
def id = idMatcher[0][1];
def url = "https://opml.radiotime.com/Tune.ashx?id=${id}&render=json&formats=mp3,aac,ogg&partnerId=RadioTime";
def json = new JsonSlurper().parse(new URL(url))
//println(json)
Map jsonResult = (Map) json;
List streams = jsonResult['body']
streams = streams.findAll { it -> it['element'] == 'audio' && it['url'].startsWith('http') }
streams = streams.sort { it -> it['bitrate'].toInteger() }
Map selectedStream = streams.last()
def streamUrl = selectedStream.url
if (selectedStream['playlist_type'])
streamUrl = getUrlFromPlaylist(new URL(selectedStream.url));
return new ContentURLContainer(fileType: MediaFileType.AUDIO, contentUrl: streamUrl, live: true)
}
private String getStreamUrl(Map jsonResult) {
List streams = jsonResult['Streams']
// only get streams that are represented as playlists and are live streams
streams = streams.findAll { it -> it['Type'] == 'Live' && ['MP3','Windows','AAC','Flash'].contains(it['MediaType']) && it['Url'].indexOf('adType') == -1 }
if( streams.size() > 0 ) {
// ignore quality, audio bitrate is too low to make any difference, deliver the best available
streams = streams.sort { it -> it['Bandwidth'].toInteger() }
Map selectedStream = streams.last()
String streamUrl = selectedStream['Url']
boolean hasPlaylist = Boolean.valueOf (selectedStream['HasPlaylist'])
if(hasPlaylist && streamUrl.startsWith("http")) {
return getUrlFromPlaylist(new URL(streamUrl))
} else {
return streamUrl
}
} else {
return null
}
}
/**
* Supports m3u playlists ATM
*/
protected getUrlFromPlaylist(URL playlistUrl) {
assert playlistUrl != null
String playlist = playlistUrl.getText()
if(playlist.toLowerCase().startsWith("
-1 || url.indexOf('.pls') > -1) {
return getUrlFromPlaylist(new URL(url))
}
return url
}
}
static void main(args) {
// this is just to test
TuneIn extractor = new TuneIn()
if (args.length == 1) {
WebResourceContainer container = extractor.extractItems(new URL(args[0]), 5)
println container
container.getItems().each {
ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
println result
}
System.exit(0);
}
assert extractor.extractorMatches( new URL("https://tunein.com/radio/London-United-Kingdom-r100780/?qlc=1") )
assert !extractor.extractorMatches( new URL("http://google.com/feeds/api/standardfeeds/top_rated?time=today") )
WebResourceContainer container = extractor.extractItems( new URL("https://tunein.com/radio/Capital-London-958-s16534/"), -1) // with embedded streams
//WebResourceContainer container = extractor.extractItems( new URL("https://tunein.com/radio/London-United-Kingdom-r100780/?qlc=1"), -1) // with embedded streams
//WebResourceContainer container = extractor.extractItems( new URL("http://tunein.com/radio/search/05301/"), -1) // with external streams
//WebResourceContainer container = extractor.extractItems( new URL("http://tunein.com/radio/Christmas-Holiday-Favorites-s257618/"), -1)
//WebResourceContainer container = extractor.extractItems( new URL("http://tunein.com/radio/Christmas-Radio-s249952/"), -1)
//WebResourceContainer container = extractor.extractItems( new URL("https://tunein.com/search/?query=kiss"), -1)
//WebResourceContainer container = extractor.extractItems( new URL("http://tunein.com/search/?query=doowop"), -1)
//WebResourceContainer container = extractor.extractItems( new URL("https://tunein.com/radio/Radio-Mizrahit-s171349/"), -1)
//WebResourceContainer container = extractor.extractItems( new URL("https://tunein.com/radio/RussianFM-s118244/"), -1)
//WebResourceContainer container = extractor.extractItems( new URL("https://tunein.com/radio/Non-Stop-Radio-1030-s14201/"), -1)
println container
container.getItems().each {
ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
println result
}
}
}