vibedeck-youtube_it 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +234 -0
 - data/Rakefile +35 -0
 - data/lib/youtube_it/chain_io.rb +76 -0
 - data/lib/youtube_it/client.rb +367 -0
 - data/lib/youtube_it/middleware/faraday_authheader.rb +24 -0
 - data/lib/youtube_it/middleware/faraday_oauth.rb +21 -0
 - data/lib/youtube_it/middleware/faraday_youtubeit.rb +30 -0
 - data/lib/youtube_it/model/author.rb +13 -0
 - data/lib/youtube_it/model/category.rb +11 -0
 - data/lib/youtube_it/model/comment.rb +16 -0
 - data/lib/youtube_it/model/contact.rb +16 -0
 - data/lib/youtube_it/model/content.rb +18 -0
 - data/lib/youtube_it/model/playlist.rb +11 -0
 - data/lib/youtube_it/model/rating.rb +23 -0
 - data/lib/youtube_it/model/subscription.rb +7 -0
 - data/lib/youtube_it/model/thumbnail.rb +17 -0
 - data/lib/youtube_it/model/user.rb +26 -0
 - data/lib/youtube_it/model/video.rb +225 -0
 - data/lib/youtube_it/parser.rb +357 -0
 - data/lib/youtube_it/record.rb +12 -0
 - data/lib/youtube_it/request/base_search.rb +72 -0
 - data/lib/youtube_it/request/error.rb +15 -0
 - data/lib/youtube_it/request/standard_search.rb +43 -0
 - data/lib/youtube_it/request/user_search.rb +47 -0
 - data/lib/youtube_it/request/video_search.rb +102 -0
 - data/lib/youtube_it/request/video_upload.rb +415 -0
 - data/lib/youtube_it/response/video_search.rb +41 -0
 - data/lib/youtube_it/version.rb +4 -0
 - data/lib/youtube_it.rb +75 -0
 - data/test/helper.rb +10 -0
 - data/test/test_chain_io.rb +63 -0
 - data/test/test_client.rb +418 -0
 - data/test/test_field_search.rb +48 -0
 - data/test/test_video.rb +43 -0
 - data/test/test_video_feed_parser.rb +271 -0
 - data/test/test_video_search.rb +141 -0
 - metadata +150 -0
 
| 
         @@ -0,0 +1,225 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # TODO
         
     | 
| 
      
 2 
     | 
    
         
            +
            #  * self atom feed
         
     | 
| 
      
 3 
     | 
    
         
            +
            #  * alternate youtube watch url
         
     | 
| 
      
 4 
     | 
    
         
            +
            #  * comments feedLink
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            class YouTubeIt
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Model
         
     | 
| 
      
 8 
     | 
    
         
            +
                class Video < YouTubeIt::Record
         
     | 
| 
      
 9 
     | 
    
         
            +
                  # Describes the various file formats in which a Youtube video may be
         
     | 
| 
      
 10 
     | 
    
         
            +
                  # made available and allows looking them up by format code number.
         
     | 
| 
      
 11 
     | 
    
         
            +
                  class Format
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @@formats = Hash.new
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    # Instantiates a new video format object.
         
     | 
| 
      
 15 
     | 
    
         
            +
                    #
         
     | 
| 
      
 16 
     | 
    
         
            +
                    # == Parameters
         
     | 
| 
      
 17 
     | 
    
         
            +
                    #   :format_code<Fixnum>:: The Youtube Format code of the object.
         
     | 
| 
      
 18 
     | 
    
         
            +
                    #   :name<Symbol>:: The name of the format
         
     | 
| 
      
 19 
     | 
    
         
            +
                    #
         
     | 
| 
      
 20 
     | 
    
         
            +
                    # == Returns
         
     | 
| 
      
 21 
     | 
    
         
            +
                    #   YouTubeIt::Model::Video::Format: Video format object
         
     | 
| 
      
 22 
     | 
    
         
            +
                    def initialize(format_code, name)
         
     | 
| 
      
 23 
     | 
    
         
            +
                      @format_code = format_code
         
     | 
| 
      
 24 
     | 
    
         
            +
                      @name = name
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                      @@formats[format_code] = self
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                    # Allows you to get the video format for a specific format code.
         
     | 
| 
      
 30 
     | 
    
         
            +
                    #
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # A full list of format codes is available at:
         
     | 
| 
      
 32 
     | 
    
         
            +
                    #
         
     | 
| 
      
 33 
     | 
    
         
            +
                    # http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:content
         
     | 
| 
      
 34 
     | 
    
         
            +
                    #
         
     | 
| 
      
 35 
     | 
    
         
            +
                    # == Parameters
         
     | 
| 
      
 36 
     | 
    
         
            +
                    #   :format_code<Fixnum>:: The Youtube Format code of the object.
         
     | 
| 
      
 37 
     | 
    
         
            +
                    #
         
     | 
| 
      
 38 
     | 
    
         
            +
                    # == Returns
         
     | 
| 
      
 39 
     | 
    
         
            +
                    #   YouTubeIt::Model::Video::Format: Video format object
         
     | 
| 
      
 40 
     | 
    
         
            +
                    def self.by_code(format_code)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @@formats[format_code]
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    # Flash format on YouTube site. All videos are available in this format.
         
     | 
| 
      
 45 
     | 
    
         
            +
                    FLASH = YouTubeIt::Model::Video::Format.new(0, :flash)
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                    # RTSP streaming URL for mobile video playback. H.263 video (176x144) and AMR audio.
         
     | 
| 
      
 48 
     | 
    
         
            +
                    RTSP = YouTubeIt::Model::Video::Format.new(1, :rtsp)
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                    # HTTP URL to the embeddable player (SWF) for this video. This format
         
     | 
| 
      
 51 
     | 
    
         
            +
                    # is not available for a video that is not embeddable.
         
     | 
| 
      
 52 
     | 
    
         
            +
                    SWF = YouTubeIt::Model::Video::Format.new(5, :swf)
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                    # RTSP streaming URL for mobile video playback. MPEG-4 SP video (up to 176x144) and AAC audio.
         
     | 
| 
      
 55 
     | 
    
         
            +
                    THREE_GPP = YouTubeIt::Model::Video::Format.new(6, :three_gpp)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  # *Fixnum*:: Duration of a video in seconds.
         
     | 
| 
      
 59 
     | 
    
         
            +
                  attr_reader :duration
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  # *Boolean*:: Specifies that a video may or may not be 16:9 ratio.
         
     | 
