]> njoseph.me Git - nimcoon.git/blame - clitube.nim
Because org-mode has checkboxes too!
[nimcoon.git] / clitube.nim
CommitLineData
6ff2dbac
JN
1import
2 htmlparser,
3 httpClient,
4 parseopt,
5 osproc,
6 sequtils,
7 sugar,
8 strformat,
9 std/[terminal],
10 strtabs,
11 strutils,
12 uri,
13 xmltree
44978125 14
2f0b8428 15import preferences
c760b5d9 16
2f3c8875
JN
17type SearchResult = tuple[title: string, url: string]
18
933e339b
JN
19proc selectMediaPlayer(): string =
20 let availablePlayers = filterIt(supportedPlayers, execProcess("which " & it).len != 0)
21 if len(availablePlayers) == 0:
b40b7243 22 stderr.writeLine &"Please install one of the supported media players: {supportedPlayers}"
933e339b
JN
23 raise newException(OSError, "No supported media player found")
24 else:
25 return availablePlayers[0]
44978125 26
39a495a9
JN
27proc getYoutubePage(searchQuery: string): string =
28 let queryParam = encodeUrl(searchQuery)
485b1053 29 let client = newHttpClient()
b40b7243 30 let response = get(client, &"https://www.youtube.com/results?hl=en&search_query={queryParam}")
485b1053 31 return $response.body
44978125 32
2f3c8875 33proc extractTitlesAndUrls(htmlFile: string): seq[SearchResult] =
485b1053 34 parseHtml(htmlFile).findAll("a").
44978125 35 filter(a => "watch" in a.attrs["href"] and a.attrs.hasKey "title").
c760b5d9 36 map(a => (a.attrs["title"], "https://www.youtube.com" & a.attrs["href"]))[..(limit-1)]
44978125 37
2f3c8875 38proc presentVideoOptions(searchResults: seq[SearchResult]) =
efcc0441 39 echo ""
2f3c8875 40 for index, (title, url) in searchResults:
3d5bf3fd 41 styledEcho $index, ". ", styleBright, fgMagenta, title, "\n", resetStyle, fgCyan, url, "\n"
44978125 42
84d84780
JN
43let player = selectMediaPlayer()
44
4827df7a
JN
45var searchQuery = ""
46var musicOnly = false
f135dfc7 47var feelingLucky = false
4827df7a
JN
48
49for kind, key, value in getopt():
50 case kind
51 of cmdArgument:
52 searchQuery = key
53 of cmdShortOption, cmdLongOption:
54 case key
55 of "m", "music": musicOnly = true
f135dfc7 56 of "l", "lucky": feelingLucky = true
4827df7a
JN
57 of cmdEnd:
58 discard
59
6ff2dbac 60if "watch?" in searchQuery or "videos/watch" in searchQuery :
4827df7a 61 discard execProcess(&"{player} {searchQuery}")
84d84780 62 quit(0)
6ff2dbac 63elif searchQuery.startswith("magnet:"):
52ecc638
JN
64 discard execProcess(&"peerflix \"{searchQuery}\" --{player}")
65 quit(0)
66
4827df7a 67let searchResults = extractTitlesAndUrls(getYoutubePage(searchQuery))
efcc0441 68
f135dfc7 69let number =
6ff2dbac 70 if feelingLucky: 0
f135dfc7
JN
71 else:
72 presentVideoOptions(searchResults)
73 stdout.styledWrite(fgYellow, "Choose video number: ")
74 parseInt(readLine(stdin))
efcc0441 75
3d5bf3fd 76styledEcho "\n", fgGreen, "Playing ", styleBright, fgMagenta, searchResults[number].title
efcc0441 77
a2319a3f
JN
78var command = @[player, searchResults[number].url]
79
80if musicOnly:
81 command.add("--no-video")
82
3d5bf3fd 83# Play the video using the preferred/available media player
a2319a3f 84discard execProcess(command.join(" "))