Skip to content

Commit

Permalink
v1.0.1: support for custom instances, vimeoDash option
Browse files Browse the repository at this point in the history
  • Loading branch information
PrincessMortix committed Mar 30, 2024
1 parent fe7d9a7 commit 8f022c5
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 62 deletions.
68 changes: 66 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,66 @@
# gobalt
Go library for cobalt.tools
<div align="center">
<a href="https://pkg.go.dev/lostdusty/gobalt" title="Go API Reference" rel="nofollow"><img src="https://img.shields.io/badge/go-documentation-blue.svg?style=for-the-badge" alt="Go API Reference"></a>
<a href="https://github.com/lostdusty/gobalt/releases/lastest" title="Latest Release" rel="nofollow"><img src="https://img.shields.io/github/v/release/lostdusty/gobalt?include_prereleases&style=for-the-badge" alt="Latest Release"></a>

[![Static Badge](https://img.shields.io/badge/cobalt_discord-join-blue?style=for-the-badge&logo=discord)](https://discord.gg/pQPt8HBUPu)
[![Static Badge](https://img.shields.io/badge/supported-services-0077b6?style=for-the-badge&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NDAgNTEyIj48IS0tIUZvbnQgQXdlc29tZSBGcmVlIDYuNS4xIGJ5IEBmb250YXdlc29tZSAtIGh0dHBzOi8vZm9udGF3ZXNvbWUuY29tIExpY2Vuc2UgLSBodHRwczovL2ZvbnRhd2Vzb21lLmNvbS9saWNlbnNlL2ZyZWUgQ29weXJpZ2h0IDIwMjQgRm9udGljb25zLCBJbmMuLS0%2BPHBhdGggZD0iTTU3OS44IDI2Ny43YzU2LjUtNTYuNSA1Ni41LTE0OCAwLTIwNC41Yy01MC01MC0xMjguOC01Ni41LTE4Ni4zLTE1LjRsLTEuNiAxLjFjLTE0LjQgMTAuMy0xNy43IDMwLjMtNy40IDQ0LjZzMzAuMyAxNy43IDQ0LjYgNy40bDEuNi0xLjFjMzIuMS0yMi45IDc2LTE5LjMgMTAzLjggOC42YzMxLjUgMzEuNSAzMS41IDgyLjUgMCAxMTRMNDIyLjMgMzM0LjhjLTMxLjUgMzEuNS04Mi41IDMxLjUtMTE0IDBjLTI3LjktMjcuOS0zMS41LTcxLjgtOC42LTEwMy44bDEuMS0xLjZjMTAuMy0xNC40IDYuOS0zNC40LTcuNC00NC42cy0zNC40LTYuOS00NC42IDcuNGwtMS4xIDEuNkMyMDYuNSAyNTEuMiAyMTMgMzMwIDI2MyAzODBjNTYuNSA1Ni41IDE0OCA1Ni41IDIwNC41IDBMNTc5LjggMjY3Ljd6TTYwLjIgMjQ0LjNjLTU2LjUgNTYuNS01Ni41IDE0OCAwIDIwNC41YzUwIDUwIDEyOC44IDU2LjUgMTg2LjMgMTUuNGwxLjYtMS4xYzE0LjQtMTAuMyAxNy43LTMwLjMgNy40LTQ0LjZzLTMwLjMtMTcuNy00NC42LTcuNGwtMS42IDEuMWMtMzIuMSAyMi45LTc2IDE5LjMtMTAzLjgtOC42Qzc0IDM3MiA3NCAzMjEgMTA1LjUgMjg5LjVMMjE3LjcgMTc3LjJjMzEuNS0zMS41IDgyLjUtMzEuNSAxMTQgMGMyNy45IDI3LjkgMzEuNSA3MS44IDguNiAxMDMuOWwtMS4xIDEuNmMtMTAuMyAxNC40LTYuOSAzNC40IDcuNCA0NC42czM0LjQgNi45IDQ0LjYtNy40bDEuMS0xLjZDNDMzLjUgMjYwLjggNDI3IDE4MiAzNzcgMTMyYy01Ni41LTU2LjUtMTQ4LTU2LjUtMjA0LjUgMEw2MC4yIDI0NC4zeiIvPjwvc3ZnPg%3D%3D&logoColor=0077b6)](https://github.com/wukko/cobalt?tab=readme-ov-file#supported-services)
<h1>gobalt</h1>
</div>

Gobalt provides a way to communicate with [cobalt.tools](https://cobalt.tools) using Go. To use it in your projects, simply run this command:
```sh
go get https://github.com/lostdusty/gobalt
```

## Usage
First, make sure you call `gobalt.CreateDefaultSettings()` to create the `Settings` struct with default values, then set an url.

```go
//Creates a Settings struct with default values, and save it to downloadMedia variable.
downloadMedia := gobalt.CreateDefaultSettings()

//Sets the URL, you MUST set one before downloading the media.
downloadMedia.Url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

//After changing the url, Do() will make the necessary requests to cobalt to download your media
destination, err := gobalt.Do(downloadMedia)
if err != nil {
//Handle errors here
}

//Prints out the url from cobalt to download the requested media.
fmt.Println(destination.URL)
//Output example: https://us4-co.wuk.sh/api/stream?t=wTn-71aaWAcV2RBejNFNV&e=1711777798864&h=fMtwwtW8AUmtTLB24DGjJJjrq1EJDBFaCDoDuZpX0pA&s=_YVZhz8fnzBBKKo7UZmGWOqfe4wWwH5P1azdgBqwf-I&i=6tGZqAXbW08_6KmAiLevZA
```

## Features
### Server info
You can query information about any cobalt server by using `CobaltServerInfo(apiurl)`. This will return a `ServerInfo` struct with [this info](https://github.com/wukko/cobalt/blob/current/docs/api.md#response-body-variables-1).

Example code:
```go
server, err := gobalt.CobaltServerInfo(gobalt.CobaltApi)
if err != nil {
//Handle the error here
}
fmt.Printf("Downloading from %v!\n", server.URL)
//Output: Downloading from https://us4-co.wuk.sh/!
```

### Use/Query other cobalt instances
Using `GetCobaltInstances()` fetches a community maintaned list of third-party cobalt instances ran by the community, except for ``*-co.wuk.sh``, none of them are "official" cobalt instances. Use them if you can't download from the main instance for whatever reason.

Example:
```go
cobalt, err := gobalt.GetCobaltInstances()
if err != nil {
//Handle errors here
}
fmt.Printf("Found %v online cobalt servers: ", len(cobalt))
for _, value := range cobalt {
fmt.Printf("%v, ", value.URL)
}
/* Output:
* Found 8 online cobalt servers: co.wuk.sh, cobalt-api.hyper.lol, cobalt.api.timelessnesses.me, api-dl.cgm.rs, cobalt.synzr.space, capi.oak.li, co.tskau.team, api.co.rooot.gay
*/
```
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/princessmortix/gobalt
module github.com/lostdusty/gobalt

go 1.21.5
176 changes: 117 additions & 59 deletions gobalt.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package Gobalt provides a go way to communicate with https://cobalt.tools servers.
package gobalt

import (
Expand All @@ -8,17 +9,18 @@ import (
"net/http"
"net/url"
"regexp"
"runtime"
"strings"
"time"
)

var (
CobaltApi = "https://co.wuk.sh" //Override this value to use your own cobalt instance. See https://instances.hyper.lol/ for alternatives from the main instance.
UserLanguage = "en" //Replace this following the ISO 639-1 standard. This downloads dubbed YouTube audio according to the language set here. Only takes effect if DubbedYoutubeAudio is set to true.
useragent = "Gobalt/1.0"
useragent = fmt.Sprintf("Mozilla/5.0 (%v; %v); gobalt/v1.0.2 (%v; %v); +(https://github.com/lostdusty/gobalt)", runtime.GOOS, runtime.GOARCH, runtime.Compiler, runtime.Version())
)

type serverInfo struct {
type ServerInfo struct {
Version string `json:"version"` //cobalt version
Commit string `json:"commit"` //git commit
Branch string `json:"branch"` //git branch
Expand All @@ -40,19 +42,31 @@ type cobaltResponse struct {
URLs []string //If the status is picker all the urls will go here.
}

type CobaltInstances []struct {
Cors int `json:"cors"`
Commit string `json:"commit,omitempty"`
Name string `json:"name,omitempty"`
StartTime int64 `json:"startTime"`
API string `json:"api"`
Version string `json:"version"`
Branch string `json:"branch,omitempty"`
FrontEnd string `json:"frontEnd"`
Status bool `json:"status"`
}

type Settings struct {
Url string `json:"url"` //Any URL from bilibili.com, instagram, pinterest, reddit, rutube, soundcloud, streamable, tiktok, tumblr, twitch clips, twitter/x, vimeo, vine archive, vk or youtube. Will be url encoded later.
VideoCodec codecs `json:"vCodec"` //H264, AV1 or VP9, defaults to H264.
VideoQuality int `json:"vQuality,string"` //144p to 2160p (4K), if not specified will default to 1080p.
AudioCodec audioCodec `json:"aFormat"` //MP3, Opus, Ogg or Wav. If not specified will default to best.
FilenamePattern pattern `json:"filenamePattern"` //Classic, Basic, Pretty or Nerdy. Defaults to Pretty
AudioOnly bool `json:"isAudioOnly"` //Removes the video, downloads audio only. Default: false
//RemoveTikTokWatermark bool `json:"isNoTTWatermark"` //Removes TikTok watermark from TikTok videos. Default: false
FullTikTokAudio bool `json:"isTTFullAudio"` //Enables download of original sound used in a tiktok video. Default: false
VideoOnly bool `json:"isAudioMuted"` //Downloads only the video, audio is muted/removed. Default: false
DubbedYoutubeAudio bool `json:"dubLang"` //Pass the User-Language HTTP header to use the dubbed audio of the respective language, must change according to user's preference, default is English (US). Uses ISO 639-1 standard.
DisableVideoMetadata bool `json:"disableMetadata"` //Removes file metadata. Default: false
ConvertTwitterGifs bool `json:"twitterGif"` //Changes whether twitter gifs are converted to .gif (Twitter gifs are usually stored in .mp4 format). Default: true
Url string `json:"url"` //Any URL from bilibili.com, instagram, pinterest, reddit, rutube, soundcloud, streamable, tiktok, tumblr, twitch clips, twitter/x, vimeo, vine archive, vk or youtube. Will be url encoded later.
VideoCodec codecs `json:"vCodec"` //H264, AV1 or VP9, defaults to H264.
VideoQuality int `json:"vQuality,string"` //144p to 2160p (4K), if not specified will default to 1080p.
AudioCodec audioCodec `json:"aFormat"` //MP3, Opus, Ogg or Wav. If not specified will default to best.
FilenamePattern pattern `json:"filenamePattern"` //Classic, Basic, Pretty or Nerdy. Defaults to Pretty
AudioOnly bool `json:"isAudioOnly"` //Removes the video, downloads audio only. Default: false
UseVimeoDash bool `json:"vimeoDash"` //Changes whether streamed file type is preferred for vimeo videos.. Default: false
FullTikTokAudio bool `json:"isTTFullAudio"` //Enables download of original sound used in a tiktok video. Default: false
VideoOnly bool `json:"isAudioMuted"` //Downloads only the video, audio is muted/removed. Default: false
DubbedYoutubeAudio bool `json:"dubLang"` //Pass the User-Language HTTP header to use the dubbed audio of the respective language, must change according to user's preference, default is English (US). Uses ISO 639-1 standard.
DisableVideoMetadata bool `json:"disableMetadata"` //Removes file metadata. Default: false
ConvertTwitterGifs bool `json:"twitterGif"` //Changes whether twitter gifs are converted to .gif (Twitter gifs are usually stored in .mp4 format). Default: true
}

type codecs string
Expand Down Expand Up @@ -82,38 +96,35 @@ const (
Pretty pattern = "pretty" //Looks like: Video Title (1080p, h264, youtube).mp4 | audio: Audio Title - Audio Author (soundcloud).mp3
)

/*
Function CreateDefaultSettings() creates the Settings struct with default values:
Url: ""
VideoCodec: H264,
VideoQuality: 1080,
AudioCodec: Best,
FilenamePattern: Pretty,
AudioOnly: false,
FullTikTokAudio: false,
VideoOnly: false,
DubbedYoutubeAudio: false,
DisableVideoMetadata: false,
ConvertTwitterGifs: false,
You MUST set an url before calling Run().
*/
//Function CreateDefaultSettings() creates the Settings struct with default values:

// Url: ""
// VideoCodec: H264,
// VideoQuality: 1080,
// AudioCodec: Best,
// FilenamePattern: Pretty,
// AudioOnly: false,
// FullTikTokAudio: false,
// VideoOnly: false,
// DubbedYoutubeAudio: false,
// DisableVideoMetadata: false,
// ConvertTwitterGifs: false,
// You MUST set an url before calling Run().
func CreateDefaultSettings() Settings {

options := Settings{
Url: "",
VideoCodec: H264,
VideoQuality: 1080,
AudioCodec: Best,
FilenamePattern: Pretty,
AudioOnly: false,
//RemoveTikTokWatermark: false,
FullTikTokAudio: false,
VideoOnly: false,
DubbedYoutubeAudio: false,
DisableVideoMetadata: false,
ConvertTwitterGifs: true,
Url: "",
VideoCodec: H264,
VideoQuality: 1080,
AudioCodec: Best,
FilenamePattern: Pretty,
AudioOnly: false,
UseVimeoDash: false,
FullTikTokAudio: false,
VideoOnly: false,
DubbedYoutubeAudio: false,
DisableVideoMetadata: false,
ConvertTwitterGifs: true,
}
return options
}
Expand All @@ -135,18 +146,18 @@ func Run(opts Settings) (*cobaltResponse, error) {
}

optionsPayload := Settings{
Url: url.QueryEscape(opts.Url),
VideoCodec: opts.VideoCodec,
VideoQuality: opts.VideoQuality,
AudioCodec: opts.AudioCodec,
FilenamePattern: opts.FilenamePattern,
AudioOnly: opts.AudioOnly,
//RemoveTikTokWatermark: opts.RemoveTikTokWatermark,
FullTikTokAudio: opts.FullTikTokAudio,
VideoOnly: opts.VideoOnly,
DubbedYoutubeAudio: opts.DubbedYoutubeAudio,
DisableVideoMetadata: opts.DisableVideoMetadata,
ConvertTwitterGifs: opts.ConvertTwitterGifs,
Url: url.QueryEscape(opts.Url),
VideoCodec: opts.VideoCodec,
VideoQuality: opts.VideoQuality,
AudioCodec: opts.AudioCodec,
FilenamePattern: opts.FilenamePattern,
AudioOnly: opts.AudioOnly,
UseVimeoDash: opts.UseVimeoDash,
FullTikTokAudio: opts.FullTikTokAudio,
VideoOnly: opts.VideoOnly,
DubbedYoutubeAudio: opts.DubbedYoutubeAudio,
DisableVideoMetadata: opts.DisableVideoMetadata,
ConvertTwitterGifs: opts.ConvertTwitterGifs,
}
payload, _ := json.Marshal(optionsPayload)

Expand Down Expand Up @@ -197,8 +208,8 @@ func Run(opts Settings) (*cobaltResponse, error) {
}

// This function is called before Run() to check if the cobalt server used is reachable.
// If you can't contact the main server, you should using one of the instances listed in https://instances.hyper.lol/.
func CobaltServerInfo(api string) (*serverInfo, error) {
// If you can't contact the main server, try getting another instance using GetCobaltinstances().
func CobaltServerInfo(api string) (*ServerInfo, error) {
//Check if the server is reachable
client := &http.Client{
Timeout: 15 * time.Second,
Expand All @@ -220,13 +231,13 @@ func CobaltServerInfo(api string) (*serverInfo, error) {
return nil, err
}

var serverResponse serverInfo
var serverResponse ServerInfo
err = json.Unmarshal(jsonbody, &serverResponse)
if err != nil {
return nil, err
}
res.Body.Close()
return &serverInfo{
return &ServerInfo{
Branch: serverResponse.Branch,
Commit: serverResponse.Commit,
Name: serverResponse.Name,
Expand All @@ -236,3 +247,50 @@ func CobaltServerInfo(api string) (*serverInfo, error) {
StartTime: serverResponse.StartTime,
}, nil
}

// GetCobaltInstances makes a request to instances.hyper.lol and returns a list of all online cobalt instances.
func GetCobaltInstances() ([]ServerInfo, error) {
client := &http.Client{
Timeout: 5 * time.Second,
}
req, err := http.NewRequest("GET", "https://instances.hyper.lol/instances.json", nil)
req.Header.Add("User-Agent", useragent)
if err != nil {
return nil, err
}

res, err := client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()

jsonbody, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}

var cobaltHyperInstances CobaltInstances
err = json.Unmarshal(jsonbody, &cobaltHyperInstances)
if err != nil {
return nil, err
}
res.Body.Close()

instancesList := make([]ServerInfo, 0)

for _, v := range cobaltHyperInstances {
if v.Status {
instancesList = append(instancesList, ServerInfo{
Version: v.Version,
Commit: v.Commit,
Branch: v.Branch,
Name: v.Name,
URL: v.API,
Cors: v.Cors,
StartTime: fmt.Sprint(v.StartTime),
})
}
}
return instancesList, nil
}

0 comments on commit 8f022c5

Please sign in to comment.