| 
      
 62 
     | 
    
         
            +
                  attr_reader :widescreen
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  # *Boolean*:: Specifies that a video may or may not be embedded on other websites.
         
     | 
| 
      
 65 
     | 
    
         
            +
                  attr_reader :noembed
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  # *Fixnum*:: Specifies the order in which the video appears in a playlist.
         
     | 
| 
      
 68 
     | 
    
         
            +
                  attr_reader :position
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                  # *Boolean*:: Specifies that a video is flagged as adult or not.
         
     | 
| 
      
 71 
     | 
    
         
            +
                  attr_reader :racy
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  # *String*: Specifies a URI that uniquely and permanently identifies the video.
         
     | 
| 
      
 74 
     | 
    
         
            +
                  attr_reader :video_id
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                  # *Time*:: When the video was published on Youtube.
         
     | 
| 
      
 77 
     | 
    
         
            +
                  attr_reader :published_at
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  # *Time*:: When the video's data was last updated.
         
     | 
| 
      
 80 
     | 
    
         
            +
                  attr_reader :updated_at
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  # *Array*:: A array of YouTubeIt::Model::Category objects that describe the videos categories.
         
     | 
| 
      
 83 
     | 
    
         
            +
                  attr_reader :categories
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  # *Array*:: An array of words associated with the video.
         
     | 
| 
      
 86 
     | 
    
         
            +
                  attr_reader :keywords
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  # *String*:: Description of the video.
         
     | 
| 
      
 89 
     | 
    
         
            +
                  attr_reader :description
         
     | 
| 
      
 90 
     | 
    
         
            +
             
     | 
| 
      
 91 
     | 
    
         
            +
                  # *String*:: Title for the video.
         
     | 
| 
      
 92 
     | 
    
         
            +
                  attr_reader :title
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  # *String*:: Description of the video.
         
     | 
| 
      
 95 
     | 
    
         
            +
                  attr_reader :html_content
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  # YouTubeIt::Model::Author:: Information about the YouTube user who owns a piece of video content.
         
     | 
| 
      
 98 
     | 
    
         
            +
                  attr_reader :author
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                  # *Array*:: An array of YouTubeIt::Model::Content objects describing the individual media content data available for this video.  Most, but not all, videos offer this.
         
     | 
| 
      
 101 
     | 
    
         
            +
                  attr_reader :media_content
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  # *Array*:: An array of YouTubeIt::Model::Thumbnail objects that contain information regarding the videos thumbnail images.
         
     | 
| 
      
 104 
     | 
    
         
            +
                  attr_reader :thumbnails
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                  # *String*:: The link to watch the URL on YouTubes website.
         
     | 
| 
      
 107 
     | 
    
         
            +
                  attr_reader :player_url
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  # YouTubeIt::Model::Rating:: Information about the videos rating.
         
     | 
| 
      
 110 
     | 
    
         
            +
                  attr_reader :rating
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  # *Fixnum*:: Number of times that the video has been viewed
         
     | 
| 
      
 113 
     | 
    
         
            +
                  attr_reader :view_count
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                  # *Fixnum*:: Number of times that the video has been favorited
         
     | 
| 
      
 116 
     | 
    
         
            +
                  attr_reader :favorite_count
         
     | 
| 
      
 117 
     | 
    
         
            +
                  
         
     | 
| 
      
 118 
     | 
    
         
            +
                  # *String*:: State of the video (processing, restricted, deleted, rejected and failed)
         
     | 
| 
      
 119 
     | 
    
         
            +
                  attr_reader :state
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  # Geodata
         
     | 
| 
      
 123 
     | 
    
         
            +
                  attr_reader :where
         
     | 
| 
      
 124 
     | 
    
         
            +
                  attr_reader :position
         
     | 
| 
      
 125 
     | 
    
         
            +
                  attr_reader :latitude
         
     | 
| 
      
 126 
     | 
    
         
            +
                  attr_reader :longitude
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  # Videos related to the current video.
         
     | 
| 
      
 129 
     | 
    
         
            +
                  #
         
     | 
| 
      
 130 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 131 
     | 
    
         
            +
                  #   YouTubeIt::Response::VideoSearch
         
     | 
| 
      
 132 
     | 
    
         
            +
                  def related
         
     | 
| 
      
 133 
     | 
    
         
            +
                    YouTubeIt::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/related").parse
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
                  # Video responses to the current video.
         
     | 
| 
      
 137 
     | 
    
         
            +
                  #
         
     | 
| 
      
 138 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 139 
     | 
    
         
            +
                  #   YouTubeIt::Response::VideoSearch
         
     | 
| 
      
 140 
     | 
    
         
            +
                  def responses
         
     | 
| 
      
 141 
     | 
    
         
            +
                    YouTubeIt::Parser::VideosFeedParser.new("http://gdata.youtube.com/feeds/api/videos/#{unique_id}/responses").parse
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  # The ID of the video, useful for searching for the video again without having to store it anywhere.
         
     | 
| 
      
 145 
     | 
    
         
            +
                  # A regular query search, with this id will return the same video.
         
     | 
| 
      
 146 
     | 
    
         
            +
                  #
         
     | 
| 
      
 147 
     | 
    
         
            +
                  # === Example
         
     | 
| 
      
 148 
     | 
    
         
            +
                  #   >> video.unique_id
         
     | 
| 
      
 149 
     | 
    
         
            +
                  #   => "ZTUVgYoeN_o"
         
     | 
| 
      
 150 
     | 
    
         
            +
                  #
         
     | 
| 
      
 151 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 152 
     | 
    
         
            +
                  #   String: The Youtube video id.
         
     | 
| 
      
 153 
     | 
    
         
            +
                  def unique_id
         
     | 
| 
      
 154 
     | 
    
         
            +
                    video_id[/videos\/([^<]+)/, 1] || video_id[/video\:([^<]+)/, 1]
         
     | 
| 
      
 155 
     | 
    
         
            +
                  end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                  # Allows you to check whether the video can be embedded on a webpage.
         
     | 
| 
      
 158 
     | 
    
         
            +
                  #
         
     | 
| 
      
 159 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 160 
     | 
    
         
            +
                  #   Boolean: True if the video can be embedded, false if not.
         
     | 
| 
      
 161 
     | 
    
         
            +
                  def embeddable?
         
     | 
| 
      
 162 
     | 
    
         
            +
                    not @noembed
         
     | 
| 
      
 163 
     | 
    
         
            +
                  end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                  # Allows you to check whether the video is widescreen (16:9) or not.
         
     | 
