~ubuntu-branches/ubuntu/trusty/libquvi/trusty

« back to all changes in this revision

Viewing changes to share/lua/website/youtube.lua

  • Committer: Bazaar Package Importer
  • Author(s): Alejandro Garrido Mota
  • Date: 2010-05-16 12:12:51 UTC
  • Revision ID: james.westby@ubuntu.com-20100516121251-oku70h33ycn8m6xe
Tags: upstream-0.2.0
ImportĀ upstreamĀ versionĀ 0.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
--[[
 
2
/* 
 
3
* Copyright (C) 2010 Toni Gundogdu.
 
4
*
 
5
* This file is part of quvi, see http://quvi.googlecode.com/
 
6
*
 
7
* This program is free software: you can redistribute it and/or modify
 
8
* it under the terms of the GNU General Public License as published by
 
9
* the Free Software Foundation, either version 3 of the License, or
 
10
* (at your option) any later version.
 
11
*
 
12
* This program is distributed in the hope that it will be useful,
 
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
* GNU General Public License for more details.
 
16
*
 
17
* You should have received a copy of the GNU General Public License
 
18
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
*/
 
20
]]--
 
21
 
 
22
-- If you make improvements to this script, drop a line. Thanks.
 
23
--   <http://quvi.googlecode.com/>
 
24
 
 
25
--[[
 
26
NOTES
 
27
* This script fetches "video info" first
 
28
  - Advantages: requires less bandwidth, works around sign-in-to-view
 
29
  - Disadvantages: fails frequently for still unknown reason
 
30
* If the above fails
 
31
  - Dump server returned error to stdout as a warning
 
32
  - Fetch and parse video page instead
 
33
  - Advantages: works for most (unrestricted) videos
 
34
  - Disadvantages:
 
35
    - Requires (a lot) more bandwidth
 
36
    - Does not work with videos that require signing-in-to-view
 
37
]]--
 
38
 
 
39
-- These are my formats.
 
40
local lookup = {
 
41
    mobile   = "17", --   3gp
 
42
    sd_270p  = "18", --   480x270
 
43
    sd_360p  = "34", --   640x360
 
44
    hq_480p  = "35", --   854x480
 
45
    hd_720p  = "22", --  1280x720
 
46
    hd_1080p = "37"  -- 1920x1080
 
47
}
 
48
 
 
49
-- Returns script details.
 
50
function ident (page_url)
 
51
    
 
52
    -- This is what I return.
 
53
    local t = {}
 
54
 
 
55
    -- This is my domain.
 
56
    t.domain = "youtube.com"
 
57
 
 
58
    -- This is my formats-string.
 
59
    t.formats = ""
 
60
    for k,_ in pairs (lookup) do
 
61
        t.formats = t.formats .."|".. k
 
62
    end
 
63
    t.formats = "default|best" .. t.formats
 
64
 
 
65
    -- This is my response to "Will you handle this URL?"
 
66
    -- Note that page_url may be nil.
 
67
    if (page_url ~= nil) then
 
68
        page_url = youtubify(page_url)
 
69
    end
 
70
    t.will_handle = (page_url ~= nil and page_url:find(t.domain) ~= nil)
 
71
 
 
72
    -- Here are my details.
 
73
    return t
 
74
 
 
75
end
 
76
 
 
77
-- Fetches video page and parses the video URL.
 
78
function parse (video)
 
79
 
 
80
    -- This is my "host ID".
 
81
    video.host_id = "youtube"
 
82
 
 
83
    -- Page URL.
 
84
    local page_url = youtubify(video.page_url)
 
85
 
 
86
    -- This is my video ID.
 
87
    local _,_,s = page_url:find("v=([%w-_]+)")
 
88
    video.id    = s or error ("no match: video id")
 
89
 
 
90
    -- Fetch and pray.
 
91
    video,t,best = get_video_info(video)
 
92
    if (video.title == nil) then
 
93
        video,t,best = old_faithful(page_url, video)
 
94
    end
 
95
 
 
96
    -- Construct the video URL.
 
