X-Git-Url: https://njoseph.me/gitweb/nimcoon.git/blobdiff_plain/e08e5cbe091074b7cd05bfe131edb2af70b26bc9..fc3b0d351d0589613cbd952726f5e11583c12700:/src/youtube.nim diff --git a/src/youtube.nim b/src/youtube.nim index fd98d41..a07a629 100644 --- a/src/youtube.nim +++ b/src/youtube.nim @@ -1,42 +1,52 @@ import httpClient, json, + std/[terminal], 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) + if jsonData.kind == JObject: # Could be a 403 error + stdout.styledWrite(fgRed, $response.body) + quit(1) + if len(jsonData) == 0: + stdout.styledWrite(fgRed, "Got empty response from Invidious instance") + quit(2) + 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()))