| 
      
 166 
     | 
    
         
            +
                  #
         
     | 
| 
      
 167 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 168 
     | 
    
         
            +
                  # Boolean: True if the video is (approximately) 16:9, false if not.
         
     | 
| 
      
 169 
     | 
    
         
            +
                  def widescreen?
         
     | 
| 
      
 170 
     | 
    
         
            +
                    @widescreen
         
     | 
| 
      
 171 
     | 
    
         
            +
                  end
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
      
 173 
     | 
    
         
            +
                  # Provides a URL and various other types of information about a video.
         
     | 
| 
      
 174 
     | 
    
         
            +
                  #
         
     | 
| 
      
 175 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 176 
     | 
    
         
            +
                  #   YouTubeIt::Model::Content: Data about the embeddable video.
         
     | 
| 
      
 177 
     | 
    
         
            +
                  def default_media_content
         
     | 
| 
      
 178 
     | 
    
         
            +
                    @media_content.find { |c| c.is_default? }
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  # Gives you the HTML to embed the video on your website.
         
     | 
| 
      
 182 
     | 
    
         
            +
                  #
         
     | 
| 
      
 183 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 184 
     | 
    
         
            +
                  #   String: The HTML for embedding the video on your website.
         
     | 
| 
      
 185 
     | 
    
         
            +
                  def embed_html(width = 425, height = 350)
         
     | 
| 
      
 186 
     | 
    
         
            +
                    <<EDOC
         
     | 
| 
      
 187 
     | 
    
         
            +
            <object width="#{width}" height="#{height}">
         
     | 
| 
      
 188 
     | 
    
         
            +
              <param name="movie" value="#{embed_url}"></param>
         
     | 
| 
      
 189 
     | 
    
         
            +
              <param name="wmode" value="transparent"></param>
         
     | 
| 
      
 190 
     | 
    
         
            +
              <embed src="#{embed_url}" type="application/x-shockwave-flash"
         
     | 
| 
      
 191 
     | 
    
         
            +
               wmode="transparent" width="#{width}" height="#{height}"></embed>
         
     | 
| 
      
 192 
     | 
    
         
            +
            </object>
         
     | 
| 
      
 193 
     | 
    
         
            +
            EDOC
         
     | 
| 
      
 194 
     | 
    
         
            +
                  end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                  # Gives you the HTML to embed the video on your website.
         
     | 
| 
      
 197 
     | 
    
         
            +
                  #
         
     | 
| 
      
 198 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 199 
     | 
    
         
            +
                  # String: The HTML for embedding the video on your website.
         
     | 
| 
      
 200 
     | 
    
         
            +
                  def embed_html_with_width(width = 1280)
         
     | 
| 
      
 201 
     | 
    
         
            +
                    height = (widescreen? ? width * 9/16 : width * 3/4) + 25
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
                    <<EDOC
         
     | 
| 
      
 204 
     | 
    
         
            +
            <object width="#{width}" height="#{height}">
         
     | 
| 
      
 205 
     | 
    
         
            +
            <param name="movie" value="#{embed_url}"></param>
         
     | 
| 
      
 206 
     | 
    
         
            +
            <param name="wmode" value="transparent"></param>
         
     | 
| 
      
 207 
     | 
    
         
            +
            <embed src="#{embed_url}" type="application/x-shockwave-flash"
         
     | 
| 
      
 208 
     | 
    
         
            +
            wmode="transparent" width="#{width}" height="#{height}"></embed>
         
     | 
| 
      
 209 
     | 
    
         
            +
            </object>
         
     | 
| 
      
 210 
     | 
    
         
            +
            EDOC
         
     | 
| 
      
 211 
     | 
    
         
            +
                  end
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                  # The URL needed for embedding the video in a page.
         
     | 
| 
      
 214 
     | 
    
         
            +
                  #
         
     | 
| 
      
 215 
     | 
    
         
            +
                  # === Returns
         
     | 
| 
      
 216 
     | 
    
         
            +
                  #   String: Absolute URL for embedding video
         
     | 
| 
      
 217 
     | 
    
         
            +
                  def embed_url
         
     | 
| 
      
 218 
     | 
    
         
            +
                    @player_url.sub('watch?', '').sub('=', '/').sub('feature/', 'feature=')
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
              end
         
     | 
| 
      
 224 
     | 
    
         
            +
            end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,357 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class YouTubeIt
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Parser #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
                class FeedParser #:nodoc:
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def initialize(content)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    @content = open(content).read
         
     | 
| 
      
 6 
     | 
    
         
            +
                    
         
     | 
| 
      
 7 
     | 
    
         
            +
                  rescue OpenURI::HTTPError => e
         
     | 
| 
      
 8 
     | 
    
         
            +
                    raise OpenURI::HTTPError.new(e.io.status[0],e)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 10 
     | 
    
         
            +
                    @content = content
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def parse
         
     | 
| 
      
 15 
     | 
    
         
            +
                    parse_content @content
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  def parse_videos
         
     | 
| 
      
 19 
     | 
    
         
            +
                    doc = REXML::Document.new(@content)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    videos = []
         
     | 
| 
      
 21 
     | 
    
         
            +
                    doc.elements.each("*/entry") do |video|
         
     | 
| 
      
 22 
     | 
    
         
            +
                      videos << parse_entry(video)
         
     | 
| 
      
 23 
     | 
    
         
            +
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    videos
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                class CommentsFeedParser < FeedParser #:nodoc:
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # return array of comments
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    doc = REXML::Document.new(content.body)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    feed = doc.elements["feed"]
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    comments = []
         
     | 
| 
      
 35 
     | 
    
         
            +
                    feed.elements.each("entry") do |entry|
         
     | 
| 
      
 36 
     | 
    
         
            +
                      comments << parse_entry(entry)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
                    return comments
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 42 
     | 
    
         
            +
                    def parse_entry(entry)
         
     | 
| 
      
 43 
     | 
    
         
            +
                      author = YouTubeIt::Model::Author.new(
         
     | 
| 
      
 44 
     | 
    
         
            +
                        :name => entry.elements["author"].elements["name"].text,
         
     | 
| 
      
 45 
     | 
    
         
            +
                        :uri  => entry.elements["author"].elements["uri"].text,
         
     | 
| 
      
 46 
     | 
    
         
            +
                        :thumbnail_url => entry.elements["media:thumbnail"].attributes["url"]
         
     | 
| 
      
 47 
     | 
    
         
            +
                      )
         
     | 
