package download
import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"os/exec"
"regexp"
"strings"
"github.com/gocolly/colly"
"github.com/joho/godotenv"
)
var ()
const (
HOST_URL = "https://www.bilibili.com"
API_PREURL = "https://api.bilibili.com/x/web-interface/view?bvid="
VID_PREURL = "https://www.bilibili.com/video/"
)
func MusicUrl(bv string) (url_list []string) {
collector := colly.NewCollector()
collector.OnResponse(func(r *colly.Response) {
var (
rtext string
rtemp string
rjson map[string]interface{}
re *regexp.Regexp
// url_list []string
)
rtext = string(r.Body)
re, _ = regexp.Compile(``)
rtemp = re.FindAllString(rtext, 1)[0]
re, _ = regexp.Compile(``)
rtemp = re.ReplaceAllString(rtemp, "")
json.Unmarshal([]byte(rtemp), &rjson)
url_list = append(url_list, fmt.Sprintf("%v", rjson["data"].(map[string]interface{})["dash"].(map[string]interface{})["audio"].([]interface{})[0].(map[string]interface{})["baseUrl"].(string)))
url_list = append(url_list, fmt.Sprintf("%v", rjson["data"].(map[string]interface{})["dash"].(map[string]interface{})["audio"].([]interface{})[0].(map[string]interface{})["base_url"].(string)))
for _, url := range rjson["data"].(map[string]interface{})["dash"].(map[string]interface{})["audio"].([]interface{})[0].(map[string]interface{})["backupUrl"].([]interface{}) {
url_list = append(url_list, fmt.Sprintf("%v", url))
}
// fmt.Println(len(url_list))
})
collector.Visit(VID_PREURL + bv)
return url_list
}
func MusicDownload(url_list []string, title string) bool {
godotenv.Load()
result := false
title = strings.Replace(title, "/", "&", -1)
title = strings.Replace(title, "\"", "'", -1)
for _, url := range url_list {
var (
response *http.Response
m4afile *os.File
)
var (
err1 error
err2 error
err3 error
)
for i := 0; i < 3; i++ {
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3")
req.Header.Set("Referer", HOST_URL)
client := &http.Client{}
response, err1 = client.Do(req)
if err1 != nil {
// fmt.Println("Get url error")
continue
}
break
}
defer response.Body.Close()
if _, direrr := os.Stat("temp/"); os.IsNotExist(direrr) {
os.Mkdir("temp/", 0755)
}
if _, direrr := os.Stat("music/"); os.IsNotExist(direrr) {
os.Mkdir("music/", 0755)
}
os.Chdir("temp/")
m4afile, err2 = os.Create(title + ".m4a")
// return true
if err2 != nil {
fmt.Println("Create file error")
}
defer m4afile.Close()
_, err3 = io.Copy(m4afile, response.Body)
if err3 != nil {
fmt.Println("Copy file error")
continue
}
fmt.Println(title)
// cmd := exec.Command(`ffmpeg`, `-i`, "\""+title+".m4a"+"\"", `-vn`, `-ar`, `44100`, `-ac`, `2`, `-ab`, `192k`, `-f`, `mp3`, "\""+"../music"+title+".mp3"+"\"")
cmd := exec.Command("bash", "../download/convert.sh", title, os.Getenv("DOWNLOAD_PATH"))
err := cmd.Run()
if err != nil {
fmt.Println("Convert error")
fmt.Println(err)
os.Remove(title + ".m4a")
break
}
os.Remove(title + ".m4a")
result = true
break
}
os.Chdir("../")
return result
}
func MusicInfo(bv string) (info map[string]interface{}) {
info = make(map[string]interface{})
collector := colly.NewCollector()
collector.OnResponse(func(r *colly.Response) {
var (
rtext string
rjson map[string]interface{}
)
rtext = string(r.Body)
json.Unmarshal([]byte(rtext), &rjson)
// fmt.Println(rjson)
page := int(rjson["data"].(map[string]interface{})["videos"].(float64))
if page == 1 {
info["isSingle"] = true
info["videos"] = make(map[int]interface{})
info["videos"].(map[int]interface{})[1] = map[string]interface{}{"title": rjson["data"].(map[string]interface{})["title"].(string), "cover": rjson["data"].(map[string]interface{})["pic"].(string), "duration": int(rjson["data"].(map[string]interface{})["duration"].(float64))}
} else {
info["isSingle"] = false
info["videos"] = make(map[int]interface{})
pages := rjson["data"].(map[string]interface{})["pages"].([]interface{})
for page, videoInfo := range pages {
info["videos"].(map[int]interface{})[page+1] = map[string]interface{}{"title": videoInfo.(map[string]interface{})["part"].(string), "cover": rjson["data"].(map[string]interface{})["pic"].(string), "duration": int(videoInfo.(map[string]interface{})["duration"].(float64))}
}
}
})
collector.Visit(API_PREURL + bv)
return info
}