scala-news-reader

rss/atom news reader in scala

git clone https://9o.is/git/scala-news-reader.git

VideoInfo.scala

(2090B)


      1 package com.joereader.lib
      2 
      3 import dispatch._
      4 import xml._
      5 
      6 import concurrent.Future
      7 import concurrent.ExecutionContext.Implicits.global
      8 
      9 /**
     10  * Video information of certain video service providers.
     11  * Supports Youtube, Vimeo.
     12  * Can only get video duration, but easily extensible.
     13  */
     14 abstract class VideoInfo {
     15   protected def name: String
     16   protected def req(id: String): Req
     17 
     18   def duration(id: String): Future[Either[String, Int]]
     19 }
     20 
     21 abstract class VideoInfoXML extends VideoInfo {
     22 
     23   protected def extract[T](id: String, extractFunc: Elem => Either[String, T]): Future[Either[String, T]] =
     24     for (xmlEither <- getXML(req(id)))
     25       yield for {
     26       xml <- xmlEither.right
     27       out <- extractFunc(xml).right
     28     } yield out
     29 
     30   private def getXML(req: Req): Future[Either[String, Elem]] = {
     31     val res = Http(req OK as.xml.Elem).either
     32 
     33     for (e <- res.left)
     34       yield s"Can't connect to ${name}: \n ${e.getMessage}"
     35   }
     36 
     37   protected def node2Int(node: NodeSeq)(attr: String): Either[String, Int] =
     38     (for (elem <- node)
     39       yield elem.text.toInt).headOption.toRight {
     40       s"${attr} is missing in ${name} service response"
     41     }
     42 }
     43 
     44 object YoutubeVideoInfo extends VideoInfoXML {
     45   override def name = "youtube"
     46 
     47   override def req(id: String) =
     48     url("https://gdata.youtube.com/feeds/api/videos/" + id) <<? Map("v" -> "2")
     49 
     50   override def duration(id: String) = extract[Int](id, {
     51     xml: Elem =>
     52       node2Int(xml \\ "duration" \ "@seconds")("duration")
     53   })
     54 }
     55 
     56 object VimeoVideoInfo extends VideoInfoXML {
     57   override def name = "vimeo"
     58 
     59   override def req(id: String) =
     60     url("http://vimeo.com/api/v2/video/" + id + ".xml")
     61 
     62   override def duration(id: String) = extract[Int](id, {
     63     xml: Elem =>
     64       node2Int(xml \\ "duration")("duration")
     65   })
     66 }
     67 
     68 object VideoService extends Enumeration {
     69   type VideoService = Value
     70   val Youtube = Value(YoutubeVideoInfo)
     71   val Vimeo = Value(VimeoVideoInfo)
     72 
     73   class VideoServiceVal(val video: VideoInfo) extends Val(nextId)
     74 
     75   protected final def Value(info: VideoInfo): VideoServiceVal =
     76     new VideoServiceVal(info)
     77 }