| 
      
 48 
     | 
    
         
            +
                      YouTubeIt::Model::Comment.new(
         
     | 
| 
      
 49 
     | 
    
         
            +
                        :author    => author,
         
     | 
| 
      
 50 
     | 
    
         
            +
                        :content   => entry.elements["content"].text,
         
     | 
| 
      
 51 
     | 
    
         
            +
                        :published => entry.elements["published"].text,
         
     | 
| 
      
 52 
     | 
    
         
            +
                        :title     => entry.elements["title"].text,
         
     | 
| 
      
 53 
     | 
    
         
            +
                        :updated   => entry.elements["updated "].text,
         
     | 
| 
      
 54 
     | 
    
         
            +
                        :url       => entry.elements["id"].text
         
     | 
| 
      
 55 
     | 
    
         
            +
                      )
         
     | 
| 
      
 56 
     | 
    
         
            +
                    end
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                class PlaylistFeedParser < FeedParser #:nodoc:
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    xml = REXML::Document.new(content.body)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    entry = xml.elements["entry"] || xml.elements["feed"]
         
     | 
| 
      
 64 
     | 
    
         
            +
                    YouTubeIt::Model::Playlist.new(
         
     | 
| 
      
 65 
     | 
    
         
            +
                      :title         => entry.elements["title"].text,
         
     | 
| 
      
 66 
     | 
    
         
            +
                      :summary       => (entry.elements["summary"] || entry.elements["media:group"].elements["media:description"]).text,
         
     | 
| 
      
 67 
     | 
    
         
            +
                      :description   => (entry.elements["summary"] || entry.elements["media:group"].elements["media:description"]).text,
         
     | 
| 
      
 68 
     | 
    
         
            +
                      :playlist_id   => entry.elements["id"].text[/playlist([^<]+)/, 1].sub(':',''),
         
     | 
| 
      
 69 
     | 
    
         
            +
                      :published     => entry.elements["published"] ? entry.elements["published"].text : nil,
         
     | 
| 
      
 70 
     | 
    
         
            +
                      :response_code => content.status,
         
     | 
| 
      
 71 
     | 
    
         
            +
                      :xml           => content.body)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                class PlaylistsFeedParser < FeedParser #:nodoc:
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  # return array of playlist objects
         
     | 
| 
      
 78 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 79 
     | 
    
         
            +
                    doc = REXML::Document.new(content.body)
         
     | 
| 
      
 80 
     | 
    
         
            +
                    feed = doc.elements["feed"]
         
     | 
| 
      
 81 
     | 
    
         
            +
                    
         
     | 
| 
      
 82 
     | 
    
         
            +
                    playlists = []
         
     | 
| 
      
 83 
     | 
    
         
            +
                    feed.elements.each("entry") do |entry|
         
     | 
| 
      
 84 
     | 
    
         
            +
                      playlists << parse_entry(entry)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    end
         
     | 
| 
      
 86 
     | 
    
         
            +
                    return playlists
         
     | 
| 
      
 87 
     | 
    
         
            +
                  end
         
     | 
| 
      
 88 
     | 
    
         
            +
                  
         
     | 
| 
      
 89 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 90 
     | 
    
         
            +
                  
         
     | 
| 
      
 91 
     | 
    
         
            +
                  def parse_entry(entry)
         
     | 
| 
      
 92 
     | 
    
         
            +
                    YouTubeIt::Model::Playlist.new(
         
     | 
| 
      
 93 
     | 
    
         
            +
                      :title         => entry.elements["title"].text,
         
     | 
| 
      
 94 
     | 
    
         
            +
                      :summary       => (entry.elements["summary"] || entry.elements["media:group"].elements["media:description"]).text,
         
     | 
| 
      
 95 
     | 
    
         
            +
                      :description   => (entry.elements["summary"] || entry.elements["media:group"].elements["media:description"]).text,
         
     | 
| 
      
 96 
     | 
    
         
            +
                      :playlist_id   => entry.elements["id"].text[/playlist([^<]+)/, 1].sub(':',''),
         
     | 
| 
      
 97 
     | 
    
         
            +
                      :published     => entry.elements["published"] ? entry.elements["published"].text : nil,
         
     | 
| 
      
 98 
     | 
    
         
            +
                      :response_code => nil,
         
     | 
| 
      
 99 
     | 
    
         
            +
                      :xml           => nil)
         
     | 
| 
      
 100 
     | 
    
         
            +
                  end
         
     | 
| 
      
 101 
     | 
    
         
            +
                end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                class ProfileFeedParser < FeedParser #:nodoc:
         
     | 
| 
      
 104 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    xml = REXML::Document.new(content.body)
         
     | 
| 
      
 106 
     | 
    
         
            +
                    entry = xml.elements["entry"] || xml.elements["feed"]
         
     | 
| 
      
 107 
     | 
    
         
            +
                    YouTubeIt::Model::User.new(
         
     | 
| 
      
 108 
     | 
    
         
            +
                      :age            => entry.elements["yt:age"] ? entry.elements["yt:age"].text : nil,
         
     | 
| 
      
 109 
     | 
    
         
            +
                      :username       => entry.elements["yt:username"] ? entry.elements["yt:username"].text : nil,
         
     | 
| 
      
 110 
     | 
    
         
            +
                      :company        => entry.elements["yt:company"] ? entry.elements["yt:company"].text : nil,
         
     | 
| 
      
 111 
     | 
    
         
            +
                      :gender         => entry.elements["yt:gender"] ? entry.elements["yt:gender"].text : nil,
         
     | 
| 
      
 112 
     | 
    
         
            +
                      :hobbies        => entry.elements["yt:hobbies"] ? entry.elements["yt:hobbies"].text : nil,
         
     | 
| 
      
 113 
     | 
    
         
            +
                      :hometown       => entry.elements["yt:hometown"] ? entry.elements["yt:hometown"].text : nil,
         
     | 
| 
      
 114 
     | 
    
         
            +
                      :location       => entry.elements["yt:location"] ? entry.elements["yt:location"].text : nil,
         
     | 
| 
      
 115 
     | 
    
         
            +
                      :last_login     => entry.elements["yt:statistics"].attributes["lastWebAccess"],
         
     | 
| 
      
 116 
     | 
    
         
            +
                      :join_date      => entry.elements["published"] ? entry.elements["published"].text : nil,
         
     | 
| 
      
 117 
     | 
    
         
            +
                      :movies         => entry.elements["yt:movies"] ? entry.elements["yt:movies"].text : nil,
         
     | 
| 
      
 118 
     | 
    
         
            +
                      :music          => entry.elements["yt:music"] ? entry.elements["yt:music"].text : nil,
         
     | 
| 
      
 119 
     | 
    
         
            +
                      :occupation     => entry.elements["yt:occupation"] ? entry.elements["yt:occupation"].text : nil,
         
     | 
| 
      
 120 
     | 
    
         
            +
                      :relationship   => entry.elements["yt:relationship"] ? entry.elements["yt:relationship"].text : nil,
         
     | 
| 
      
 121 
     | 
    
         
            +
                      :school         => entry.elements["yt:school"] ? entry.elements["yt:school"].text : nil,
         
     | 
| 
      
 122 
     | 
    
         
            +
                      :subscribers    => entry.elements["yt:statistics"].attributes["subscriberCount"],
         
     | 
| 
      
 123 
     | 
    
         
            +
                      :videos_watched => entry.elements["yt:statistics"].attributes["videoWatchCount"],
         
     | 
| 
      
 124 
     | 
    
         
            +
                      :view_count     => entry.elements["yt:statistics"].attributes["viewCount"],
         
     | 
| 
      
 125 
     | 
    
         
            +
                      :upload_views   => entry.elements["yt:statistics"].attributes["totalUploadViews"]
         
     | 
| 
      
 126 
     | 
    
         
            +
                    )
         
     | 
