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 }