From: Joseph Nuthalapati Date: Sun, 12 Jan 2020 06:25:06 +0000 (+0530) Subject: Modularity and Tests X-Git-Tag: 0.1.0~21 X-Git-Url: https://njoseph.me/gitweb/nimcoon.git/commitdiff_plain/d65a1dcf24e9c17cea89385c78b1c39c314f0f97 Modularity and Tests Signed-off-by: Joseph Nuthalapati --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 727e2f2..e5efc71 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,10 +1,14 @@ image: nimlang/nim:latest stages: - - build + - test + - publish compile: - stage: build + stage: test + script: + - nim c -d:ssl -r tests + stage: publish script: - nim c -d:ssl -d:release nimcoon.nim && strip nimcoon artifacts: diff --git a/TODO.org b/TODO.org index cf42d0f..0019cab 100644 --- a/TODO.org +++ b/TODO.org @@ -5,8 +5,7 @@ - [X] Create a proper CLI - [X] PeerTube support (only direct download, because webtorrent seeds are too slow) - [X] Find a better name. clitube is an SEO disaster -- [ ] Terminal color themes? -- [ ] SoundCloud support? - [ ] Spawn video player and quit immediately +- [ ] SoundCloud support? Search and play music - [ ] LRU cache of content so that frequently-played content doesn't use BW - [ ] Option to download audio/video diff --git a/lib.nim b/lib.nim new file mode 100644 index 0000000..25669a3 --- /dev/null +++ b/lib.nim @@ -0,0 +1,62 @@ +import + htmlparser, + httpClient, + osproc, + sequtils, + sugar, + strformat, + std/[terminal], + strtabs, + strutils, + uri, + xmltree + +import config + +type + SearchResult* = tuple[title: string, url: string] + CommandLineOptions* = tuple[searchQuery: string, musicOnly: bool, feelingLucky: bool, fullScreen: bool] + +proc selectMediaPlayer*(): string = + let availablePlayers = filterIt(supportedPlayers, execProcess("which " & it).len != 0) + if len(availablePlayers) == 0: + stderr.writeLine &"Please install one of the supported media players: {supportedPlayers}" + raise newException(OSError, "No supported media player found") + else: + return availablePlayers[0] + +proc getYoutubePage*(searchQuery: string): string = + let queryParam = encodeUrl(searchQuery) + let client = newHttpClient() + let response = get(client, &"https://www.youtube.com/results?hl=en&search_query={queryParam}") + return $response.body + +proc extractTitlesAndUrls*(html: string): seq[SearchResult] = + parseHtml(html).findAll("a"). + filter(a => "watch" in a.attrs["href"] and a.attrs.hasKey "title"). + map(a => (a.attrs["title"], "https://www.youtube.com" & a.attrs["href"]))[..(limit-1)] + +proc presentVideoOptions*(searchResults: seq[SearchResult]) = + echo "" + for index, (title, url) in searchResults: + styledEcho $index, ". ", styleBright, fgMagenta, title, "\n", resetStyle, fgCyan, url, "\n" + +proc play*(player: string, args: openArray[string]) = + # poEchoCmd can be added to options for debugging + discard execProcess(player, args=args, options={poStdErrToStdOut, poUsePath}) + quit(0) + +func urlLongen(url: string): string = + url.replace("youtu.be/", "www.youtube.com/watch?v=") + +func stripZshEscaping(url: string): string = + url.replace("\\", "") + +func sanitizeURL*(url: string): string = + urlLongen(stripZshEscaping(url)) + +proc directPlay*(searchQuery: string, player: string) = + if "watch?" in searchQuery or "videos/watch" in searchQuery or "soundcloud.com" in searchQuery: + play(player, args=[sanitizeURL(searchQuery)]) + elif searchQuery.startswith("magnet:"): + play("peerflix", args=[searchQuery, &"--{player}"]) diff --git a/nimcoon.nim b/nimcoon.nim index 7b69ddb..5c2dc08 100644 --- a/nimcoon.nim +++ b/nimcoon.nim @@ -1,30 +1,9 @@ import - htmlparser, - httpClient, parseopt, - osproc, - sequtils, - sugar, - strformat, std/[terminal], - strtabs, - strutils, - uri, - xmltree + strutils -import config - -type - SearchResult = tuple[title: string, url: string] - CommandLineOptions = tuple[searchQuery: string, musicOnly: bool, feelingLucky: bool, fullScreen: bool] - -proc selectMediaPlayer(): string = - let availablePlayers = filterIt(supportedPlayers, execProcess("which " & it).len != 0) - if len(availablePlayers) == 0: - stderr.writeLine &"Please install one of the supported media players: {supportedPlayers}" - raise newException(OSError, "No supported media player found") - else: - return availablePlayers[0] +import lib proc parseOptions(): CommandLineOptions = var @@ -47,32 +26,6 @@ proc parseOptions(): CommandLineOptions = return (searchQuery, musicOnly, feelingLucky, fullScreen) -proc getYoutubePage(searchQuery: string): string = - let queryParam = encodeUrl(searchQuery) - let client = newHttpClient() - let response = get(client, &"https://www.youtube.com/results?hl=en&search_query={queryParam}") - return $response.body - -proc extractTitlesAndUrls(html: string): seq[SearchResult] = - parseHtml(html).findAll("a"). - filter(a => "watch" in a.attrs["href"] and a.attrs.hasKey "title"). - map(a => (a.attrs["title"], "https://www.youtube.com" & a.attrs["href"]))[..(limit-1)] - -proc presentVideoOptions(searchResults: seq[SearchResult]) = - echo "" - for index, (title, url) in searchResults: - styledEcho $index, ". ", styleBright, fgMagenta, title, "\n", resetStyle, fgCyan, url, "\n" - -proc play(player: string, args: openArray[string]) = - discard execProcess(player, args=args, options={poStdErrToStdOut, poUsePath, poEchoCmd}) - quit(0) - -proc directPlay(searchQuery: string, player: string) = - if "watch?" in searchQuery or "videos/watch" in searchQuery: - play(player, args=[searchQuery]) - elif searchQuery.startswith("magnet:"): - play("peerflix", args=[searchQuery, &"--{player}"]) - proc main() = let player = selectMediaPlayer() @@ -102,4 +55,5 @@ proc main() = # Play the video using the preferred/available media player play(player, buildArgs()) -main() +when isMainModule: + main() diff --git a/tests.nim b/tests.nim new file mode 100644 index 0000000..f24eb18 --- /dev/null +++ b/tests.nim @@ -0,0 +1,11 @@ +import unittest + +import lib + +suite "Playing direct links": + + test "sanitize URL": + # give up and stop if this fails + let expected = "https://www.youtube.com/watch?v=QOEMv0S8AcA" + check(sanitizeURL("https://youtu.be/QOEMv0S8AcA") == expected) + check(sanitizeURL("https://www.youtube.com/watch\\?v\\=QOEMv0S8AcA") == expected)