| 
      
 127 
     | 
    
         
            +
                  end
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
                
         
     | 
| 
      
 130 
     | 
    
         
            +
                class SubscriptionFeedParser < FeedParser #:nodoc:
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 133 
     | 
    
         
            +
                    doc = REXML::Document.new(content.body)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    feed = doc.elements["feed"]
         
     | 
| 
      
 135 
     | 
    
         
            +
                    
         
     | 
| 
      
 136 
     | 
    
         
            +
                    subscriptions = []
         
     | 
| 
      
 137 
     | 
    
         
            +
                    feed.elements.each("entry") do |entry|
         
     | 
| 
      
 138 
     | 
    
         
            +
                      subscriptions << parse_entry(entry)
         
     | 
| 
      
 139 
     | 
    
         
            +
                    end
         
     | 
| 
      
 140 
     | 
    
         
            +
                    return subscriptions
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  
         
     | 
| 
      
 143 
     | 
    
         
            +
                  protected
         
     | 
| 
      
 144 
     | 
    
         
            +
                  
         
     | 
| 
      
 145 
     | 
    
         
            +
                  def parse_entry(entry)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    YouTubeIt::Model::Subscription.new(
         
     | 
| 
      
 147 
     | 
    
         
            +
                      :title        => entry.elements["title"].text,
         
     | 
| 
      
 148 
     | 
    
         
            +
                      :id           => entry.elements["id"].text[/subscription([^<]+)/, 1].sub(':',''),
         
     | 
| 
      
 149 
     | 
    
         
            +
                      :published    => entry.elements["published"] ? entry.elements["published"].text : nil
         
     | 
| 
      
 150 
     | 
    
         
            +
                    )
         
     | 
| 
      
 151 
     | 
    
         
            +
                  end
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
                
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                class VideoFeedParser < FeedParser #:nodoc:
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 158 
     | 
    
         
            +
                    doc = REXML::Document.new(content)
         
     | 
| 
      
 159 
     | 
    
         
            +
                    entry = doc.elements["entry"]
         
     | 
| 
      
 160 
     | 
    
         
            +
                    parse_entry(entry)
         
     | 
| 
      
 161 
     | 
    
         
            +
                  end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                protected
         
     | 
| 
      
 164 
     | 
    
         
            +
                  def parse_entry(entry)
         
     | 
| 
      
 165 
     | 
    
         
            +
                    video_id = entry.elements["id"].text
         
     | 
| 
      
 166 
     | 
    
         
            +
                    published_at  = entry.elements["published"] ? Time.parse(entry.elements["published"].text) : nil
         
     | 
| 
      
 167 
     | 
    
         
            +
                    updated_at    = entry.elements["updated"] ? Time.parse(entry.elements["updated"].text) : nil
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                    # parse the category and keyword lists
         
     | 
| 
      
 170 
     | 
    
         
            +
                    categories = []
         
     | 
| 
      
 171 
     | 
    
         
            +
                    keywords = []
         
     | 
| 
      
 172 
     | 
    
         
            +
                    entry.elements.each("category") do |category|
         
     | 
| 
      
 173 
     | 
    
         
            +
                      # determine if  it's really a category, or just a keyword
         
     | 
| 
      
 174 
     | 
    
         
            +
                      scheme = category.attributes["scheme"]
         
     | 
| 
      
 175 
     | 
    
         
            +
                      if (scheme =~ /\/categories\.cat$/)
         
     | 
| 
      
 176 
     | 
    
         
            +
                        # it's a category
         
     | 
| 
      
 177 
     | 
    
         
            +
                        categories << YouTubeIt::Model::Category.new(
         
     | 
| 
      
 178 
     | 
    
         
            +
                                        :term => category.attributes["term"],
         
     | 
| 
      
 179 
     | 
    
         
            +
                                        :label => category.attributes["label"])
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                      elsif (scheme =~ /\/keywords\.cat$/)
         
     | 
| 
      
 182 
     | 
    
         
            +
                        # it's a keyword
         
     | 
| 
      
 183 
     | 
    
         
            +
                        keywords << category.attributes["term"]
         
     | 
| 
      
 184 
     | 
    
         
            +
                      end
         
     | 
| 
      
 185 
     | 
    
         
            +
                    end
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
                    title = entry.elements["title"].text
         
     | 
| 
      
 188 
     | 
    
         
            +
                    html_content = entry.elements["content"] ? entry.elements["content"].text : nil
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                    # parse the author
         
     | 
| 
      
 191 
     | 
    
         
            +
                    author_element = entry.elements["author"]
         
     | 
| 
      
 192 
     | 
    
         
            +
                    author = nil
         
     | 
| 
      
 193 
     | 
    
         
            +
                    if author_element
         
     | 
| 
      
 194 
     | 
    
         
            +
                      author = YouTubeIt::Model::Author.new(
         
     | 
| 
      
 195 
     | 
    
         
            +
                                 :name => author_element.elements["name"].text,
         
     | 
| 
      
 196 
     | 
    
         
            +
                                 :uri => author_element.elements["uri"].text)
         
     | 
| 
      
 197 
     | 
    
         
            +
                    end
         
     | 
| 
      
 198 
     | 
    
         
            +
                    media_group = entry.elements["media:group"]
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                    # if content is not available on certain region, there is no media:description, media:player or yt:duration
         
     | 
