Commit d65a1dcf authored by Joseph Nuthalapati's avatar Joseph Nuthalapati

Modularity and Tests

Signed-off-by: Joseph Nuthalapati's avatarJoseph Nuthalapati <njoseph@riseup.net>
parent c8812b68
Pipeline #108672389 passed with stage
in 51 seconds
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:
......
......@@ -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
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}"])
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()
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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment