youtube: Use a different Invidious instance
[nimcoon.git] / src / youtube.nim
1 import
2 httpClient,
3 json,
4 std/[terminal],
5 strformat,
6 strutils,
7 uri
8
9 import
10 config,
11 types
12
13
14 discard """
15
16 Invidious API reference:
17 https://github.com/iv-org/documentation/blob/master/API.md
18 """
19
20 func makeUrl(videoId: string): string =
21 "https://www.youtube.com/watch?v=" & videoId
22
23
24 proc getSearchResults*(searchQuery: string): SearchResults =
25 # Using Invidious API to retrieve the search results but playing the results directly from YouTube.
26 let queryParam = encodeUrl(searchQuery)
27 let client = newHttpClient()
28 let response = get(client, &"{invidiousInstance}/api/v1/search?q={queryParam}")
29 let jsonData = parseJson($response.body)
30 if jsonData.kind == JObject: # Could be a 403 error
31 stdout.styledWrite(fgRed, $response.body)
32 quit(1)
33 if len(jsonData) == 0:
34 stdout.styledWrite(fgRed, "Got empty response from Invidious instance")
35 quit(2)
36 var searchResults: SearchResults = @[]
37 for item in jsonData:
38 if item["type"].getStr() == "video":
39 searchResults.add((item["title"].getStr(), makeUrl(item["videoId"].getStr())))
40 elif item["type"].getStr() == "playlist":
41 searchResults.add((item["title"].getStr(), makeUrl(item["playlistId"].getStr())))
42 # Not handling type = channel for now
43 searchResults
44
45 proc getAutoPlayVideo*(searchResult: SearchResult): SearchResult =
46 # Take a search result and fetch its first recommendation
47 let videoId = searchResult.url.split("=")[1]
48 let client = newHttpClient()
49 let response = get(client, &"{invidiousInstance}/api/v1/videos/{videoId}")
50 let jsonData = parseJson($response.body)
51 let firstRecommendation = jsonData["recommendedVideos"][0]
52 (firstRecommendation["title"].getStr(), makeUrl(firstRecommendation["videoId"].getStr()))