| 
      
 201 
     | 
    
         
            +
                    description = ""
         
     | 
| 
      
 202 
     | 
    
         
            +
                    unless media_group.elements["media:description"].nil?
         
     | 
| 
      
 203 
     | 
    
         
            +
                      description = media_group.elements["media:description"].text
         
     | 
| 
      
 204 
     | 
    
         
            +
                    end
         
     | 
| 
      
 205 
     | 
    
         
            +
             
     | 
| 
      
 206 
     | 
    
         
            +
                    # if content is not available on certain region, there is no media:description, media:player or yt:duration
         
     | 
| 
      
 207 
     | 
    
         
            +
                    duration = 0
         
     | 
| 
      
 208 
     | 
    
         
            +
                    unless media_group.elements["yt:duration"].nil?
         
     | 
| 
      
 209 
     | 
    
         
            +
                      duration = media_group.elements["yt:duration"].attributes["seconds"].to_i
         
     | 
| 
      
 210 
     | 
    
         
            +
                    end
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                    # if content is not available on certain region, there is no media:description, media:player or yt:duration
         
     | 
| 
      
 213 
     | 
    
         
            +
                    player_url = ""
         
     | 
| 
      
 214 
     | 
    
         
            +
                    unless media_group.elements["media:player"].nil?
         
     | 
| 
      
 215 
     | 
    
         
            +
                      player_url = media_group.elements["media:player"].attributes["url"]
         
     | 
| 
      
 216 
     | 
    
         
            +
                    end
         
     | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
                    unless media_group.elements["yt:aspectRatio"].nil?
         
     | 
| 
      
 219 
     | 
    
         
            +
                      widescreen = media_group.elements["yt:aspectRatio"].text == 'widescreen' ? true : false
         
     | 
| 
      
 220 
     | 
    
         
            +
                    end
         
     | 
| 
      
 221 
     | 
    
         
            +
             
     | 
| 
      
 222 
     | 
    
         
            +
                    media_content = []
         
     | 
| 
      
 223 
     | 
    
         
            +
                    media_group.elements.each("media:content") do |mce|
         
     | 
| 
      
 224 
     | 
    
         
            +
                      media_content << parse_media_content(mce)
         
     | 
| 
      
 225 
     | 
    
         
            +
                    end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                    # parse thumbnails
         
     | 
| 
      
 228 
     | 
    
         
            +
                    thumbnails = []
         
     | 
| 
      
 229 
     | 
    
         
            +
                    media_group.elements.each("media:thumbnail") do |thumb_element|
         
     | 
| 
      
 230 
     | 
    
         
            +
                      # TODO: convert time HH:MM:ss string to seconds?
         
     | 
| 
      
 231 
     | 
    
         
            +
                      thumbnails << YouTubeIt::Model::Thumbnail.new(
         
     | 
| 
      
 232 
     | 
    
         
            +
                                      :url    => thumb_element.attributes["url"],
         
     | 
| 
      
 233 
     | 
    
         
            +
                                      :height => thumb_element.attributes["height"].to_i,
         
     | 
| 
      
 234 
     | 
    
         
            +
                                      :width  => thumb_element.attributes["width"].to_i,
         
     | 
| 
      
 235 
     | 
    
         
            +
                                      :time   => thumb_element.attributes["time"])
         
     | 
| 
      
 236 
     | 
    
         
            +
                    end
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
      
 238 
     | 
    
         
            +
                    rating_element = entry.elements["gd:rating"]
         
     | 
| 
      
 239 
     | 
    
         
            +
                    extended_rating_element = entry.elements["yt:rating"]
         
     | 
| 
      
 240 
     | 
    
         
            +
             
     | 
| 
      
 241 
     | 
    
         
            +
                    rating = nil
         
     | 
| 
      
 242 
     | 
    
         
            +
                    if rating_element
         
     | 
| 
      
 243 
     | 
    
         
            +
                      rating_values = {
         
     | 
| 
      
 244 
     | 
    
         
            +
                        :min         => rating_element.attributes["min"].to_i,
         
     | 
| 
      
 245 
     | 
    
         
            +
                        :max         => rating_element.attributes["max"].to_i,
         
     | 
| 
      
 246 
     | 
    
         
            +
                        :rater_count => rating_element.attributes["numRaters"].to_i,
         
     | 
| 
      
 247 
     | 
    
         
            +
                        :average     => rating_element.attributes["average"].to_f
         
     | 
| 
      
 248 
     | 
    
         
            +
                      }
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
                      if extended_rating_element
         
     | 
| 
      
 251 
     | 
    
         
            +
                        rating_values[:likes] = extended_rating_element.attributes["numLikes"].to_i
         
     | 
| 
      
 252 
     | 
    
         
            +
                        rating_values[:dislikes] = extended_rating_element.attributes["numDislikes"].to_i
         
     | 
| 
      
 253 
     | 
    
         
            +
                      end
         
     | 
| 
      
 254 
     | 
    
         
            +
             
     | 
| 
      
 255 
     | 
    
         
            +
                      rating = YouTubeIt::Model::Rating.new(rating_values)
         
     | 
| 
      
 256 
     | 
    
         
            +
                    end
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
                    if (el = entry.elements["yt:statistics"])
         
     | 
| 
      
 259 
     | 
    
         
            +
                      view_count, favorite_count = el.attributes["viewCount"].to_i, el.attributes["favoriteCount"].to_i
         
     | 
| 
      
 260 
     | 
    
         
            +
                    else
         
     | 
| 
      
 261 
     | 
    
         
            +
                      view_count, favorite_count = 0,0
         
     | 
| 
      
 262 
     | 
    
         
            +
                    end
         
     | 
| 
      
 263 
     | 
    
         
            +
             
     | 
| 
      
 264 
     | 
    
         
            +
                    noembed = entry.elements["yt:noembed"] ? true : false
         
     | 
| 
      
 265 
     | 
    
         
            +
                    racy = entry.elements["media:rating"] ? true : false
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                    if where = entry.elements["georss:where"]
         
     | 
| 
      
 268 
     | 
    
         
            +
                      position = where.elements["gml:Point"].elements["gml:pos"].text
         
     | 
| 
      
 269 
     | 
    
         
            +
                      latitude, longitude = position.split(" ")
         
     | 
| 
      
 270 
     | 
    
         
            +
                    end
         
     | 
| 
      
 271 
     | 
    
         
            +
                    
         
     | 
