You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

parsechannel.go 1.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package apijson
  2. import (
  3. "github.com/valyala/fastjson"
  4. "errors"
  5. "strings"
  6. "net/http"
  7. "io/ioutil"
  8. "fmt"
  9. )
  10. var MissingData = errors.New("missing data")
  11. var ServerError = errors.New("server error")
  12. func ParseChannelVideoURLs(res *http.Response) ([]string, error) {
  13. if res.StatusCode != 200 {
  14. return nil, fmt.Errorf("HTTP error: %s", res.Request.URL.String())
  15. }
  16. // Download response
  17. defer res.Body.Close()
  18. buf, err := ioutil.ReadAll(res.Body)
  19. if err != nil { return nil, err }
  20. // Parse JSON
  21. var p fastjson.Parser
  22. rootObj, err := p.ParseBytes(buf)
  23. if err != nil { return nil, err }
  24. // Root as array
  25. root, err := rootObj.Array()
  26. if err != nil { return nil, err }
  27. // Find response container
  28. var container *fastjson.Value
  29. for _, item := range root {
  30. if item.Exists("response") {
  31. container = item
  32. break
  33. }
  34. }
  35. if container == nil { return nil, MissingData }
  36. // Get error obj
  37. errorExists := container.Exists(
  38. "response",
  39. "responseContext",
  40. "errors",
  41. "error",
  42. )
  43. if errorExists { return nil, ServerError }
  44. // Get items from grid
  45. itemsObj := container.Get(
  46. "response",
  47. "continuationContents",
  48. "gridContinuation",
  49. "items",
  50. )
  51. if itemsObj == nil { return nil, MissingData }
  52. // Items as array
  53. items, err := itemsObj.Array()
  54. if err != nil { return nil, err }
  55. urls := make([]string, 0)
  56. // Enumerate
  57. for _, item := range items {
  58. // Find URL
  59. urlObj := item.Get(
  60. "gridVideoRenderer",
  61. "navigationEndpoint",
  62. "commandMetadata",
  63. "webCommandMetadata",
  64. "url",
  65. )
  66. if urlObj == nil { return nil, MissingData }
  67. // URL as string
  68. urlBytes, err := urlObj.StringBytes()
  69. if err != nil { return nil, err }
  70. url := string(urlBytes)
  71. if strings.HasPrefix(url, "/watch?v") {
  72. urls = append(urls, "https://www.youtube.com" + url)
  73. }
  74. }
  75. return urls, nil
  76. }