From: Joseph Nuthalapati Date: Fri, 27 Mar 2020 06:57:47 +0000 (+0530) Subject: Add option to download music X-Git-Tag: 0.1.0~6 X-Git-Url: https://njoseph.me/gitweb/nimcoon.git/commitdiff_plain/e9f0c7d0facb6a454a204e3b3ce66d521f40d6e8 Add option to download music Signed-off-by: Joseph Nuthalapati --- diff --git a/README.md b/README.md index daf4ca6..d5d51b6 100644 --- 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 diff --git a/src/config.nim b/src/config.nim index 2431cd7..3593fe6 100644 --- a/src/config.nim +++ b/src/config.nim @@ -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" diff --git a/src/lib.nim b/src/lib.nim index 8315473..1b6ed93 100644 --- a/src/lib.nim +++ b/src/lib.nim @@ -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=") diff --git a/src/nimcoon.nim b/src/nimcoon.nim index 2143c12..2db5ece 100644 --- a/src/nimcoon.nim +++ b/src/nimcoon.nim @@ -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