import groovy.json.JsonSlurper import org.serviio.library.metadata.* import org.serviio.library.online.* import org.serviio.util.* import static java.util.Calendar.* /******************************************************************** * Dailymotion plugin for Serviio * * @author Mandar Hawaldar * * URL to use as video webresource: http://videotanker.co/player/embed_player.php?vid==ix8jh6mvfh1ih * * Version: * V1.0: - Jan 21, 2014 * ********************************************************************/ class Dailymotion extends WebResourceUrlExtractor { final VALID_RESOURCE_URL = 'http://.*dailymotion.(?:co|com)/video/' final VID_EXTRACTOR = '^.+/video/([^_/]+)_?([^/]+)?$' final TITLE = 'Dailymotion' final MY_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.1' String getExtractorName() { return 'Dailymotion.groovy' } boolean extractorMatches(URL resourceURL) { def urlval = resourceURL.toString() =~ VALID_RESOURCE_URL log(String.format("extractorMatches %s - %d", resourceURL.toString(), urlval.count)) if (urlval.count > 0) { return true } else { return false } } /**/ void write_to_log( String text ) { log(TITLE + ' - ' + text) } /**/ public int getVersion() { return 1.0 } Boolean URLExists(URL fileURL){ if(((HttpURLConnection) fileURL.openConnection()).getResponseCode() == 404){ return false } return true } WebResourceContainer extractItems(URL resourceURL, int maxItemsToRetrieve) { List items = [] write_to_log(String.format("extractItems - %s", resourceURL)) def itemsCount = 0 def videoTitle if (URLExists(resourceURL) == false) { write_to_log("Invalid Resource URL") return null } items << new WebResourceItem( title: videoTitle, additionalInfo: [ channelURL: resourceURL, cacheKey: TITLE + ' ' + videoTitle ]) write_to_log(String.format("extractItems Returning items.size()=[%d] \n", items.size())) return new WebResourceContainer(title: TITLE, items: items) } protected String getMediaId(String resourceURL) { def mediaID def vidMatcher = resourceURL =~ VID_EXTRACTOR def vidCount = vidMatcher.count write_to_log(String.format("getMediaId Found #%d VIDEO IDs", vidCount)) if (vidCount > 0){ mediaID = vidMatcher[0][1] write_to_log(String.format("getMediaId mediaID=[%s]", mediaID)) } return mediaID } protected String getMediaId(URL resourceURL) { return getMediaId(resourceURL.toString()) } protected ContentURLContainer extractUrl(WebResourceItem webResourceItem, PreferredQuality preferredQuality) { write_to_log(String.format("extractUrl: channelURL=[%s]", webResourceItem.getAdditionalInfo().get("channelURL"))) if(log.isDebugEnabled()){ log(String.format("Staring video URL extraction for [%s]", webResourceItem.getAdditionalInfo().get("videoPageURL"))) } try{ def embdVidUrlMatcher def embedFileKey def mediaUrl def channelUrl = webResourceItem.getAdditionalInfo().get("channelURL") write_to_log(String.format("extractUrl: channelUrl=[%s]\n", channelUrl)) def mediaID def webUrl def embedUrlList = [] mediaID = getMediaId(channelUrl) if (mediaID != null){ webUrl = 'http://www.dailymotion.com/embed/video/' + mediaID write_to_log(String.format("extractUrl: webUrl=[%s]", webUrl)) } String embedPageHtml = webUrl.toURL().getText( requestProperties: ['User-Agent': MY_USER_AGENT] ) embdVidUrlMatcher = embedPageHtml =~ '"stream_h264_ld_url":"(.*?)",' if (embdVidUrlMatcher.count > 0 && !embdVidUrlMatcher[0][1].equals("null")){ mediaUrl = URLDecoder.decode(embdVidUrlMatcher[0][1].replaceAll('\\\\/', '/'),'UTF-8') write_to_log(String.format("extractUrl: stream_h264_ld_url mediaUrl=[%s]\n", mediaUrl)) embedUrlList.add(mediaUrl); } embdVidUrlMatcher = embedPageHtml =~ '"stream_h264_url":"(.*?)",' if (embdVidUrlMatcher.count > 0 && !embdVidUrlMatcher[0][1].equals("null")){ mediaUrl = URLDecoder.decode(embdVidUrlMatcher[0][1].replaceAll('\\\\/', '/'),'UTF-8') write_to_log(String.format("extractUrl: stream_h264_url mediaUrl=[%s]\n", mediaUrl)) embedUrlList.add(mediaUrl); } embdVidUrlMatcher = embedPageHtml =~ '"stream_h264_hq_url":"(.*?)",' if (embdVidUrlMatcher.count > 0 && !embdVidUrlMatcher[0][1].equals("null")){ mediaUrl = URLDecoder.decode(embdVidUrlMatcher[0][1].replaceAll('\\\\/', '/'),'UTF-8') write_to_log(String.format("extractUrl: stream_h264_hq_url mediaUrl=[%s]\n", mediaUrl)) embedUrlList.add(mediaUrl); } embdVidUrlMatcher = embedPageHtml =~ '"stream_h264_hd_url":"(.*?)",' if (embdVidUrlMatcher.count > 0 && !embdVidUrlMatcher[0][1].equals("null")){ mediaUrl = URLDecoder.decode(embdVidUrlMatcher[0][1].replaceAll('\\\\/', '/'),'UTF-8') write_to_log(String.format("extractUrl: stream_h264_hd_url mediaUrl=[%s]\n", mediaUrl)) embedUrlList.add(mediaUrl); } def embdThumbUrlMatcher = embedPageHtml =~ '"thumbnail_url":"(.*?)",' def thumbnailUrl if (embdThumbUrlMatcher.count > 0 && !embdThumbUrlMatcher[0][1].equals("null")){ thumbnailUrl = URLDecoder.decode(embdThumbUrlMatcher[0][1].replaceAll('\\\\/', '/'),'UTF-8') write_to_log(String.format("extractUrl: thumbnail_url embedThumbUrl=[%s]\n", thumbnailUrl)) } webResourceItem.setTitle(webResourceItem.getTitle() + ' ' + TITLE) return new ContentURLContainer( contentUrl: URLDecoder.decode(findSuitableQuality(embedUrlList, preferredQuality),'UTF-8'), //thumbnailUrl: webResourceItem.getAdditionalInfo().get("thumbnailURL"), thumbnailUrl: thumbnailUrl, //expiresOn: cal.time, expiresOn: webResourceItem.getAdditionalInfo().get("expiresOn"), expiresImmediately: false, cacheKey : webResourceItem.getAdditionalInfo().get("cacheKey") + ' ' + TITLE, live: false ) }catch (IndexOutOfBoundsException e){ log.error(String.format("%s , Filed to create resource item for URL: %s", getExtractorName(), webResourceItem.getAdditionalInfo().get("videoPageURL")), log.isDebugEnabled()? e:null) } return null } def String findSuitableQuality(List items, PreferredQuality requestedQuality) { log(String.format("findSuitableQuality: requestedQuality[%s]\n", requestedQuality.toString())) if(requestedQuality == PreferredQuality.LOW) { // worst quality, get the first from the list return items.head() } else if (requestedQuality == PreferredQuality.MEDIUM) { // get item from the middle return items.get(Math.floor(items.size()/2).toInteger()) // } else { // best quality, take the last url return items.last() } }// def Date calculateExpTime(String onAirTime){ def onAirHH = 22 def onAirMM = 30 def airTimeMatcher = onAirTime =~ /(\d*):(\d*)/ log(String.format("calculateExpTime airTimeMatcher count # %d", airTimeMatcher.count)) if (airTimeMatcher.count>0){ onAirHH = Integer.parseInt(airTimeMatcher[0][1]) + 12 + 2 onAirMM = Integer.parseInt(airTimeMatcher[0][2]) } //println 'onAir = ' + onAirHH + ':' + onAirMM def todayCal = Calendar.getInstance(TimeZone.getTimeZone("IST")) //todayCal.set 2014, JANUARY, 12 //todayCal.set(year: 2014, month: JANUARY, date: 12, hourOfDay: 11, minute: 30, second: 00) //println todayCal.time def dateFormat = 'yyyy/MM/dd HH:mm z' def todayDate = todayCal.time //println todayDate.format(dateFormat, TimeZone.getTimeZone("EST")) //println todayDate.format(dateFormat, TimeZone.getTimeZone("IST")) def currHH = todayDate.format('HH', TimeZone.getTimeZone("IST")) def currMM = todayDate.format('mm', TimeZone.getTimeZone("IST")) //println 'currHH = ' + Integer.parseInt(currHH) //println 'currMM = ' + Integer.parseInt(currMM) if (Integer.parseInt(currHH) > onAirHH || (Integer.parseInt(currHH) == onAirHH && Integer.parseInt(currMM) > onAirMM)){ // set tomo date-10pm //println 'currHH > ' + onAirHH + ':' onAirMM todayCal.set(hourOfDay: onAirHH, minute: onAirMM, second: 00) //println todayCal.time todayDate = todayCal.time + 1 //println todayDate } else{ // set today's date-10pm todayCal.set(hourOfDay: onAirHH, minute: onAirMM) todayDate = todayCal.time } //println todayDate.format(dateFormat, TimeZone.getTimeZone("EST")) //println todayDate.format(dateFormat, TimeZone.getTimeZone("IST")) return todayDate } static void main(args) { def extractor = new Dailymotion() def WebResourceContainer container println extractor.calculateExpTime("8:30") container = extractor.extractItems( new URL("http://www.dailymotion.com/video/x1ab2pc"), 5) //container = extractor.extractItems( new URL("http://www.divxstage.eu/video/ix8jh6mvfh1ih"), 5) /**/ container.getItems().each { ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.HIGH) println result } /**/ } }