Skip to content

Instantly share code, notes, and snippets.

@ste-lam
Last active April 12, 2020 18:02
Show Gist options
  • Save ste-lam/5339ef566c94fcd8cb43 to your computer and use it in GitHub Desktop.
Save ste-lam/5339ef566c94fcd8cb43 to your computer and use it in GitHub Desktop.
local json = require("dkjson")
local client = "jzkbprff40iqj646a697cyrvl0zt2m6"
local urls = {
vod = {
token = "${scheme}://api.twitch.tv/api/vods/${user}/access_token?client_id=${client}",
playlist = "${scheme}://usher.ttvnw.net/vod/${user}.m3u8?allow_source=true&allow_spectre=true&type=any&nauth=${token}&nauthsig=${sig}"
},
hls = {
token = "${scheme}://api.twitch.tv/api/channels/${user}/access_token?client_id=${client}",
playlist = "${scheme}://usher.ttvnw.net/api/channel/hls/${user}.m3u8?allow_source=true&allow_spectre=true&type=any&token=${token}&sig=${sig}"
}
}
function ends_with(s, test)
return s:sub(-#test) == test
end
function begins_with(s, test)
return s:sub(1, #test) == test
end
function matches(begin)
return ends_with(("."..vlc.path.."/"):match("^([^/]+)/"), begin)
end
-- QND: hacked m3u-parser for twitch
function m3u_parse(url, meta)
local m3u_parse_line = function (line, map)
local tag, data = line:match("^#([^:]*:)(.*)")
for k, v in ("," .. data):gmatch("%s*,%s*([^=]+)=\"([^\"]*)\"") do
map[tag .. k] = v
end
end
local stream = vlc.stream(url)
if not stream then return false end
local items = {}
local map = {}
if "#EXTM3U" ~= stream:readline() then
return {{}}
end
while true do
local line = stream:readline()
if not line then break end
if "#" == line:sub(1, 1) then
m3u_parse_line(line, map)
else
local name = map["EXT-X-MEDIA:NAME"] or "error"
local resolution = map["EXT-X-STREAM-INF:RESOLUTION"] or "error"
table.insert(items, {
path = line,
description = meta.description,
name = name.." ("..resolution..")"
})
map = {}
end
end
return items
end
function get_playlist(urls, id, meta)
local opt = {scheme = vlc.access, user = id, client = client}
local url = build_url(urls.token, opt)
local data = json.decode(vlc.stream(url):readline())
opt.token = data.token
opt.sig = data.sig
url = build_url(urls.hls, opt)
return m3u_parse(url, meta)
end
function get_content(line, matcher, finder)
local content
if string.match( line, matcher ) then
_,_,content = string.find( line, finder )
if content then
content = vlc.strings.resolve_xml_special_chars( content )
end
end
return content
end
function build_url(template, options)
return template:gsub("%${(%w+)}", function (arg)
return vlc.strings.encode_uri_component(options[arg])
end)
end
function probe()
return (vlc.access == "http"
or vlc.access == "https")
and matches(".twitch.tv")
end
function parse()
local meta = {}
local id
local path = vlc.path:match("^[^/]+/(.-)/?$")
while true do
-- ugly pseudo xml/html parsing
local line = vlc.readline()
if not line then break end
meta.title = get_content( line, "<meta.- property='og:title'>", "content='(.-)'" )
meta.description = get_content( line, "<meta.- property='og:description'>", "content='(.-)'" )
end
-- vod url
id = path:match("videos/([^/]+)$")
if id
then
return get_playlist(urls.vod, id, meta)
end
-- live stream url
id = path:match("^([^/]+)$")
if id
then
return get_playlist(urls.hls, id, meta)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment