From 81fb030b66879a978387ce2e45530318eb4eaa60 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Wed, 31 Mar 2021 22:02:16 +0530 Subject: [PATCH 1/6] Rebrand NimCoon to Nimcoon Apparently Coon is an American cussword. Nimcoon is now one word, not two. Signed-off-by: Joseph Nuthalapati --- README.md | 12 ++++++------ nimcoon.el | 20 ++++++++++---------- src/nimcoon.nim | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2b09f97..13cb14a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NimCoon +# Nimcoon Play videos from YouTube and PeerTube from the command line using your preferred desktop media player. @@ -28,7 +28,7 @@ I tried all kinds of alternative YouTube players for the desktop. Most are eithe YouTube's business incentive is to make you watch as many videos as possible. If you open the YouTube website and are logged into it, you will just get distracted by recommendations and forget why you opened it in the first place. You might have wanted to watch a conference talk but end up going down a rabbit hole of other "interesting" videos customized for you. -NimCoon has a spartan design. It doesn't even show images of the search results. It doesn't let you browse YouTube. You have to explicitly search for something. +Nimcoon has a spartan design. It doesn't even show images of the search results. It doesn't let you browse YouTube. You have to explicitly search for something. I have had better success with managing my YouTube consumption after shifting to this tool. Settings inspired by Pinafore's wellness settings. @@ -91,7 +91,7 @@ npm install --global peerflix webtorrent-cli ### Installing using Nimble -NimCoon can be installed from Nimble repositories: +Nimcoon can be installed from Nimble repositories: ``` sh nimble install nimcoon @@ -144,7 +144,7 @@ again. ### Command line arguments -NimCoon provides both interactive and non-interactive arguments with significant +Nimcoon provides both interactive and non-interactive arguments with significant overlap. But some arguments might only be present in one mode. Non-interactive arguments are specified to the nimcoon program and apply @@ -159,7 +159,7 @@ case-by-case basis using the interactive arguments. | -d, --download | Download video or music | | -a, --auto-play | Play the next search result (YouTube only) | -Feel free to use these options in any combination. NimCoon will show a helpful +Feel free to use these options in any combination. Nimcoon will show a helpful error message if you pick incompatible options. Interactive arguments are provided during selection of a search result. These @@ -178,7 +178,7 @@ options as single characters. i.e | -d, --download | Download video or music | | -a, --auto-play | Play the next search result (YouTube only) | -Auto-playing videos leads to binge watching. The default option in NimCoon is to +Auto-playing videos leads to binge watching. The default option in Nimcoon is to support auto-play for music only. ## Development diff --git a/nimcoon.el b/nimcoon.el index 90f15e4..5f01750 100644 --- a/nimcoon.el +++ b/nimcoon.el @@ -7,24 +7,24 @@ ;;; Non-interactive functions to respond to URL clicks (defun nimcoon-play-url (url &rest args) - "Play given URL in NimCoon." + "Play given URL in Nimcoon." (start-process "nimcoon" nil "nimcoon" url)) -;; Play all YouTube URLs in NimCoon +;; Play all YouTube URLs in Nimcoon (setq browse-url-browser-function (quote (("youtu\\.?be" . nimcoon-play-url) ("." . browse-url-default-browser)))) (defun run-nimcoon(args query) - "Search by QUERY and play in NimCoon." + "Search by QUERY and play in Nimcoon." (call-process "nimcoon" nil 0 nil args query)) (defun nimcoon-search(args query) "Search by QUERY with the given ARGS." - (with-output-to-temp-buffer "*NimCoon search results*" - (call-process "nimcoon" nil "*NimCoon search results*" t args query) - (with-current-buffer "*NimCoon search results*" + (with-output-to-temp-buffer "*Nimcoon search results*" + (call-process "nimcoon" nil "*Nimcoon search results*" t args query) + (with-current-buffer "*Nimcoon search results*" (org-mode)))) ;;; Interactive functions @@ -44,9 +44,9 @@ (interactive "sSearch query: ") (run-nimcoon "-dlm" query)) -;; Assumes only one process exists. Must capture the pid of the running NimCoon process and only kill it. +;; Assumes only one process exists. Must capture the pid of the running Nimcoon process and only kill it. (defun nimcoon-kill-background-processes() - "Kill NimCoon process running in the background. Useful for stopping background music." + "Kill Nimcoon process running in the background. Useful for stopping background music." (interactive) (shell-command "kill `pgrep nimcoon` `pgrep mpv` `pgrep vlc`")) @@ -62,8 +62,8 @@ ;;; Keybindings (map! :leader - ;;; N --- NimCoon - (:prefix-map ("N" . "NimCoon") + ;;; N --- Nimcoon + (:prefix-map ("N" . "Nimcoon") (:prefix ("d" . "Download") :desc "Video" "v" #'nimcoon-download-video :desc "Music" "m" #'nimcoon-download-music) diff --git a/src/nimcoon.nim b/src/nimcoon.nim index 1fd3ba6..9b3c6af 100644 --- a/src/nimcoon.nim +++ b/src/nimcoon.nim @@ -39,7 +39,7 @@ proc parseArguments(): CommandLineOptions = of cmdEnd: discard if searchQuery == "": - stderr.writeLine "NimCoon doesn't permit browsing. You must provide a search query." + stderr.writeLine "Nimcoon doesn't permit browsing. You must provide a search query." quit(1) (searchQuery, options) -- 2.43.0 From f4db2dfeab3abaf50943765005e3a3218bad0f90 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Fri, 3 Dec 2021 15:49:12 +0530 Subject: [PATCH 2/6] Shift from youtube-dl to yt-dlp Signed-off-by: Joseph Nuthalapati --- README.md | 6 +++--- src/lib.nim | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 13cb14a..fa32d61 100644 --- a/README.md +++ b/README.md @@ -71,15 +71,15 @@ I made this just for myself. The development is completely based on my needs and ## Installation Nim Coon depends on the following: -- youtube-dl +- yt-dlp - mpv (recommended) or vlc - peerflix and webtorrent (for magnet links) Install MPV or VLC using your distribution's package manager. -Install YouTube-dl +Install yt-dlp ``` sh -pip3 install --user youtube-dl +pip3 install --user yt-dlp ``` Install PeerFlix and WebTorrent diff --git a/src/lib.nim b/src/lib.nim index 4dbbf8b..3dcf78a 100644 --- a/src/lib.nim +++ b/src/lib.nim @@ -119,24 +119,24 @@ func buildDownloadArgs(url: string, options: Options): seq[string] = proc download*(args: openArray[string], title: string) = printTitle("Downloading", title) - discard execShellCmd(&"youtube-dl {args.join(\" \")}") + discard execShellCmd(&"yt-dlp {args.join(\" \")}") proc directDownload*(url: string, options: Options) = let args = buildDownloadArgs(url, options) if "aria2c".isInstalled: - discard execShellCmd(&"youtube-dl {args.join(\" \")} --external-downloader aria2c --external-downloader-args '-x 16 -s 16 -k 2M'") + discard execShellCmd(&"yt-dlp {args.join(\" \")} --external-downloader aria2c --external-downloader-args '-x 16 -s 16 -k 2M'") else: - discard execShellCmd(&"youtube-dl {args.join(\" \")}") + discard execShellCmd(&"yt-dlp {args.join(\" \")}") proc luckyDownload*(searchQuery: string, options: Options) = - let args = @[&"ytsearch:\"{searchQuery}\""] & buildDownloadArgs("", options) - let title = execProcess(&"youtube-dl --get-title {args.join(\" \")}").split("\n")[0] + let args = @[&"ytsearch1:\"{searchQuery}\""] & buildDownloadArgs("", options) + let title = execProcess(&"yt-dlp --get-title {args.join(\" \")}").split("\n")[0] download(args, title) proc luckyPlay*(searchQuery: string, player: string, options: Options) = let args = @[&"ytsearch:\"{searchQuery}\""] & buildDownloadArgs("", options) - let output = execProcess(&"youtube-dl --get-url --get-title {args.join(\" \")}").split("\n") + let output = execProcess(&"yt-dlp --get-url --get-title {args.join(\" \")}").split("\n") let title = output[0] url = &"\"{output[1]}\"" -- 2.43.0 From 62e4d409fe321dff3ef519f88df839c458fcfa49 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Fri, 3 Dec 2021 16:52:12 +0530 Subject: [PATCH 3/6] peertube: Shift from UUID to short video id format Signed-off-by: Joseph Nuthalapati --- src/lib.nim | 2 +- src/peertube.nim | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.nim b/src/lib.nim index 3dcf78a..c88c4ed 100644 --- a/src/lib.nim +++ b/src/lib.nim @@ -17,7 +17,7 @@ import let processOptions = {poStdErrToStdOut, poUsePath} # Add poEchoCmd to debug - PEERTUBE_REGEX = re"videos\/watch\/[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}" + PEERTUBE_REGEX = re"w\/[0-9a-zA-z]{22}" proc isInstalled(program: string): bool = diff --git a/src/peertube.nim b/src/peertube.nim index 36f1054..946736f 100644 --- a/src/peertube.nim +++ b/src/peertube.nim @@ -5,11 +5,11 @@ import strformat, strutils -let PEERTUBE_REGEX = re"videos\/watch\/[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}" +let PEERTUBE_REGEX = re"w\/[0-9a-zA-z]{22}" proc getPeerTubeMagnetLink*(url: string): string = ## Gets the magnet link of the best possible resolution from PeerTube - let uuid = url.substr(find(url, PEERTUBE_REGEX) + "videos/watch/".len) + let uuid = url.substr(find(url, PEERTUBE_REGEX) + "w/".len) let domainName = url.substr(8, find(url, '/', start=8) - 1) let apiURL = &"https://{domainName}/api/v1/videos/{uuid}" let client = newHttpClient() -- 2.43.0 From f114ff9a9ec2477cf9b8fe62283b28794d49fcab Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Fri, 3 Dec 2021 17:21:44 +0530 Subject: [PATCH 4/6] Get rid of Peerflix. Only use Webtorrent. Signed-off-by: Joseph Nuthalapati --- README.md | 6 +++--- src/lib.nim | 6 ++---- src/peertube.nim | 10 ++++++++-- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fa32d61..6e88ecf 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ I made this just for myself. The development is completely based on my needs and Nim Coon depends on the following: - yt-dlp - mpv (recommended) or vlc -- peerflix and webtorrent (for magnet links) +- webtorrent (for magnet links) Install MPV or VLC using your distribution's package manager. @@ -82,9 +82,9 @@ Install yt-dlp pip3 install --user yt-dlp ``` -Install PeerFlix and WebTorrent +Install WebTorrent ```sh -npm install --global peerflix webtorrent-cli +npm install --global webtorrent-cli ``` (Optional) If you want your YouTube downloads to be faster, install `aria2` download manager. diff --git a/src/lib.nim b/src/lib.nim index c88c4ed..4064ae4 100644 --- a/src/lib.nim +++ b/src/lib.nim @@ -82,14 +82,12 @@ proc play*(player: string, options: Table[string, bool], url: string, title: str proc directPlay*(url: string, player: string, options: Table[string, bool]) = let url = if find(url, PEERTUBE_REGEX) != -1 and "webtorrent".isInstalled: - getPeerTubeMagnetLink(url) + getPeerTubeMagnetLink(url, options["musicOnly"]) else: url if url.startswith("magnet:") or url.endswith(".torrent"): if options["musicOnly"]: - # TODO Replace with WebTorrent once it supports media player options - discard execShellCmd(&"peerflix '{url}' -a --{player} -- --no-video") + discard execShellCmd(&"webtorrent '{url}' --{player} --player-args='--no-video'") else: - # WebTorrent is so much faster! discard execProcess("webtorrent", args=[url, &"--{player}"], options=processOptions) else: play(player, options, url) diff --git a/src/peertube.nim b/src/peertube.nim index 946736f..16b6d23 100644 --- a/src/peertube.nim +++ b/src/peertube.nim @@ -7,7 +7,7 @@ import let PEERTUBE_REGEX = re"w\/[0-9a-zA-z]{22}" -proc getPeerTubeMagnetLink*(url: string): string = +proc getPeerTubeMagnetLink*(url: string, musicOnly: bool): string = ## Gets the magnet link of the best possible resolution from PeerTube let uuid = url.substr(find(url, PEERTUBE_REGEX) + "w/".len) let domainName = url.substr(8, find(url, '/', start=8) - 1) @@ -15,4 +15,10 @@ proc getPeerTubeMagnetLink*(url: string): string = let client = newHttpClient() let response = get(client, apiURL) let jsonNode = parseJson($response.body) - jsonNode["files"][0]["magnetUri"].getStr() + var files = jsonNode["files"] + if len(jsonNode["files"]) == 0: + files = jsonNode["streamingPlaylists"][0]["files"] + if musicOnly: + files[len(files)-1]["magnetUri"].getStr() + else: + files[0]["magnetUri"].getStr() -- 2.43.0 From fc5bf33f392a1d189695ca7624e5320ec5c79ff0 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Fri, 3 Dec 2021 17:29:06 +0530 Subject: [PATCH 5/6] Bump version and update changelog Signed-off-by: Joseph Nuthalapati --- CHANGELOG.md | 6 ++++++ nimcoon.nimble | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 301fbdf..22a8187 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +# 0.9.0 + +- Replace youtube-dl with yt-dlp. Though this fixes the problem with YouTube throttling download speeds, it doesn't fix the throttling during streaming since mpv and vlc are still using youtube-dl. mpv has provided an option to provide an alternative youtube-dl implementation. Waiting for VLC to implement the same. +- Shift to PeerTube's new videoId format. Support for the UUID format is dropped. +- Dropped Peerflix as a dependency. WebTorrent is faster and better. They also added support for video player arguments on my request. See https://github.com/webtorrent/webtorrent-cli/issues/141 + # 0.8.3 - Add fake user-agent diff --git a/nimcoon.nimble b/nimcoon.nimble index e29c44c..92fc529 100644 --- a/nimcoon.nimble +++ b/nimcoon.nimble @@ -1,8 +1,8 @@ # Package -version = "0.8.3" +version = "0.9.0" author = "Joseph Nuthalapati" -description = "A command-line YouTube player and more" +description = "A command-line player for YouTube, PeerTube and more." license = "GPL-3.0" srcDir = "src" bin = @["nimcoon"] -- 2.43.0 From 7247fec67473ab4c98bedf683fbcbfb07f61e693 Mon Sep 17 00:00:00 2001 From: Joseph Nuthalapati Date: Fri, 9 Feb 2024 10:27:42 +0530 Subject: [PATCH 6/6] update TODO list --- TODO.org | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO.org b/TODO.org index ce4ef86..b6dbf20 100644 --- a/TODO.org +++ b/TODO.org @@ -16,3 +16,4 @@ - [ ] Better CLI using curses - select with arrows and press enter - illwill library can be used - see nim-mod project as an example +- [ ] Fix JSON parsing error thrown during search -- 2.43.0