| 
      
 272 
     | 
    
         
            +
                    control = entry.elements["app:control"]
         
     | 
| 
      
 273 
     | 
    
         
            +
                    state = { :name => "published" }
         
     | 
| 
      
 274 
     | 
    
         
            +
                    if control && control.elements["yt:state"]
         
     | 
| 
      
 275 
     | 
    
         
            +
                      state = {
         
     | 
| 
      
 276 
     | 
    
         
            +
                        :name        => control.elements["yt:state"].attributes["name"],
         
     | 
| 
      
 277 
     | 
    
         
            +
                        :reason_code => control.elements["yt:state"].attributes["reasonCode"],
         
     | 
| 
      
 278 
     | 
    
         
            +
                        :help_url    => control.elements["yt:state"].attributes["helpUrl"],
         
     | 
| 
      
 279 
     | 
    
         
            +
                        :copy        => control.elements["yt:state"].text
         
     | 
| 
      
 280 
     | 
    
         
            +
                      }
         
     | 
| 
      
 281 
     | 
    
         
            +
                      
         
     | 
| 
      
 282 
     | 
    
         
            +
                    end
         
     | 
| 
      
 283 
     | 
    
         
            +
             
     | 
| 
      
 284 
     | 
    
         
            +
                    YouTubeIt::Model::Video.new(
         
     | 
| 
      
 285 
     | 
    
         
            +
                      :video_id       => video_id,
         
     | 
| 
      
 286 
     | 
    
         
            +
                      :published_at   => published_at,
         
     | 
| 
      
 287 
     | 
    
         
            +
                      :updated_at     => updated_at,
         
     | 
| 
      
 288 
     | 
    
         
            +
                      :categories     => categories,
         
     | 
| 
      
 289 
     | 
    
         
            +
                      :keywords       => keywords,
         
     | 
| 
      
 290 
     | 
    
         
            +
                      :title          => title,
         
     | 
| 
      
 291 
     | 
    
         
            +
                      :html_content   => html_content,
         
     | 
| 
      
 292 
     | 
    
         
            +
                      :author         => author,
         
     | 
| 
      
 293 
     | 
    
         
            +
                      :description    => description,
         
     | 
| 
      
 294 
     | 
    
         
            +
                      :duration       => duration,
         
     | 
| 
      
 295 
     | 
    
         
            +
                      :media_content  => media_content,
         
     | 
| 
      
 296 
     | 
    
         
            +
                      :player_url     => player_url,
         
     | 
| 
      
 297 
     | 
    
         
            +
                      :thumbnails     => thumbnails,
         
     | 
| 
      
 298 
     | 
    
         
            +
                      :rating         => rating,
         
     | 
| 
      
 299 
     | 
    
         
            +
                      :view_count     => view_count,
         
     | 
| 
      
 300 
     | 
    
         
            +
                      :favorite_count => favorite_count,
         
     | 
| 
      
 301 
     | 
    
         
            +
                      :widescreen     => widescreen,
         
     | 
| 
      
 302 
     | 
    
         
            +
                      :noembed        => noembed,
         
     | 
| 
      
 303 
     | 
    
         
            +
                      :racy           => racy,
         
     | 
| 
      
 304 
     | 
    
         
            +
                      :where          => where,
         
     | 
| 
      
 305 
     | 
    
         
            +
                      :position       => position,
         
     | 
| 
      
 306 
     | 
    
         
            +
                      :latitude       => latitude,
         
     | 
| 
      
 307 
     | 
    
         
            +
                      :longitude      => longitude,
         
     | 
| 
      
 308 
     | 
    
         
            +
                      :state          => state)
         
     | 
| 
      
 309 
     | 
    
         
            +
                  end
         
     | 
| 
      
 310 
     | 
    
         
            +
             
     | 
| 
      
 311 
     | 
    
         
            +
                  def parse_media_content (media_content_element)
         
     | 
| 
      
 312 
     | 
    
         
            +
                    content_url = media_content_element.attributes["url"]
         
     | 
| 
      
 313 
     | 
    
         
            +
                    format_code = media_content_element.attributes["yt:format"].to_i
         
     | 
| 
      
 314 
     | 
    
         
            +
                    format = YouTubeIt::Model::Video::Format.by_code(format_code)
         
     | 
| 
      
 315 
     | 
    
         
            +
                    duration = media_content_element.attributes["duration"].to_i
         
     | 
| 
      
 316 
     | 
    
         
            +
                    mime_type = media_content_element.attributes["type"]
         
     | 
| 
      
 317 
     | 
    
         
            +
                    default = (media_content_element.attributes["isDefault"] == "true")
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
                    YouTubeIt::Model::Content.new(
         
     | 
| 
      
 320 
     | 
    
         
            +
                      :url       => content_url,
         
     | 
| 
      
 321 
     | 
    
         
            +
                      :format    => format,
         
     | 
| 
      
 322 
     | 
    
         
            +
                      :duration  => duration,
         
     | 
| 
      
 323 
     | 
    
         
            +
                      :mime_type => mime_type,
         
     | 
| 
      
 324 
     | 
    
         
            +
                      :default   => default)
         
     | 
| 
      
 325 
     | 
    
         
            +
                  end
         
     | 
| 
      
 326 
     | 
    
         
            +
                end
         
     | 
| 
      
 327 
     | 
    
         
            +
             
     | 
| 
      
 328 
     | 
    
         
            +
                class VideosFeedParser < VideoFeedParser #:nodoc:
         
     | 
| 
      
 329 
     | 
    
         
            +
             
     | 
| 
      
 330 
     | 
    
         
            +
                private
         
     | 
| 
      
 331 
     | 
    
         
            +
                  def parse_content(content)
         
     | 
| 
      
 332 
     | 
    
         
            +
                    videos  = []
         
     | 
| 
      
 333 
     | 
    
         
            +
                    doc     = REXML::Document.new(content)
         
     | 
| 
      
 334 
     | 
    
         
            +
                    feed    = doc.elements["feed"]
         
     | 
| 
      
 335 
     | 
    
         
            +
                    if feed
         
     | 
| 
      
 336 
     | 
    
         
            +
                      feed_id            = feed.elements["id"].text
         
     | 
| 
      
 337 
     | 
    
         
            +
                      updated_at         = Time.parse(feed.elements["updated"].text)
         
     | 
| 
      
 338 
     | 
    
         
            +
                      total_result_count = feed.elements["openSearch:totalResults"].text.to_i
         
     | 
| 
      
 339 
     | 
    
         
            +
                      offset             = feed.elements["openSearch:startIndex"].text.to_i
         
     | 
