parent
ad1dd075a8
commit
34ea18fdbd
@ -1,233 +0,0 @@ |
||||
// Package liveurls
|
||||
// @Time:2023/02/05 23:34
|
||||
// @File:huya.go
|
||||
// @SoftWare:Goland
|
||||
// @Author:feiyang
|
||||
// @Contact:TG@feiyangdigital
|
||||
|
||||
package liveurls |
||||
|
||||
import ( |
||||
"bytes" |
||||
"crypto/md5" |
||||
"encoding/base64" |
||||
"encoding/json" |
||||
"fmt" |
||||
"io" |
||||
"math/rand" |
||||
"net/http" |
||||
"net/url" |
||||
"regexp" |
||||
"strconv" |
||||
"strings" |
||||
"time" |
||||
) |
||||
|
||||
type Huya struct { |
||||
Rid string |
||||
Media string |
||||
Type string |
||||
Cdn string |
||||
} |
||||
|
||||
type Data struct { |
||||
} |
||||
|
||||
type Payload struct { |
||||
AppId int `json:"appId"` |
||||
ByPass int `json:"byPass"` |
||||
Context string `json:"context"` |
||||
Version string `json:"version"` |
||||
Data Data `json:"data"` |
||||
} |
||||
|
||||
type ResponseData struct { |
||||
Data struct { |
||||
Uid string `json:"uid"` |
||||
} `json:"data"` |
||||
} |
||||
|
||||
func md5huya(str string) string { |
||||
w := md5.New() |
||||
io.WriteString(w, str) |
||||
md5str := fmt.Sprintf("%x", w.Sum(nil)) |
||||
return md5str |
||||
} |
||||
|
||||
func oldformat(realstr string) string { |
||||
i := strings.Split(realstr, "?")[0] |
||||
b := strings.Split(realstr, "?")[1] |
||||
r := strings.Split(i, "/") |
||||
reg := regexp.MustCompile(".(flv|m3u8)") |
||||
s := reg.ReplaceAllString(r[len(r)-1], "") |
||||
c := strings.SplitN(b, "&", 4) |
||||
cnil := c[:0] |
||||
n := make(map[string]string) |
||||
for _, v := range c { |
||||
if len(v) > 0 { |
||||
cnil = append(cnil, v) |
||||
narr := strings.Split(v, "=") |
||||
n[narr[0]] = narr[1] |
||||
} |
||||
} |
||||
c = cnil |
||||
fm, _ := url.QueryUnescape(n["fm"]) |
||||
ub64, _ := base64.StdEncoding.DecodeString(fm) |
||||
u := string(ub64) |
||||
p := strings.Split(u, "_")[0] |
||||
f := strconv.FormatInt(time.Now().UnixNano()/100, 10) |
||||
l := n["wsTime"] |
||||
t := "0" |
||||
h := p + "_" + t + "_" + s + "_" + f + "_" + l |
||||
m := md5huya(h) |
||||
y := c[len(c)-1] |
||||
url := fmt.Sprintf("%s?wsSecret=%s&wsTime=%s&u=%s&seqid=%s&%s", i, m, l, t, f, y) |
||||
return url |
||||
} |
||||
|
||||
func getContent(apiUrl string) ([]byte, error) { |
||||
payload := Payload{ |
||||
AppId: 5002, |
||||
ByPass: 3, |
||||
Context: "", |
||||
Version: "2.4", |
||||
Data: Data{}, |
||||
} |
||||
jsonPayload, err := json.Marshal(payload) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
req, err := http.NewRequest("POST", apiUrl, bytes.NewBuffer(jsonPayload)) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
req.Header.Set("Content-Type", "application/json") |
||||
req.Header.Set("Content-Length", fmt.Sprintf("%d", len(jsonPayload))) |
||||
req.Header.Set("upgrade-insecure-requests", "1") |
||||
req.Header.Set("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36") |
||||
|
||||
client := &http.Client{} |
||||
resp, err := client.Do(req) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
defer resp.Body.Close() |
||||
|
||||
return io.ReadAll(resp.Body) |
||||
} |
||||
|
||||
func getUid() string { |
||||
content, _ := getContent("https://udblgn.huya.com/web/anonymousLogin") |
||||
var responseData ResponseData |
||||
json.Unmarshal(content, &responseData) |
||||
uid := responseData.Data.Uid |
||||
return uid |
||||
} |
||||
|
||||
var uid, _ = strconv.Atoi(getUid()) |
||||
|
||||
func getUUID() int64 { |
||||
now := time.Now().UnixNano() / int64(time.Millisecond) |
||||
randNum := rand.Intn(1000) |
||||
return ((now % 10000000000 * 1000) + int64(randNum)) % 4294967295 |
||||
} |
||||
|
||||
func processAntiCode(antiCode string, uid int, streamName string) string { |
||||
q, _ := url.ParseQuery(antiCode) |
||||
q.Set("ver", "1") |
||||
q.Set("sv", "2110211124") |
||||
seqId := strconv.Itoa(uid + int(time.Now().UnixNano()/int64(time.Millisecond))) |
||||
q.Set("seqid", seqId) |
||||
q.Set("uid", strconv.Itoa(uid)) |
||||
q.Set("uuid", strconv.FormatInt(getUUID(), 10)) |
||||
ss := md5huya(seqId + "|" + q.Get("ctype") + "|" + q.Get("t")) |
||||
fm, _ := base64.StdEncoding.DecodeString(q.Get("fm")) |
||||
q.Set("fm", strings.Replace(strings.Replace(strings.Replace(strings.Replace(string(fm), "$0", q.Get("uid"), -1), "$1", streamName, -1), "$2", ss, -1), "$3", q.Get("wsTime"), -1)) |
||||
q.Set("wsSecret", md5huya(q.Get("fm"))) |
||||
q.Del("fm") |
||||
if _, ok := q["txyp"]; ok { |
||||
q.Del("txyp") |
||||
} |
||||
return q.Encode() |
||||
} |
||||
|
||||
func format(liveArr map[string]any, uid int) map[string]any { |
||||
streamInfo := map[string]any{"flv": make(map[string]string), "hls": make(map[string]string)} |
||||
cdnType := map[string]string{"HY": "hycdn", "AL": "alicdn", "TX": "txcdn", "HW": "hwcdn", "HS": "hscdn", "WS": "wscdn"} |
||||
for _, s := range liveArr["roomInfo"].(map[string]any)["tLiveInfo"].(map[string]any)["tLiveStreamInfo"].(map[string]any)["vStreamInfo"].(map[string]any)["value"].([]any) { |
||||
sMap := s.(map[string]any) |
||||
if sMap["sFlvUrl"] != nil { |
||||
streamInfo["flv"].(map[string]string)[cdnType[sMap["sCdnType"].(string)]] = sMap["sFlvUrl"].(string) + "/" + sMap["sStreamName"].(string) + "." + sMap["sFlvUrlSuffix"].(string) + "?" + processAntiCode(sMap["sFlvAntiCode"].(string), uid, sMap["sStreamName"].(string)) |
||||
} |
||||
if sMap["sHlsUrl"] != nil { |
||||
streamInfo["hls"].(map[string]string)[cdnType[sMap["sCdnType"].(string)]] = sMap["sHlsUrl"].(string) + "/" + sMap["sStreamName"].(string) + "." + sMap["sHlsUrlSuffix"].(string) + "?" + processAntiCode(sMap["sHlsAntiCode"].(string), uid, sMap["sStreamName"].(string)) |
||||
} |
||||
} |
||||
return streamInfo |
||||
} |
||||
|
||||
func (h *Huya) GetLiveUrl() any { |
||||
var liveArr map[string]any |
||||
liveurl := "https://m.huya.com/" + h.Rid |
||||
client := &http.Client{} |
||||
r, _ := http.NewRequest("GET", liveurl, nil) |
||||
r.Header.Add("user-agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 16_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.3 Mobile/15E148 Safari/604.1") |
||||
r.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8") |
||||
resp, _ := client.Do(r) |
||||
defer resp.Body.Close() |
||||
body, _ := io.ReadAll(resp.Body) |
||||
str := string(body) |
||||
freg := regexp.MustCompile(`"(?i)liveLineUrl":"([\s\S]*?)",`) |
||||
res := freg.FindStringSubmatch(str) |
||||
if h.Media == "hls" { |
||||
res = nil |
||||
} |
||||
if res == nil || res[1] == "" { |
||||
sreg := regexp.MustCompile(`(?i)<script> window.HNF_GLOBAL_INIT = (.*) </script>`) |
||||
nres := sreg.FindStringSubmatch(str) |
||||
json.Unmarshal([]byte(nres[1]), &liveArr)
|
||||
var mediaurl any
|
||||
if roomInfo, ok := liveArr["roomInfo"].(map[string]any); ok { |
||||
if liveStatus, ok := roomInfo["eLiveStatus"].(float64); ok && liveStatus == 2 {
|
||||
realurl := format(liveArr, uid)
|
||||
if h.Type == "display" {
|
||||
return realurl
|
||||
}
|
||||
for k, v := range realurl {
|
||||
switch k {
|
||||
case h.Media:
|
||||
if urlarr, ok := v.(map[string]string); ok {
|
||||
for k, v := range urlarr {
|
||||
switch k {
|
||||
case h.Cdn:
|
||||
mediaurl = v
|
||||
}
|
||||
}
|
||||
} |
||||
}
|
||||
}
|
||||
} else if liveStatus, ok := roomInfo["eLiveStatus"].(float64); ok && liveStatus == 3 {
|
||||
if roomProfile, ok := liveArr["roomProfile"].(map[string]any); ok {
|
||||
if liveLineUrl, ok := roomProfile["liveLineUrl"].(string); ok {
|
||||
decodedLiveLineUrl, _ := base64.StdEncoding.DecodeString(liveLineUrl)
|
||||
mediaurl = "http:" + string(decodedLiveLineUrl)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mediaurl = nil
|
||||
}
|
||||
}
|
||||
return mediaurl
|
||||
} |
||||
nstr, _ := base64.StdEncoding.DecodeString(res[1]) |
||||
realstr := string(nstr) |
||||
if strings.Contains(realstr, "replay") { |
||||
return "https:" + realstr |
||||
} else { |
||||
liveurl := oldformat(realstr) |
||||
realurl := strings.Replace(strings.Replace(strings.Replace(liveurl, "hls", "flv", -1), "m3u8", "flv", -1), "&ctype=tars_mobile", "", -1) |
||||
return "https:" + realurl |
||||
} |
||||
} |
||||
Loading…
Reference in new issue