2020-02-08 20:44:46 +08:00

115 lines
2.4 KiB
Go

package geekbang
import (
"encoding/json"
"errors"
"net/http"
"strings"
"github.com/iawia002/annie/downloader"
"github.com/iawia002/annie/extractors"
"github.com/iawia002/annie/request"
"github.com/iawia002/annie/utils"
)
type geekData struct {
Code int `json:"code"`
Error json.RawMessage `json:"error"`
Data struct {
Title string `json:"article_sharetitle"`
VideoMediaMap map[string]struct {
URL string `json:"url"`
Size int64 `json:"size"`
} `json:"video_media_map"`
} `json:"data"`
}
type geekURLInfo struct {
URL string
Size int64
}
func geekM3u8(url string) ([]geekURLInfo, error) {
var (
data []geekURLInfo
temp geekURLInfo
size int64
err error
)
urls, err := utils.M3u8URLs(url)
if err != nil {
return nil, err
}
for _, u := range urls {
temp = geekURLInfo{
URL: u,
Size: size,
}
data = append(data, temp)
}
return data, nil
}
// Extract is the main function for extracting data
func Extract(url string) ([]downloader.Data, error) {
var err error
matches := utils.MatchOneOf(url, `https?://time.geekbang.org/course/detail/(\d+)-(\d+)`)
if matches == nil || len(matches) < 3 {
return nil, extractors.ErrURLParseFailed
}
heanders := map[string]string{"Origin": "https://time.geekbang.org", "Content-Type": "application/json", "Referer": url}
params := strings.NewReader("{\"id\":" + string(matches[2]+"}"))
res, err := request.Request(http.MethodPost, "https://time.geekbang.org/serv/v1/article", params, heanders)
if err != nil {
return nil, err
}
defer res.Body.Close()
var data geekData
if err = json.NewDecoder(res.Body).Decode(&data); err != nil {
return nil, err
}
if data.Code < 0 {
return nil, errors.New(string(data.Error))
}
title := data.Data.Title
streams := make(map[string]downloader.Stream, len(data.Data.VideoMediaMap))
for key, media := range data.Data.VideoMediaMap {
m3u8URLs, err := geekM3u8(media.URL)
if err != nil {
return nil, err
}
urls := make([]downloader.URL, len(m3u8URLs))
for index, u := range m3u8URLs {
urls[index] = downloader.URL{
URL: u.URL,
Size: u.Size,
Ext: "ts",
}
}
streams[key] = downloader.Stream{
URLs: urls,
Size: media.Size,
Quality: key,
}
}
return []downloader.Data{
{
Site: "极客时间 geekbang.org",
Title: title,
Type: "video",
Streams: streams,
URL: url,
},
}, nil
}