diff options
| author | Julian Hurst <julian.hurst92@gmail.com> | 2020-10-19 12:57:52 +0200 |
|---|---|---|
| committer | Julian Hurst <julian.hurst92@gmail.com> | 2020-10-19 12:57:52 +0200 |
| commit | 81654b53ae422431255a1e3fbc4cd520aeffcb06 (patch) | |
| tree | f2fe16d44d886089e82b3d30b583063e186921c2 | |
| parent | ae8513f692688106058356aabd05424437405c11 (diff) | |
| download | grimtube-81654b53ae422431255a1e3fbc4cd520aeffcb06.tar.gz | |
Update ytparser (migrated to srht)
| -rw-r--r-- | go.mod | 2 | ||||
| -rw-r--r-- | go.sum | 2 | ||||
| -rw-r--r-- | grimtube.go | 2 | ||||
| -rw-r--r-- | templates/search.html | 2 | ||||
| -rw-r--r-- | ytparser/ytparser.go | 188 |
5 files changed, 6 insertions, 190 deletions
@@ -1,3 +1,5 @@ module grimtube go 1.15 + +require git.sr.ht/~ark/ytparser v0.0.0-20201019100927-5f211df7cfbb @@ -0,0 +1,2 @@ +git.sr.ht/~ark/ytparser v0.0.0-20201019100927-5f211df7cfbb h1:cl79Gq9gc7XrfYh42k7FHngRT0oh1u+GgH1DTot/cYQ= +git.sr.ht/~ark/ytparser v0.0.0-20201019100927-5f211df7cfbb/go.mod h1:/LVNTXoOf1dnQ85TQK3Osw8KK7POmeeqBQUoXivfIPI= diff --git a/grimtube.go b/grimtube.go index 0ea1d50..17de1b6 100644 --- a/grimtube.go +++ b/grimtube.go @@ -10,7 +10,7 @@ import ( "strconv" //"path" - "grimtube/ytparser" + "git.sr.ht/~ark/ytparser" ) func getLangs() []string { diff --git a/templates/search.html b/templates/search.html index 8a75962..c0cdb76 100644 --- a/templates/search.html +++ b/templates/search.html @@ -16,7 +16,7 @@ {{range .Items}} <tr> <td> - <a href="/embed?id={{.Id}}"><img width=240 src="{{.Thumb}}"></a> + <a href="/embed?id={{.Id}}"><img width=240 src="{{.ThumbUrl}}"></a> </td> <td> <p><a href="/embed?id={{.Id}}">{{.Title}}</a></p> diff --git a/ytparser/ytparser.go b/ytparser/ytparser.go deleted file mode 100644 index 1ebd783..0000000 --- a/ytparser/ytparser.go +++ /dev/null @@ -1,188 +0,0 @@ -package ytparser - -import ( - "text/template" - "encoding/json" - "fmt" - "net/http" - "bytes" - "os" - "io" - "io/ioutil" - "strings" - "net/url" - "regexp" -) - -const windowInitDataString string = "window[\"ytInitialData\"] = " -const initDataString string = "var ytInitialData = " -const baseUrl string = "https://youtube.com" - -type Item struct { - Id string - Title string - Url string - Thumb string - ChannelTitle string - ChannelUrl string - Published string -} - -func (item Item) Format(t *template.Template) string { - var b strings.Builder - err := t.Execute(&b, item) - if err != nil { - panic(err) - } - return b.String() -} - -func (item Item) String() string { - return fmt.Sprintf("id: %s, title: %s, url: %s, thumb: %s", item.Id, item.Title, item.Url, item.Thumb) -} - -func parsejson(data string) ([]Item, error) { - dec := json.NewDecoder(strings.NewReader(data)) - - depth := 0 - isArray := false - isValue := false - var items []Item - var item Item - var names []string - nbItems := 0 - for { - tok, err := dec.Token() - if err == io.EOF { - break - } else if err != nil { - return items, err - } - - switch t := tok.(type) { - case json.Delim: - if t == '{' { - depth++ - } else if t == '}' { - depth-- - names = names[:depth] - } - isArray = t == '[' - isValue = false - case string: - if !isArray { - if !isValue { - if t == "videoRenderer" { - if nbItems > 0 { - items = append(items, item) - } - item = Item{} - nbItems++ - } - if depth > len(names) { - names = append(names, t) - } else { - names[depth - 1] = t - } - //fmt.Println(t, depth, len(names), names[depth - 1]) - isValue = true - } else { - //fmt.Println(names[len(names) - 1]) - if names[depth-1] == "videoId" { - item.Id = t - item.Url = fmt.Sprintf("https://youtube.com/watch?v=%s", t) - } - if depth >= 3 && names[depth-3] == "title" && - names[depth-2] == "runs" && - names[depth-1] == "text" { - item.Title = t - } - if depth >= 3 && names[depth-3] == "ownerText" && - names[depth-2] == "runs" && - names[depth-1] == "text" { - item.ChannelTitle = t - } - if depth >= 6 && - names[depth-6] == "ownerText" && - names[depth-5] == "runs" && - names[depth-4] == "navigationEndpoint" && - names[depth-3] == "commandMetadata" && - names[depth-2] == "webCommandMetadata" && - names[depth-1] == "url" { - item.ChannelUrl = baseUrl + t - } - if depth >= 4 && - names[depth-4] == "videoRenderer" && - names[depth-3] == "thumbnail" && - names[depth-2] == "thumbnails" && - names[depth-1] == "url" { - item.Thumb = t - } - if depth >= 3 && - names[depth-3] == "videoRenderer" && - names[depth-2] == "publishedTimeText" && - names[depth-1] == "simpleText" { - item.Published = t - } - isValue = false - } - } - default: - } - } - return items, nil -} - -func PrintItems(items []Item, format string) { - t := template.Must(template.New("items").Parse(format)) - for _, i := range items { - fmt.Println(i.Format(t)) - } -} - -func request(query string, page int, lang string) (string, error) { - q := url.QueryEscape(query) - url := fmt.Sprintf("https://www.youtube.com/results?search_query=%s&page=%d&hl=%s", q, page, lang) - res, err := http.DefaultClient.Get(url) - if err != nil { - return "", err - } - body, err := ioutil.ReadAll(res.Body) - if err != nil { - return "", err - } - initString := windowInitDataString - idx := bytes.Index(body, []byte(windowInitDataString)) - if idx == -1 { - initString = initDataString - idx = bytes.Index(body, []byte(initDataString)) - } - idx += len(initString) - startData := body[idx:] - pattern := regexp.MustCompile(`; *\n`) - loc := pattern.FindIndex(startData) - startData = startData[:loc[0]] - return string(startData), nil -} - -func isValidData(data string) bool { - return data != "" -} - -func Search(query string, page int, lang string) ([]Item, error) { - if lang == "" { - lang = "en" - } - var data string = "" - var err error - for i := 1; i < 4 && !isValidData(data); i++ { - if i > 1 { - fmt.Fprintf(os.Stderr, "Yt data invalid, retrying (attempt %d)\n", i) - } - data, err = request(query, page, lang) - if err != nil { - return nil, err - } - } - return parsejson(data) -} |
