]> njoseph.me Git - nimcoon.git/blobdiff - src/youtube.nim
YouTube auto-play
[nimcoon.git] / src / youtube.nim
index fd98d41e4f2f22b257789e34cf2fe437008b0ab3..a83e23372fb21b6e66822648812bf60ef062aacf 100644 (file)
@@ -3,40 +3,43 @@ import
   json,
   strformat,
   strutils,
-  sequtils,
   uri
 
-import types
-
-proc getYouTubePage(searchQuery: string): string =
-  let queryParam = encodeUrl(searchQuery)
-  let client = newHttpClient()
-  let response = get(client, &"https://www.youtube.com/results?search_query={queryParam}")
-  $response.body
-
+import
+  config,
+  types
 
-proc getSearchResults*(searchQuery: string): SearchResults =
-  let html = getYouTubePage(searchQuery)
-  let lines = html.split('\n').filterIt(it.contains("ytInitialData"))
-  let line = lines[0]
-  let jsonString = line.split('=', maxsplit=1)[1].strip().strip(chars={';'})
-  let jsonData = parseJson(jsonString)
 
-  let videos = jsonData["contents"]["twoColumnSearchResultsRenderer"]["primaryContents"]["sectionListRenderer"]["contents"][0]["itemSectionRenderer"]["contents"]
+discard """
 
-  var searchResults: SearchResults = @[]
+Invidious API reference:
+https://github.com/iv-org/documentation/blob/master/API.md
+"""
 
-  for video in videos:
-    if video.hasKey("videoRenderer"):
-      let title = ($video["videoRenderer"]["title"]["runs"][0]["text"]).strip(chars={'"'})
-      let videoId = ($video["videoRenderer"]["videoId"]).strip(chars={'"'})
-      let videoUrl = &"https://www.youtube.com/watch?v={videoId}"
-      searchResults.add((title, videoUrl))
+func makeUrl(videoId: string): string =
+  "https://www.youtube.com/watch?v=" & videoId
 
-    elif video.hasKey("playlistRenderer"):
-      let title = ($video["playlistRenderer"]["title"]["simpleText"]).strip(chars={'"'})
-      let playlistId = ($video["playlistRenderer"]["playlistId"]).strip(chars={'"'})
-      let playlistUrl = &"https://www.youtube.com/playlist?list={playlistId}"
-      searchResults.add((title, playlistUrl))
 
+proc getSearchResults*(searchQuery: string): SearchResults =
+  # Using Invidious API to retrieve the search results but playing the results directly from YouTube.
+  let queryParam = encodeUrl(searchQuery)
+  let client = newHttpClient()
+  let response = get(client, &"{invidiousInstance}/api/v1/search?q={queryParam}")
+  let jsonData = parseJson($response.body)
+  var searchResults: SearchResults = @[]
+  for item in jsonData:
+    if item["type"].getStr() == "video":
+      searchResults.add((item["title"].getStr(), makeUrl(item["videoId"].getStr())))
+    elif item["type"].getStr() == "playlist":
+      searchResults.add((item["title"].getStr(), makeUrl(item["playlistId"].getStr())))
+    # Not handling type = channel for now
   searchResults
+
+proc getAutoPlayVideo*(searchResult: SearchResult): SearchResult =
+  # Take a search result and fetch its first recommendation
+  let videoId = searchResult.url.split("=")[1]
+  let client = newHttpClient()
+  let response = get(client, &"{invidiousInstance}/api/v1/videos/{videoId}")
+  let jsonData = parseJson($response.body)
+  let firstRecommendation = jsonData["recommendedVideos"][0]
+  (firstRecommendation["title"].getStr(), makeUrl(firstRecommendation["videoId"].getStr()))