]>
Commit | Line | Data |
---|---|---|
6ff2dbac | 1 | import |
e9f0c7d0 | 2 | os, |
6ff2dbac | 3 | parseopt, |
6ff2dbac | 4 | std/[terminal], |
6f161e0b JN |
5 | strformat, |
6 | strutils, | |
7 | tables | |
44978125 | 8 | |
72720bec | 9 | import config |
d65a1dcf | 10 | import lib |
44978125 | 11 | |
6f161e0b JN |
12 | |
13 | proc parseArguments(): CommandLineOptions = | |
121e06b2 JN |
14 | var |
15 | searchQuery = "" | |
6f161e0b | 16 | options = to_table({"musicOnly": false, "feelingLucky": false, "fullScreen": false, "download": false}) |
121e06b2 JN |
17 | |
18 | for kind, key, value in getopt(): | |
19 | case kind | |
20 | of cmdArgument: | |
21 | searchQuery = key | |
22 | of cmdShortOption, cmdLongOption: | |
23 | case key | |
6f161e0b JN |
24 | of "m", "music": options["musicOnly"] = true |
25 | of "l", "lucky": options["feelingLucky"] = true | |
26 | of "f", "full-screen": options["fullScreen"] = true | |
27 | of "d", "download": options["download"] = true | |
28 | of cmdEnd: discard | |
29 | ||
30 | return (searchQuery, options) | |
121e06b2 | 31 | |
6f161e0b JN |
32 | |
33 | proc isValidOptions*(options: Options): bool = | |
34 | # Check for invalid combinations of options | |
95683732 | 35 | var invalidCombinations = [("musicOnly", "fullScreen"), ("download", "fullScreen")] |
6f161e0b JN |
36 | for combination in invalidCombinations: |
37 | if options[combination[0]] and options[combination[1]]: | |
38 | stderr.writeLine fmt"Incompatible options provided: {combination[0]} and {combination[1]}" | |
39 | return false | |
40 | return true | |
121e06b2 | 41 | |
d807245d | 42 | |
121e06b2 JN |
43 | proc main() = |
44 | let | |
45 | player = selectMediaPlayer() | |
6f161e0b JN |
46 | (searchQuery, options) = parseArguments() |
47 | ||
48 | if(not isValidOptions(options)): | |
49 | quit(1) | |
121e06b2 | 50 | |
92f80e5a | 51 | if searchQuery.startswith("https:") or searchQuery.startswith("magnet:"): |
9a8ef4ad | 52 | if options["download"]: |
811928a7 | 53 | directDownload(sanitizeURL(searchQuery), options["musicOnly"]) |
9a8ef4ad | 54 | else: |
811928a7 | 55 | directPlay(sanitizeURL(searchQuery), player, options["musicOnly"]) |
9e6b8568 | 56 | quit(0) |
121e06b2 JN |
57 | |
58 | let searchResults = extractTitlesAndUrls(getYoutubePage(searchQuery)) | |
59 | ||
e6561dc9 JN |
60 | # Currently available range to choose from depending on pagination |
61 | var selectionRange: SelectionRange = (0, limit-1) # Nim decided to deviate from Python ranges here | |
62 | ||
63 | proc offerSelection(): string = | |
6f161e0b | 64 | if options["feelingLucky"]: "0" |
121e06b2 | 65 | else: |
e6561dc9 | 66 | presentVideoOptions(searchResults[selectionRange.begin .. selectionRange.until]) |
121e06b2 | 67 | stdout.styledWrite(fgYellow, "Choose video number: ") |
d807245d | 68 | readLine(stdin) |
efcc0441 | 69 | |
c8812b68 | 70 | # This is a pure function with no side effects |
e9f0c7d0 | 71 | func buildPlayerArgs(number: int): seq[string] = |
c8812b68 | 72 | var args = @[searchResults[number].url] |
6f161e0b JN |
73 | if options["musicOnly"]: args.add("--no-video") |
74 | if options["fullScreen"]: args.add("--fullscreen") | |
c8812b68 | 75 | return args |
d1e4d2de | 76 | |
e6561dc9 | 77 | proc handleUserInput(selection: int) = |
e9f0c7d0 JN |
78 | if options["download"]: |
79 | if options["musicOnly"]: | |
e6561dc9 | 80 | download(buildMusicDownloadArgs(searchResults[selection].url), searchResults[selection].title) |
d2ebe4d2 | 81 | else: |
e6561dc9 | 82 | download(buildVideoDownloadArgs(searchResults[selection].url), searchResults[selection].title) |
e9f0c7d0 | 83 | else: |
e6561dc9 | 84 | play(player, buildPlayerArgs(selection), searchResults[selection].title) |
e9f0c7d0 JN |
85 | |
86 | ||
d807245d | 87 | while(true): |
e6561dc9 | 88 | let userInput = offerSelection() |
72720bec | 89 | |
e6561dc9 JN |
90 | case userInput |
91 | of "all": | |
92 | for selection in selectionRange.begin .. selectionRange.until: | |
e9f0c7d0 | 93 | # TODO `spawn` this? |
e6561dc9 JN |
94 | handleUserInput(selection) |
95 | of "n": | |
96 | if selectionRange.until + 1 < len(searchResults): | |
97 | selectionRange = (selectionRange.until + 1, min(len(searchResults) - 1, selectionRange.until + limit)) | |
98 | continue | |
99 | # of "p": | |
100 | of "q": | |
101 | quit(0) | |
d807245d | 102 | |
d807245d | 103 | # Play the video using the preferred/available media player |
9e6b8568 | 104 | let videoNumber = parseInt(userInput) |
e9f0c7d0 | 105 | handleUserInput(videoNumber) |
6f161e0b | 106 | if options["feelingLucky"]: |
d807245d JN |
107 | break |
108 | ||
a2319a3f | 109 | |
d65a1dcf JN |
110 | when isMainModule: |
111 | main() |