Skip to content

Commit

Permalink
v1.0.7: don't panic, describe your error better
Browse files Browse the repository at this point in the history
  • Loading branch information
lostdusty committed Jun 21, 2024
1 parent 6bd4964 commit 8df52f5
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 63 deletions.
59 changes: 35 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,20 @@ Unofficial [cobalt](https://cobalt.tools) command line client made in go. cobalt
|-----------------|--------------------|
| Windows | [**x64**](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-windows-amd64.zip) / [x86](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-windows-386.zip) / [arm](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-windows-arm.zip) |
| Linux | [**x64**](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-linux-amd64.tar.gz) / [x86](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-linux-386.tar.gz) / [arm64](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-linux-arm64.tar.gz) |
| MacOS | [Intel](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-darwin-amd64.tar.gz) / [**M1, M2, M3**](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-darwin-arm64.tar.gz) |
| Mac | [Intel](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-darwin-amd64.tar.gz) / [**M1, M2, M3**](https://github.com/princessmortix/cobalt/releases/latest/download/cobalt-darwin-arm64.tar.gz) |

You can also check the [releases page](https://github.com/princessmortix/cobalt/releases/latest) to download the latest version according to your platform.

Alternatively, if you have Go installed, you can use `go install github.com/lostdusty/cobalt@latest` to install to your machine.

## Roadmap
Planned features for cobalt-cli:

- [x] Json output;
- [ ] Time expiration for the returned url.
- [ ] Option to save file to the current/custom folder, likely `-s` flag;
- [ ] Display progress bar to track download progress (when supported by cobalt).
- [ ] Hability to use custom downloader program (wget, curl, got, etc);
- [ ] Hability to use custom downloader program (wget, curl, got, etc);
- [ ] Translations.


Expand All @@ -50,13 +52,21 @@ cobalt-cli has two subcommands:
- download: downloads something using cobalt
- instances: lists all known cobalt instances

```
Usage: cobalt <command>
Commands:
download - Use this command to download something.
instances - Use this command to view stats about other cobalt instances.
Error: No command was provided. Please specify a command.
```

### Download
```
usage: cobalt download [-h|--help] [-u|--url "<value>"] [-c|--video-codec
(av1|vp9|h264)] [-q|--video-quality
(144|240|360|480|720|1080|1440|2160)] [-f|--audio-format
(opus|ogg|wav|mp3|best)] [-p|--filename-pattern
(basic|pretty|nerdy|classic)] [-a|--no-video] [-V|--vimeo-dash]
(basic|pretty|nerdy|classic)] [-a|--no-video] [-T|--tiktok-h265]
[-t|--full-tiktok-audio] [-v|--no-audio] [-d|--dubbed-audio]
[-m|--metadata] [-g|--gif] [-j|--json] [-s|--status] [-i|--api
"<value>"] [-l|--language "<value>"] [-b|--browser]
Expand All @@ -71,9 +81,10 @@ Arguments:
downloads. AV1: 8K/HDR, lower support | VP9: 4K/HDR,
best quality | H264: 1080p, works everywhere.
Default: h264
-q --video-quality Quality of the video. Default: 1080
-f --audio-format Audio format/codec to be used. Using the default the
audio won't be re-encoded. Default: best
-q --video-quality Quality of the video, also applies only to youtube
downloads. Default: 1080
-f --audio-format Audio format/codec to be used. "best" doesn't
re-encodes the audio. Default: best
-p --filename-pattern File name pattern. Classic:
youtube_yPYZpwSpKmA_1920x1080_h264.mp4 | audio:
youtube_yPYZpwSpKmA_audio.mp3 // Basic: Video Title
Expand All @@ -84,32 +95,32 @@ Arguments:
youtube, yPYZpwSpKmA).mp4 | audio: Audio Title -
Audio Author (soundcloud, 1242868615).mp3. Default:
pretty
-a --no-video Extract audio only. Default: false
-V --vimeo-dash Downloads Vimeo videos using dash instead of
progressive. Default: false
-t --full-tiktok-audio Enables download of original sound used in a tiktok
video. Default: false
-a --no-video Downloads only the audio, and removes the video.
Default: false
-T --tiktok-h265 Downloads TikTok videos using h265 codec. Default:
false
-t --full-tiktok-audio Download the original sound used in a tiktok video.
Default: false
-v --no-audio Downloads only the video, without audio, when
possible. Default: false
-d --dubbed-audio Downloads youtube audio dubbed, if present. Change
the language using -l <ISO 639-1 format>. Default:
false
-m --metadata Disables file metadata. Default: false
-g --gif Disables conversion of twitter gifs to a .gif file.
Default: true
-j --json Output to stdin as json. Default: false
-s --status Will only check status of the select cobalt server,
print and exit. All other options will be ignored,
except -j. Default: false
-i --api Change the cobalt api endpoint to be used. See
others instances in https://instances.hyper.lol.
Default: https://co.wuk.sh
-g --gif Convert twitter gifs to .gif. Default: true
-j --json Output to stdout as json
-s --status Check status of the selected cobalt server, prints
and exits. All other options will be ignored, except
-j | --json. Default: false
-i --api Change the cobalt api url used. See others instances
in https://instances.hyper.lol. Default:
https://api.cobalt.tools
-l --language Downloads dubbed youtube audio according to the
language set following the ISO 639-1 format. Only
takes effect if -d was passed as an argument.
Default: en
-b --browser Opens the response link in default browser, if
successful. Default: false
-b --browser Downloads the requested media in your browser.
Default: false
```

### Instances
Expand All @@ -125,7 +136,7 @@ Arguments:
```

## JSON Output
See the documentation for the json output of cobalt-cli.
Documentation for the json output of cobalt-cli.
### Download
All json output from the download subcommands follows this format:
```json
Expand Down Expand Up @@ -177,7 +188,7 @@ Check out too:


# About & Thanks
- [cobalt](https://github.com/wukko/cobalt) made by [wukko](https://github.com/wukko) && [jj](https://github.com/dumbmoron), super cool people;
- [cobalt](https://github.com/imputnet/cobalt) made by [wukko](https://github.com/wukko) && [jj](https://github.com/dumbmoron), cool people;
- [argparse](https://github.com/akamensky/argparse), for handling args;
- Icon made by [me](https://lostdusty.com.br);
- You, for using my application!
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ go 1.21.6
require (
github.com/akamensky/argparse v1.4.0
github.com/emvi/iso-639-1 v1.1.0
github.com/lostdusty/gobalt v1.0.6
github.com/lostdusty/gobalt v1.0.7
github.com/mergestat/timediff v0.0.3
)

require (
github.com/jedib0t/go-pretty/v6 v6.5.8
github.com/jedib0t/go-pretty/v6 v6.5.9
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/sys v0.21.0 // indirect
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emvi/iso-639-1 v1.1.0 h1:EhZiYVA+ysa/b7+0T2DD9hcX7E/5sh4o1KyDAIPu7VE=
github.com/emvi/iso-639-1 v1.1.0/go.mod h1:CSA53/Tx0xF9bk2DEA0Mr0wTdIxq7pqoVZgBOfoL5GI=
github.com/jedib0t/go-pretty/v6 v6.5.8 h1:8BCzJdSvUbaDuRba4YVh+SKMGcAAKdkcF3SVFbrHAtQ=
github.com/jedib0t/go-pretty/v6 v6.5.8/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
github.com/lostdusty/gobalt v1.0.6 h1:vCVAlZS7dyc8x3Xdt4WmMeO9v2wriSIXwaK+binNz2U=
github.com/lostdusty/gobalt v1.0.6/go.mod h1:gv+Hmbv0SC3lWpJvUvxJYRmmcuBjlmhKCIRskk0lSjY=
github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+UV8OU=
github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E=
github.com/lostdusty/gobalt v1.0.7 h1:8iL4eqp4NGn4lw9URYHD9DZYtIBMs2m81MWE+a9w/NM=
github.com/lostdusty/gobalt v1.0.7/go.mod h1:gv+Hmbv0SC3lWpJvUvxJYRmmcuBjlmhKCIRskk0lSjY=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mergestat/timediff v0.0.3 h1:ucCNh4/ZrTPjFZ081PccNbhx9spymCJkFxSzgVuPU+Y=
Expand All @@ -19,7 +19,7 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
93 changes: 67 additions & 26 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ func main() {

optionVideoQuality := doDownload.Selector("q", "video-quality", []string{"144", "240", "360", "480", "720", "1080", "1440", "2160"}, &argparse.Options{
Required: false,
Help: "Quality of the video",
Help: "Quality of the video, also applies only to youtube downloads",
Default: "1080",
})

optionAudioFormat := doDownload.Selector("f", "audio-format", []string{"opus", "ogg", "wav", "mp3", "best"}, &argparse.Options{
Required: false,
Help: "Audio format/codec to be used. Using the default the audio won't be re-encoded",
Help: "Audio format/codec to be used. \"best\" doesn't re-encodes the audio",
Default: "best",
})

Expand All @@ -58,19 +58,19 @@ func main() {

optionAudioOnly := doDownload.Flag("a", "no-video", &argparse.Options{
Required: false,
Help: "Extract audio only",
Help: "Downloads only the audio, and removes the video",
Default: false,
})

optionVimeoDash := doDownload.Flag("V", "vimeo-dash", &argparse.Options{
optionTikTokH265 := doDownload.Flag("T", "tiktok-h265", &argparse.Options{
Required: false,
Help: "Downloads Vimeo videos using dash instead of progressive",
Help: "Downloads TikTok videos using h265 codec",
Default: false,
})

optionFullTikTokAudio := doDownload.Flag("t", "full-tiktok-audio", &argparse.Options{
Required: false,
Help: "Enables download of original sound used in a tiktok video",
Help: "Download the original sound used in a tiktok video",
Default: false,
})

Expand All @@ -94,21 +94,28 @@ func main() {

optionConvertTwitterGif := doDownload.Flag("g", "gif", &argparse.Options{
Required: false,
Help: "Disables conversion of twitter gifs to a .gif file",
Help: "Convert twitter gifs to .gif",
Default: true,
})

var outputJson, jsonOutput = doDownload.Flag("j", "json", &argparse.Options{Required: false, Help: "Output to stdout as json"}), getCobaltInstances.Flag("j", "json", &argparse.Options{Required: false, Help: "Output to stdout as json"})
var outputJson, jsonOutput = doDownload.Flag("j", "json", &argparse.Options{
Required: false,
Help: "Output to stdout as json",
}),
getCobaltInstances.Flag("j", "json", &argparse.Options{
Required: false,
Help: "Output to stdout as json",
})

commandStatus := doDownload.Flag("s", "status", &argparse.Options{
Required: false,
Help: "Will only check status of the select cobalt server, print and exit. All other options will be ignored, except -j",
Help: "Check status of the selected cobalt server, prints and exits. All other options will be ignored, except -j | --json",
Default: false,
})

customCobaltApi := doDownload.String("i", "api", &argparse.Options{
Required: false,
Help: "Change the cobalt api endpoint to be used. See others instances in https://instances.hyper.lol",
Help: "Change the cobalt api url used. See others instances in https://instances.hyper.lol",
Default: gobalt.CobaltApi,
})

Expand All @@ -120,22 +127,30 @@ func main() {

openInBrowser := doDownload.Flag("b", "browser", &argparse.Options{
Required: false,
Help: "Opens the response link in default browser, if successful",
Help: "Downloads the requested media in your browser",
Default: false,
})

err := flagParser.Parse(os.Args)
if err != nil && errors.Is(err, flagParser.Parse(os.Args)) {
panic(fmt.Errorf("expected sub-command '%v' or '%v'", doDownload.GetName(), getCobaltInstances.GetName()))
fmt.Print(`Usage: cobalt <command>
Commands:
  download  - Use this command to download something.
  instances - Use this command to view stats about other cobalt instances.
Error: No command was provided. Please specify a command.
`)
return
}

if getCobaltInstances.Happened() {
err := getInstances(*jsonOutput)
if err != nil {
if *jsonOutput {
panic(errorJson(err))
fmt.Println(errorJson(err))
return
}
panic(err)
fmt.Println(err)
return
}
return
}
Expand All @@ -144,9 +159,11 @@ func main() {
err := checkStatus(*customCobaltApi, *outputJson)
if err != nil {
if *jsonOutput {
panic(errorJson(err))
fmt.Println(errorJson(err))
return
}
panic(err)
fmt.Println(err)
return
}
return
}
Expand All @@ -159,9 +176,11 @@ func main() {
validateLanguage := iso6391.ValidCode(strings.ToLower(*customLanguage))
if !validateLanguage {
if *outputJson {
panic(fmt.Errorf("invalid language code, check if the language code is following ISO 639-1 format"))
fmt.Println(fmt.Errorf("invalid language code, check if the language code is following ISO 639-1 format"))
return
}
panic("Invalid language code: " + *customLanguage)
fmt.Println("Invalid language code: " + *customLanguage)
return
}

newSettings := gobalt.CreateDefaultSettings()
Expand Down Expand Up @@ -208,24 +227,28 @@ func main() {
newSettings.DisableVideoMetadata = *optionDisableMetadata
newSettings.DubbedYoutubeAudio = *optionDubAudio
newSettings.FullTikTokAudio = *optionFullTikTokAudio
newSettings.UseVimeoDash = *optionVimeoDash
newSettings.TikTokH265 = *optionTikTokH265
newSettings.Url = *URL
newSettings.VideoOnly = *optionVideoOnly
quality, err := strconv.Atoi(*optionVideoQuality)
if err != nil {
if *outputJson {
panic(fmt.Errorf("expected int on flag -q, got something else: %s", *optionVideoQuality))
fmt.Println(fmt.Errorf("expected int on flag -q, got something else: %s", *optionVideoQuality))
return
}
panic(fmt.Errorf("expected int on flag -q, got something else: %s\nError details: %e", *optionVideoQuality, err))
fmt.Println(fmt.Errorf("expected int on flag -q, got something else: %s\nError details: %e", *optionVideoQuality, err))
return
}
newSettings.VideoQuality = quality

cobaltRequest, err := gobalt.Run(newSettings)
if err != nil {
if *outputJson {
panic(errorJson(err))
fmt.Println(errorJson(err))
return
}
panic(err)
fmt.Println(err)
return
}

if *outputJson {
Expand Down Expand Up @@ -257,7 +280,7 @@ func main() {
for _, urls := range cobaltRequest.URLs {
err := openInDefaultBrowser(urls)
if err != nil {
fmt.Println("Failed to open URL on default browser:", err)
fmt.Printf("Failed to open URL on default browser: %v\nWill print instead.", err)
}
}
}
Expand Down Expand Up @@ -335,9 +358,9 @@ func getInstances(args bool) error {

instancesTable := table.NewWriter()
instancesTable.SetOutputMirror(os.Stdout)
instancesTable.AppendHeader(table.Row{"name", "api url (frontend)", "api online (frontend)", "cors", "since", "version (branch, commit)"})
instancesTable.AppendHeader(table.Row{"name", "api url (frontend)", "API/Front online", "cors", "since", "version (branch, commit)"})
for _, v := range instances {
instancesTable.AppendRow(table.Row{v.Name, fmt.Sprintf("%v (front: %v)", v.URL, v.FrontendUrl), fmt.Sprintf("%v (front: %v)", v.ApiOnline, v.FrontEndOnline), v.Cors, utilHumanTime(v.StartTime), fmt.Sprintf("%v (%v, %v)", v.Version, v.Branch, v.Commit)})
instancesTable.AppendRow(table.Row{v.Name, fmt.Sprintf("%v (front: %v)", v.URL, v.FrontendUrl), fmt.Sprintf("%v", resolveApiFrontOnline(v.ApiOnline, v.FrontEndOnline)), resolveCors(v.Cors), utilHumanTime(v.StartTime), fmt.Sprintf("%v (%v, %v)", v.Version, v.Branch, v.Commit)})
}
instancesTable.SetStyle(table.StyleRounded)
instancesTable.Render()
Expand All @@ -349,3 +372,21 @@ func utilHumanTime(unixTime int64) string {
since := time.UnixMilli(unixTime)
return timediff.TimeDiff(since)
}

func resolveApiFrontOnline(api, front bool) string {
a, f := "no", "no"
if api {
a = "yes"
}
if front {
f = "yes"
}
return fmt.Sprintf("%s/%s", a, f)
}

func resolveCors(cors int) string {
if cors == 1 {
return "on"
}
return "off"
}
Loading

0 comments on commit 8df52f5

Please sign in to comment.