| 
      
 340 
     | 
    
         
            +
                      max_result_count   = feed.elements["openSearch:itemsPerPage"].text.to_i
         
     | 
| 
      
 341 
     | 
    
         
            +
             
     | 
| 
      
 342 
     | 
    
         
            +
                      feed.elements.each("entry") do |entry|
         
     | 
| 
      
 343 
     | 
    
         
            +
                        videos << parse_entry(entry)
         
     | 
| 
      
 344 
     | 
    
         
            +
                      end
         
     | 
| 
      
 345 
     | 
    
         
            +
                    end
         
     | 
| 
      
 346 
     | 
    
         
            +
                    YouTubeIt::Response::VideoSearch.new(
         
     | 
| 
      
 347 
     | 
    
         
            +
                      :feed_id            => feed_id || nil,
         
     | 
| 
      
 348 
     | 
    
         
            +
                      :updated_at         => updated_at || nil,
         
     | 
| 
      
 349 
     | 
    
         
            +
                      :total_result_count => total_result_count || nil,
         
     | 
| 
      
 350 
     | 
    
         
            +
                      :offset             => offset || nil,
         
     | 
| 
      
 351 
     | 
    
         
            +
                      :max_result_count   => max_result_count || nil,
         
     | 
| 
      
 352 
     | 
    
         
            +
                      :videos             => videos)
         
     | 
| 
      
 353 
     | 
    
         
            +
                  end
         
     | 
| 
      
 354 
     | 
    
         
            +
                end
         
     | 
| 
      
 355 
     | 
    
         
            +
              end
         
     | 
| 
      
 356 
     | 
    
         
            +
            end
         
     | 
| 
      
 357 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class YouTubeIt
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Request #:nodoc:
         
     | 
| 
      
 3 
     | 
    
         
            +
                class BaseSearch #:nodoc:
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_reader :url
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  private
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def base_url
         
     | 
| 
      
 9 
     | 
    
         
            +
                    "http://gdata.youtube.com/feeds/api/"
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def set_instance_variables( variables )
         
     | 
| 
      
 13 
     | 
    
         
            +
                    variables.each do |key, value|
         
     | 
| 
      
 14 
     | 
    
         
            +
                      name = key.to_s
         
     | 
| 
      
 15 
     | 
    
         
            +
                      instance_variable_set("@#{name}", value) if respond_to?(name)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    end
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def build_query_params(params)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    qs = params.to_a.map { | k, v | v.nil? ? nil : "#{YouTubeIt.esc(k)}=#{YouTubeIt.esc(v)}" }.compact.sort.join('&')
         
     | 
| 
      
 21 
     | 
    
         
            +
                    qs.empty? ? '' : (@dev_key ? "?#{qs}&key=#{@dev_key}" : "?#{qs}")
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                module FieldSearch
         
     | 
| 
      
 27 
     | 
    
         
            +
                  def default_fields
         
     | 
| 
      
 28 
     | 
    
         
            +
                    "id,updated,openSearch:totalResults,openSearch:startIndex,openSearch:itemsPerPage"
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def fields_to_params(fields)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    return "" unless fields
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                    fields_param = [default_fields]
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    if fields[:recorded]
         
     | 
| 
      
 37 
     | 
    
         
            +
                      if fields[:recorded].is_a? Range
         
     | 
| 
      
 38 
     | 
    
         
            +
                        fields_param << "entry[xs:date(yt:recorded) > xs:date('#{formatted_date(fields[:recorded].first)}') and xs:date(yt:recorded) < xs:date('#{formatted_date(fields[:recorded].last)}')]"
         
     | 
| 
      
 39 
     | 
    
         
            +
                      else
         
     | 
| 
      
 40 
     | 
    
         
            +
                        fields_param << "entry[xs:date(yt:recorded) = xs:date('#{formatted_date(fields[:recorded])}')]"
         
     | 
| 
      
 41 
     | 
    
         
            +
                      end
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    if fields[:published]
         
     | 
| 
      
 45 
     | 
    
         
            +
                      if fields[:published].is_a? Range
         
     | 
| 
      
 46 
     | 
    
         
            +
                        fields_param << "entry[xs:dateTime(published) > xs:dateTime('#{formatted_date(fields[:published].first)}T00:00:00') and xs:dateTime(published) < xs:dateTime('#{formatted_date(fields[:published].last)}T00:00:00')]"
         
     | 
| 
      
 47 
     | 
    
         
            +
                      else
         
     | 
| 
      
 48 
     | 
    
         
            +
                        fields_param << "entry[xs:date(published) = xs:date('#{formatted_date(fields[:published])}')]"
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    if fields[:view_count]
         
     | 
| 
      
 53 
     | 
    
         
            +
                      fields_param << "entry[yt:statistics/@viewCount > #{fields[:view_count]}]"
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                    return "&fields=#{URI.escape(fields_param.join(","))}"
         
     | 
| 
      
 58 
     | 
    
         
            +
                  end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                  #youtube taked dates that look like 'YYYY-MM-DD'
         
     | 
| 
      
 61 
     | 
    
         
            +
                  def formatted_date(date)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    return date if date.is_a? String
         
     | 
| 
      
 63 
     | 
    
         
            +
                    if date.respond_to? :strftime
         
     | 
| 
      
 64 
     | 
    
         
            +
                      date.strftime("%Y-%m-%d")
         
     | 
| 
      
 65 
     | 
    
         
            +
                    else
         
     | 
| 
      
 66 
     | 
    
         
            +
                      ""
         
     | 
| 
      
 67 
     | 
    
         
            +
                    end
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
              end
         
     | 
| 
      
 71 
     | 
    
         
            +
            end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class UploadError < YouTubeIt::Error
         
     | 
| 
      
 2 
     | 
    
         
            +
              attr_reader :code
         
     | 
| 
      
 3 
     | 
    
         
            +
              def initialize(msg, code = 0)
         
     | 
| 
      
 4 
     | 
    
         
            +
                super(msg)
         
     | 
| 
      
 5 
     | 
    
         
            +
                @code = code
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            class AuthenticationError < YouTubeIt::Error
         
     | 
| 
      
 10 
     | 
    
         
            +
              attr_reader :code
         
     | 
| 
      
 11 
     | 
    
         
            +
              def initialize(msg, code = 0)
         
     | 
| 
      
 12 
     | 
    
         
            +
                super(msg)
         
     | 
| 
      
 13 
     | 
    
         
            +
                @code = code
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     |