97
    local video_url = 
 
98
        string.format(
 
99
            "http://youtube.com/get_video?video_id=%s&t=%s",
 
100
                video.id, quvi.unescape(t))
 
101
 
 
102
    -- Choose correct format ID.
 
103
    if (best == nil and video.requested_format == "best") then
 
104
        print ("  > Warning: Unable to find `best' format. Use `default'.")
 
105
    end
 
106
 
 
107
    local fmt_id = nil
 
108
 
 
109
    if (video.requested_format == "best") then
 
110
        fmt_id = best or fmt_id
 
111
    else
 
112
        for k,v in pairs (lookup) do
 
113
            if (k == video.requested_format) then
 
114
                fmt_id = v
 
115
                break
 
116
            end
 
117
        end
 
118
    end
 
119
 
 
120
    if (fmt_id ~= nil) then
 
121
        video_url = video_url .."&fmt=".. fmt_id
 
122
    end
 
123
 
 
124
    -- Set my video URL.
 
125
    video.url = {video_url}
 
126
 
 
127
    -- Return the updated video properties.
 
128
    return video
 
129
 
 
130
end
 
131
 
 
132
-- Youtube video page URL unwrangler.
 
133
function youtubify (url)
 
134
    url = url:gsub("-nocookie", "")    -- youtube-nocookie.com
 
135
    url = url:gsub("/v/", "/watch?v=") -- embedded
 
136
    return url
 
137
end
 
138
 
 
139
-- The preferred method, uses less bandwidth, fails for some videos.
 
140
-- See also the NOTES above.
 
141
function get_video_info (video)
 
142
 
 
143
    -- Fetch video info.
 
144
    local config_url = string.format(
 
145
        "http://www.youtube.com/get_video_info?&video_id=%s"
 
146
         .. "&el=detailpage&ps=default&eurl=&gl=US&hl=en", video.id)
 
147
 
 
148
    local config = quvi.unescape( quvi.fetch(config_url, "config") )
 
149
 
 
150
    -- Check response. For still unknown reasons, the above
 
151
    -- does not work for all videos that I've tried so far.
 
152
    local _,_,s = config:find("&reason=(.-)[?:&]?$")
 
153
    if (s ~= nil) then
 
154
        print ("  > Warning: get_video_info: " .. s:gsub("+"," "))
 
155
        print ("  > Warning: Revert to fetch video page instead.")
 
156
        return video -- This one's for the Old Faithful.
 
157
    end
 
158
 
 
159
    -- This is my video title.
 
160
    local _,_,s = config:find("&title=(.-)&")
 
161
    video.title = s or error ("no match: video title")
 
162
    video.title = video.title:gsub("+"," ")
 
163
 
 
164
    -- This is my t(oken) param used to construct the video URL.
 
165
    local _,_,s = config:find("&token=(.-)&")
 
166
    local t     = s or error ("no match: token parameter")
 
167
 
 
168
    -- Best format.
 
169
    local _,_,best = config:find("&fmt_map=(%d+)")
 
170
 
 
171
    -- Return parsed details.
 
172
    return video, t, best
 
173
 
 
174
end
 
175
 
 
176
-- Fetch video page from the user specified URL and parse.
 
177
-- See also the NOTES above.
 
178
function old_faithful (page_url, video)
 
179
 
 
180
    -- Fetch video page.
 
181
    local page = quvi.fetch(page_url)
 
182
 
 
183
    -- This is my video title.
 
184
    local _,_,s = page:find('<meta name="title" content="(.-)"')
 
185
    video.title = s or error ("no match: video title")
 
186
 
 
187
    -- This is my t param used to construct the video URL.
 
188
    local _,_,s = page:find('&t=(.-)&')
 
189
    local t     = s or error ("no match: t param")
 
190
 
 
191
    -- Best format
 
192
    local _,_,best = page:find("&fmt_map=(%d+)")
 
193
 
 
194
    -- Return parsed details.
 
195
    return video, t, best
 
196
 
 
197
end
 
198
 
 
199