Add option to download music
authorJoseph Nuthalapati <njoseph@riseup.net>
Fri, 27 Mar 2020 06:57:47 +0000 (12:27 +0530)
committerJoseph Nuthalapati <njoseph@riseup.net>
Fri, 27 Mar 2020 07:10:41 +0000 (12:40 +0530)
Signed-off-by: Joseph Nuthalapati <njoseph@riseup.net>
README.md
src/config.nim
src/lib.nim
src/nimcoon.nim

index daf4ca6c54f0f60daae679c4fad551137a5ee3fa..d5d51b6fb87dc53afd41207db10edbfe7a0d0e76 100644 (file)
--- a/README.md
+++ b/README.md
@@ -15,8 +15,8 @@ only the standard library.
 - [x] Stream music
 - [x] Play direct links from YouTube and PeerTube
 - [x] Stream video from magnet links
+- [x] Download music
 - [ ] Download video
-- [ ] Download music
 - [ ] Configuration options
 
 ## Installation
@@ -61,6 +61,7 @@ nimcoon -m -l "counting stars"
 | -m, --music       | Play Music only, no video                  |
 | -l, --lucky       | Try your luck with the first search result |
 | -f, --full-screen | Play video in full screen                  |
+| -d, --download    | Download video or music                    |
 
 ## Development
 
index 2431cd72dea17e2389c180f9243430487c2929e2..3593fe6aff419725a0197d1fe7a464aa941e5492 100644 (file)
@@ -6,3 +6,9 @@ let supportedPlayers* = ["mpv", "cvlc"]
 
 # Only show these many results
 let limit* = 10
+
+# Download videos to this directory
+let videoDownloadDirectory* = "~/Videos"
+
+# Download music to this directory
+let musicDownloadDirectory* = "~/Music"
index 83154737295ab7f25e9d5957245591cd3f550a7e..1b6ed93770f0571ec0d9df915cb4302371637e17 100644 (file)
@@ -1,11 +1,13 @@
 import
   htmlparser,
   httpClient,
+  os,
   osproc,
   sequtils,
   sugar,
   strformat,
   std/[terminal],
+  strformat,
   strtabs,
   strutils,
   tables,
@@ -15,11 +17,12 @@ import
 import config
 
 type
-  SearchResult* = tuple[title: string, url: string]
   Options* = Table[string, bool]
+  SearchResult* = tuple[title: string, url: string]
   CommandLineOptions* = tuple[searchQuery: string, options: Options]
 
-let processOptions = {poStdErrToStdOut, poUsePath}
+# poEchoCmd can be added to options for debugging
+let processOptions = {poStdErrToStdOut, poUsePath, poEchoCmd}
 
 proc selectMediaPlayer*(): string =
   let availablePlayers = filterIt(supportedPlayers, execProcess("which " & it).len != 0)
@@ -47,10 +50,13 @@ proc presentVideoOptions*(searchResults: seq[SearchResult]) =
     styledEcho $index, ". ", styleBright, fgMagenta, title, "\n", resetStyle, fgCyan, url, "\n"
 
 proc play*(player: string, args: openArray[string], title: string) =
-  # poEchoCmd can be added to options for debugging
   styledEcho "\n", fgGreen, "Playing ", styleBright, fgMagenta, title
   discard execProcess(player, args=args, options=processOptions)
 
+proc download*(args: openArray[string], title: string) =
+  styledEcho "\n", fgGreen, "Downloading ", styleBright, fgMagenta, title
+  discard execShellCmd(&"youtube-dl {args.join(\" \")}")
+
 func urlLongen(url: string): string =
   url.replace("youtu.be/", "www.youtube.com/watch?v=")
 
index 2143c12ad6c9d990e15e379b65dd701fc5e32098..2db5ece023a706ac3312e2a73419cdf22282b355 100644 (file)
@@ -1,4 +1,5 @@
 import
+  os,
   parseopt,
   std/[terminal],
   strformat,
@@ -61,25 +62,42 @@ proc main() =
       readLine(stdin)
 
   # This is a pure function with no side effects
-  func buildArgs(number: int): seq[string] =
+  func buildPlayerArgs(number: int): seq[string] =
     var args = @[searchResults[number].url]
     if options["musicOnly"]: args.add("--no-video")
     if options["fullScreen"]: args.add("--fullscreen")
     return args
 
+  func buildMusicDownloadArgs(number: int): seq[string] =
+    {.noSideEffect.}:
+      var args = @["--ignore-errors", "-f", "bestaudio", "--extract-audio", "--audio-format", "mp3", "--audio-quality", "0", "-o"]
+      let downloadLocation = &"'{expandTilde(musicDownloadDirectory)}/{searchResults[number].title}.mp3'"
+      args.add(downloadLocation)
+      args.add(searchResults[number].url)
+      return args
+
+  proc handleUserInput(number: int) =
+    if options["download"]:
+      if options["musicOnly"]:
+        download(buildMusicDownloadArgs(number), searchResults[number].title)
+    else:
+      play(player, buildPlayerArgs(number), searchResults[number].title)
+
+
   while(true):
     let userInput = getUserInput()
 
     if userInput == "all":
       for number in 0..(len(searchResults)):
-        play(player, buildArgs(number), searchResults[number].title)
+        # TODO `spawn` this?
+        handleUserInput(number)
 
     if userInput == "q":
       break
 
     # Play the video using the preferred/available media player
     let videoNumber = parseInt(userInput)
-    play(player, buildArgs(videoNumber), searchResults[videoNumber].title)
+    handleUserInput(videoNumber)
     if options["feelingLucky"]:
       break