Skip to content

Commit

Permalink
Added support for downloading through search using -s flag
Browse files Browse the repository at this point in the history
- Support for downloading only one track through search.
- Added some types and cleaned previous json decoding methods.
- Little validation : can't use <url> with `--search-and-download` flag.
  • Loading branch information
AYehia0 committed Jan 14, 2023
1 parent 298b408 commit 0131385
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 14 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/manifoldco/promptui v0.9.0
github.com/schollz/progressbar/v3 v3.13.0
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
)

require (
Expand All @@ -21,7 +22,6 @@ require (
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8 // indirect
golang.org/x/sys v0.4.0 // indirect
golang.org/x/term v0.4.0 // indirect
Expand Down
34 changes: 23 additions & 11 deletions internal/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import (
)

var defaultQuality string = "low"
var soundData = &soundcloud.SoundData{}

func Sc(args []string, bestQuality bool) {
func Sc(args []string, downloadPath string, bestQuality bool, search bool) {

url := args[0]
downloadPath := args[len(args)-1]
url := ""
if len(args) > 0 {
url = args[0]
}

if !initValidations(url) {
if url != "" && !initValidations(url) {
return
}

Expand All @@ -24,16 +27,25 @@ func Sc(args []string, bestQuality bool) {
fmt.Println("Something went wrong while getting the Client Id!")
return
}
// --search-and-download
if search {
keyword := getUserSearch()
searchResult := soundcloud.SearchTracksByKeyword(keyword, 0, clientId)

soundData := soundcloud.GetSoundMetaData(url, clientId)
if soundData == nil {
fmt.Printf("%s URL : %s doesn't return a valid track. Track is publicly accessed ?", theme.Red("[+]"), theme.Magenta(url))
return
}
// select one to download
soundData = selectSearchUrl(searchResult)
} else {

soundData = soundcloud.GetSoundMetaData(url, clientId)
if soundData == nil {
fmt.Printf("%s URL : %s doesn't return a valid track. Track is publicly accessed ?", theme.Red("[+]"), theme.Magenta(url))
return
}

fmt.Printf("%s Track found. Title : %s - Duration : %s\n", theme.Green("[+]"), theme.Magenta(soundData.Title), theme.Magenta(theme.FormatTime(soundData.Duration)))
fmt.Printf("%s Track found. Title : %s - Duration : %s\n", theme.Green("[+]"), theme.Magenta(soundData.Title), theme.Magenta(theme.FormatTime(soundData.Duration)))
}

list := soundcloud.GetFormattedDL(soundData.Transcodes.Transcodings, clientId)
list := soundcloud.GetFormattedDL(soundData, clientId)

// show available download options
qualities := getQualities(list)
Expand Down
38 changes: 38 additions & 0 deletions internal/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,41 @@ func getHighestQuality(qualities []string) string {
}
return ""
}

// select a url to download
func selectSearchUrl(searches *soundcloud.SearchResult) *soundcloud.SoundData {

titles := make([]string, 0)

for _, res := range searches.Sounds {
titles = append(titles, res.Title)
}
prompt := promptui.Select{
Label: "Choose a track to download :",
Items: titles,
}
ind, _, err := prompt.Run()
if err != nil {
os.Exit(0)
}

return &searches.Sounds[ind]
}

// prompt the input search for a keyword
func getUserSearch() string {

prompt := promptui.Prompt{
Label: "🔍Search: ",
Default: "surah yasin",
}

result, err := prompt.Run()

if err != nil {
os.Exit(0)
}

return result

}
27 changes: 25 additions & 2 deletions pkg/soundcloud/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
)

var Sound *SoundData
var SearchLimit = 6

// extract some meta data under : window.__sc_hydration
// check if the track exists and open to public
Expand All @@ -35,6 +36,11 @@ func GetSoundMetaData(url string, clientId string) *SoundData {

func GetClientId(url string) string {

if url == "" {
// the best url ever, if you find this then you're so cool :D I love you :DDD
url = "https://soundcloud.com/ahmed-yehia0"
}

statusCode, bodyData, err := client.Get(url)

if err != nil {
Expand Down Expand Up @@ -74,9 +80,10 @@ func GetClientId(url string) string {
return matches[0][1]
}

func GetFormattedDL(data []Transcode, clientId string) []DownloadTrack {
func GetFormattedDL(track *SoundData, clientId string) []DownloadTrack {
ext := "mp3" // the default extension type
tracks := make([]DownloadTrack, 0)
data := track.Transcodes.Transcodings

for _, tcode := range data {
url := tcode.ApiUrl + "?client_id=" + clientId
Expand All @@ -94,7 +101,7 @@ func GetFormattedDL(data []Transcode, clientId string) []DownloadTrack {
tmpTrack := DownloadTrack{
Url: mediaUrl.Url,
Quality: q,
SoundData: Sound,
SoundData: track,
Ext: ext,
}
tracks = append(tracks, tmpTrack)
Expand All @@ -112,3 +119,19 @@ func mapQuality(url string, format string) string {
}
return "low"
}

func SearchTracksByKeyword(keyword string, offset int, clientId string) *SearchResult {

apiUrl := GetSeachAPIUrl(keyword, SearchLimit, offset, clientId)

statusCode, body, err := client.Get(apiUrl)

if err != nil && statusCode != http.StatusOK {
return nil
}

var result = SearchResult{}
json.Unmarshal(body, &result)

return &result
}
5 changes: 5 additions & 0 deletions pkg/soundcloud/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,8 @@ type DownloadTrack struct {
Ext string
SoundData *SoundData
}

type SearchResult struct {
Sounds []SoundData `json:"collection"`
Next string `json:"next_href"`
}

0 comments on commit 0131385

Please sign in to comment.