)
type Common struct {
- Uid int //client uid
- Live []string //直播流链接
- Live_qn int //当前直播流质量
- Live_want_qn int //期望直播流质量
- Roomid int //房间ID
- Cookie syncmap.Map //Cookie
- Title string //直播标题
- Uname string //主播名
- UpUid int //主播uid
- Rev float64 //营收
- Renqi int //人气
- GuardNum int //舰长数
- ParentAreaID int //父分区
- AreaID int //子分区
- Locked bool //直播间封禁
- Note string //分区排行
- Live_Start_Time time.Time //直播开始时间
- Liveing bool //是否在直播
- Wearing_FansMedal int //当前佩戴的粉丝牌
- Token string //弹幕钥
- WSURL []string //弹幕链接
- LIVE_BUVID bool //cookies含LIVE_BUVID
- Stream_url string //直播Web服务
- Proxy string //全局代理
- AcceptQn map[int]string //允许的直播流质量
- Qn map[int]string //全部直播流质量
- K_v syncmap.Map //配置文件
+ Uid int //client uid
+ Live []string //直播流链接
+ Live_qn int //当前直播流质量
+ Live_want_qn int //期望直播流质量
+ Roomid int //房间ID
+ Cookie syncmap.Map //Cookie
+ Title string //直播标题
+ Uname string //主播名
+ UpUid int //主播uid
+ Rev float64 //营收
+ Renqi int //人气
+ GuardNum int //舰长数
+ ParentAreaID int //父分区
+ AreaID int //子分区
+ Locked bool //直播间封禁
+ Note string //分区排行
+ Live_Start_Time time.Time //直播开始时间
+ Liveing bool //是否在直播
+ Wearing_FansMedal int //当前佩戴的粉丝牌
+ Token string //弹幕钥
+ WSURL []string //弹幕链接
+ LIVE_BUVID bool //cookies含LIVE_BUVID
+ Stream_url string //直播Web服务
+ Proxy string //全局代理
+ AcceptQn map[int]string //允许的直播流质量
+ Qn map[int]string //全部直播流质量
+ K_v syncmap.Map //配置文件
+ Log *log.Log_interface //日志
+ Danmu_Main_mq *mq.Msgq //消息
}
-var (
- Uid = 0 //client uid
-
- Live []string //直播流链接
- Live_qn int //当前直播流质量
- Live_want_qn int //期望直播流质量
- Roomid int
- Cookie syncmap.Map
- Title string //直播标题
- Uname string //主播名
- UpUid int //主播uid
- Rev float64 //营收
- Renqi int //人气
- GuardNum int //舰长数
- ParentAreaID int //父分区
- AreaID int //子分区
- Locked bool //直播间封禁
- Note string //分区排行
- Live_Start_Time time.Time //直播开始时间
- Liveing bool //是否在直播
- Wearing_FansMedal int //当前佩戴的粉丝牌
- Token string //弹幕钥
- WSURL []string //弹幕链接
- LIVE_BUVID bool //cookies含LIVE_BUVID
-)
-
-var (
- Stream_url string //直播Web服务
-)
-
-//消息队列
-type Danmu_Main_mq_item struct {
- Class string
- Data interface{}
-}
-
-//200长度防止push击穿
-var Danmu_Main_mq = mq.New(200)
-
-//k-v
-var K_v syncmap.Map
-
-func init() {
- bb, err := ioutil.ReadFile("config/config_K_v.json")
- if err != nil {
- return
- }
- var data map[string]interface{}
- json.Unmarshal(bb, &data)
- for k, v := range data {
- K_v.Store(k, v)
- }
-}
-
-//constKv
-var (
- Proxy string //全局代理
-)
-
-func init() {
- Proxy, _ = K_v.LoadV("http代理地址").(string)
-}
-
-//日志
-var Log = log.New(log.Config{
- File: `danmu.log`,
- Stdout: true,
- Prefix_string: map[string]struct{}{
- `T: `: log.On,
- `I: `: log.On,
- `N: `: log.On,
- `W: `: log.On,
- `E: `: log.On,
- },
-})
-
-func init() {
- logmap := make(map[string]struct{})
- if array, ok := K_v.Load(`日志显示`); ok {
- for _, v := range array.([]interface{}) {
- logmap[v.(string)] = log.On
- }
- }
- Log = Log.Level(logmap)
- return
-}
-
-//from player-loader-2.0.11.min.js
-/*
- customAuthParam
-*/
-// var (
-// VERSION = "2.0.11"
-// ) // 不再需要
-
-//允许的清晰度
-
-var (
- AcceptQn = map[int]string{
+func (t *Common) init() Common {
+ t.Qn = map[int]string{ // no change
10000: "原画",
800: "4K",
401: "蓝光(杜比)",
150: "高清",
80: "流畅",
}
- Qn = map[int]string{ // no change
+
+ t.AcceptQn = map[int]string{ // no change
10000: "原画",
800: "4K",
401: "蓝光(杜比)",
150: "高清",
80: "流畅",
}
-)
+
+ t.Log = log.New(log.Config{
+ File: `danmu.log`,
+ Stdout: true,
+ Prefix_string: map[string]struct{}{
+ `T: `: log.On,
+ `I: `: log.On,
+ `N: `: log.On,
+ `W: `: log.On,
+ `E: `: log.On,
+ },
+ })
+
+ t.Danmu_Main_mq = mq.New(200)
+
+ if bb, err := ioutil.ReadFile("config/config_K_v.json"); err == nil {
+ var data map[string]interface{}
+ json.Unmarshal(bb, &data)
+ for k, v := range data {
+ t.K_v.Store(k, v)
+ }
+ }
+
+ if val, exist := t.K_v.Load("http代理地址"); exist {
+ t.Proxy = val.(string)
+ }
+
+ logmap := make(map[string]struct{})
+ if array, ok := t.K_v.Load(`日志显示`); ok {
+ for _, v := range array.([]interface{}) {
+ logmap[v.(string)] = log.On
+ }
+ }
+ t.Log = t.Log.Level(logmap)
+
+ return *t
+}
+
+var C = new(Common).init()
+
+//消息队列
+type Danmu_Main_mq_item struct {
+ Class string
+ Data interface{}
+}
import (
"fmt"
+
c "github.com/qydysky/bili_danmu/CV"
p "github.com/qydysky/part"
crypto "github.com/qydysky/part/crypto"
)
-
//公私钥加密
var (
- clog = c.Log.Base(`cookie加密`)
- pub []byte
- pri []byte
+ clog = c.C.Log.Base(`cookie加密`)
+ pub []byte
+ pri []byte
)
-func CookieGet() ([]byte) {
+func CookieGet() []byte {
clog := clog.Base_add(`获取`)
if len(pri) == 0 {
- if priS,ok := c.K_v.LoadV(`cookie解密私钥`).(string);ok && priS != ``{
- if d,e := crypto.FileLoad(priS);e != nil {
- clog.L(`E: `,e)
+ if priS, ok := c.C.K_v.LoadV(`cookie解密私钥`).(string); ok && priS != `` {
+ if d, e := crypto.FileLoad(priS); e != nil {
+ clog.L(`E: `, e)
return []byte{}
} else {
pri = d
}
- } else if pubS,ok := c.K_v.LoadV(`cookie加密公钥`).(string);ok && pubS != ``{
- c.Log.Block(1000)//等待所有日志输出完毕
+ } else if pubS, ok := c.C.K_v.LoadV(`cookie加密公钥`).(string); ok && pubS != `` {
+ c.C.Log.Block(1000) //等待所有日志输出完毕
priS := ``
fmt.Printf("cookie密钥路径: ")
_, err := fmt.Scanln(&priS)
clog.L(`E: `, "输入错误", err)
return []byte{}
}
- if d,e := crypto.FileLoad(priS);e != nil {
- clog.L(`E: `,e)
+ if d, e := crypto.FileLoad(priS); e != nil {
+ clog.L(`E: `, e)
return []byte{}
} else {
pri = d
}
} else {
- if d,e := crypto.FileLoad(`cookie.txt`);e != nil || string(d[:3]) != `nol` {
+ if d, e := crypto.FileLoad(`cookie.txt`); e != nil || string(d[:3]) != `nol` {
clog.L(`E: `, e, `cookie保存格式:`, string(d[:3]))
return []byte{}
} else {
}
}
}
- if source,e := crypto.FileLoad(`cookie.txt`);e != nil || string(source[:3]) != `pem` {
+ if source, e := crypto.FileLoad(`cookie.txt`); e != nil || string(source[:3]) != `pem` {
clog.L(`E: `, e, `cookie保存格式:`, string(source[:3]))
return []byte{}
- } else if s,e := crypto.Decrypt(source[3:],pri);e != nil{
- clog.L(`E: `,e)
+ } else if s, e := crypto.Decrypt(source[3:], pri); e != nil {
+ clog.L(`E: `, e)
return []byte{}
} else {
return s
func CookieSet(source []byte) {
clog := clog.Base_add(`设置`)
if len(pub) == 0 {
- if pubS,ok := c.K_v.LoadV(`cookie加密公钥`).(string);ok && pubS != ``{
- if d,e := crypto.FileLoad(pubS);e != nil {
- clog.L(`E: `,e)
+ if pubS, ok := c.C.K_v.LoadV(`cookie加密公钥`).(string); ok && pubS != `` {
+ if d, e := crypto.FileLoad(pubS); e != nil {
+ clog.L(`E: `, e)
return
} else {
pub = d
} else {
f := p.File()
f.FileWR(p.Filel{
- File:`cookie.txt`,
- Loc:0,
- Context:[]interface{}{`nol`,source},
+ File: `cookie.txt`,
+ Loc: 0,
+ Context: []interface{}{`nol`, source},
})
return
}
}
- if source,e := crypto.Encrypt(source,pub);e != nil{
- clog.L(`E: `,e)
+ if source, e := crypto.Encrypt(source, pub); e != nil {
+ clog.L(`E: `, e)
return
} else {
f := p.File()
f.FileWR(p.Filel{
- File:`cookie.txt`,
- Loc:0,
- Context:[]interface{}{`pem`,source},
+ File: `cookie.txt`,
+ Loc: 0,
+ Context: []interface{}{`pem`, source},
})
}
-}
\ No newline at end of file
+}
c "github.com/qydysky/bili_danmu/CV"
)
-var flog = c.Log.Base(`F/F.go`)
+var flog = c.C.Log.Base(`F/F.go`)
//base on source/player-loader-2.0.7.min.js L3313
//base on source/player-loader-2.0.7.min.js L3455
}
//头部生成与检查
-func HeadGen(datalenght,Opeation,Sequence int) []byte {
+func HeadGen(datalenght, Opeation, Sequence int) []byte {
var buffer bytes.Buffer //Buffer是一个实现了读写方法的可变大小的字节缓冲
buffer.Write(Itob32(int32(datalenght + c.WS_PACKAGE_HEADER_TOTAL_LENGTH)))
return buffer.Bytes()
}
-func HeadChe(head []byte) (header) {
+func HeadChe(head []byte) header {
- if len(head) != c.WS_PACKAGE_HEADER_TOTAL_LENGTH {flog.Base_add("头部检查").L(`E: `,"输入头长度错误");return header{}}
+ if len(head) != c.WS_PACKAGE_HEADER_TOTAL_LENGTH {
+ flog.Base_add("头部检查").L(`E: `, "输入头长度错误")
+ return header{}
+ }
PackL := Btoi32(head, c.WS_PACKAGE_OFFSET)
HeadL := Btoi16(head, c.WS_HEADER_OFFSET)
Seque := Btoi32(head, c.WS_SEQUENCE_OFFSET)
return header{
- PackL :PackL,
- HeadL :HeadL,
- BodyV :BodyV,
- OpeaT :OpeaT,
- Seque :Seque,
+ PackL: PackL,
+ HeadL: HeadL,
+ BodyV: BodyV,
+ OpeaT: OpeaT,
+ Seque: Seque,
}
}
flog := flog.Base_add("认证生成")
if roomid == 0 || key == "" {
- flog.L(`E: `,"roomid == 0 || key == \"\"")
+ flog.L(`E: `, "roomid == 0 || key == \"\"")
return []byte("")
}
- var obj = `{"uid":` + strconv.Itoa(c.Uid) +
- `,"roomid":` + strconv.Itoa(roomid) +
- `,"protover":` + strconv.Itoa(c.Protover) +
- `,"platform":"`+ c.Platform +
- // `","clientver":"` + c.VERSION + //delete at 2021 4 14
- `","type":` + strconv.Itoa(c.Type) +
- `,"key":"` + key + `"}`
+ var obj = `{"uid":` + strconv.Itoa(c.C.Uid) +
+ `,"roomid":` + strconv.Itoa(roomid) +
+ `,"protover":` + strconv.Itoa(c.Protover) +
+ `,"platform":"` + c.Platform +
+ // `","clientver":"` + c.VERSION + //delete at 2021 4 14
+ `","type":` + strconv.Itoa(c.Type) +
+ `,"key":"` + key + `"}`
var buffer bytes.Buffer //Buffer是一个实现了读写方法的可变大小的字节缓冲
-
+
buffer.Write(HeadGen(len(obj), c.WS_OP_USER_AUTHENTICATION, c.WS_HEADER_DEFAULT_SEQUENCE))
buffer.Write([]byte(obj))
}
func HelloChe(r []byte) bool {
- if len(r) == 0 {return false}
+ if len(r) == 0 {
+ return false
+ }
var obj = `{"code":0}`
h := buffer.Bytes()
- if len(h) != len(r) {return false}
+ if len(h) != len(r) {
+ return false
+ }
for k, v := range r {
- if v != h[k] {return false}
+ if v != h[k] {
+ return false
+ }
}
return true
}
var obj = `[object Object]`
var buffer bytes.Buffer //Buffer是一个实现了读写方法的可变大小的字节缓冲
-
+
buffer.Write(HeadGen(len(obj), c.WS_OP_HEARTBEAT, c.WS_HEADER_DEFAULT_SEQUENCE))
buffer.Write([]byte(obj))
//cookie检查
func CookieCheck(key []string) (missKey []string) {
- for _,tk := range key{
- if tk == `` {continue}
- if _,ok := c.Cookie.Load(tk);!ok{
+ for _, tk := range key {
+ if tk == `` {
+ continue
+ }
+ if _, ok := c.C.Cookie.Load(tk); !ok {
missKey = append(missKey, tk)
}
}
return
-}
\ No newline at end of file
+}
qr "github.com/skip2/go-qrcode"
)
-var apilog = c.Log.Base(`api`)
+var apilog = c.C.Log.Base(`api`)
var api_limit = limit.New(1, 2000, 30000) //频率限制1次/2s,最大等待时间30s
type GetFunc struct {
- c.Common
+ *c.Common
+}
+
+func Get(c *c.Common) *GetFunc {
+ return &GetFunc{c}
}
func (c *GetFunc) Get(key string) {
apilog := apilog.Base_add(`获取头像`)
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
if err := req.Reqf(reqf.Rval{
Url: "https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuMedalAnchorInfo?ruid=" + uid,
Header: map[string]string{
- `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.Roomid),
+ `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.C.Roomid),
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
Retry: 2,
}); err != nil {
req := reqf.New()
if err := req.Reqf(reqf.Rval{
Url: `https://api.bilibili.com/x/space/acc/info?mid=` + strconv.Itoa(UpUid) + `&jsonp=jsonp`,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
Retry: 2,
}); err != nil {
return
}
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
Header: map[string]string{
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
Retry: 2,
}); e != nil {
return
}
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
Header: map[string]string{
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
Retry: 2,
}); e != nil {
{ //检查是否签到
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
`Referer`: "https://live.bilibili.com/all",
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 3 * 1000,
Retry: 2,
}); err != nil {
{ //签到
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
`Referer`: "https://live.bilibili.com/all",
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 3 * 1000,
Retry: 2,
}); err != nil {
func F_x25Kn() {
apilog := apilog.Base_add(`小心心`)
- if c.Wearing_FansMedal == 0 {
+ if c.C.Wearing_FansMedal == 0 {
apilog.L(`I: `, `无粉丝牌,不获取`)
return
}
apilog.L(`T: `, `Cookie无Key:`, missKey)
return
}
- if c.ParentAreaID == -1 {
+ if c.C.ParentAreaID == -1 {
apilog.L(`E: `, `失败!未获取Parent_area_id`)
return
}
- if c.AreaID == -1 {
+ if c.C.AreaID == -1 {
apilog.L(`E: `, `失败!未获取Area_id`)
return
}
loop_num = 0
)
- csrf, _ := c.Cookie.LoadV(`bili_jct`).(string)
+ csrf, _ := c.C.Cookie.LoadV(`bili_jct`).(string)
if csrf == `` {
apilog.L(`E: `, "Cookie错误,无bili_jct")
return
}
- LIVE_BUVID := c.Cookie.LoadV(`LIVE_BUVID`).(string)
+ LIVE_BUVID := c.C.Cookie.LoadV(`LIVE_BUVID`).(string)
if LIVE_BUVID == `` {
apilog.L(`E: `, "Cookie错误,无LIVE_BUVID")
return
{ //初始化
- PostStr := `id=[` + strconv.Itoa(c.ParentAreaID) + `,` + strconv.Itoa(c.AreaID) + `,` + strconv.Itoa(loop_num) + `,` + strconv.Itoa(c.Roomid) + `]&`
+ PostStr := `id=[` + strconv.Itoa(c.C.ParentAreaID) + `,` + strconv.Itoa(c.C.AreaID) + `,` + strconv.Itoa(loop_num) + `,` + strconv.Itoa(c.C.Roomid) + `]&`
PostStr += `device=["` + LIVE_BUVID + `","` + new_uuid + `"]&`
PostStr += `ts=` + strconv.Itoa(int(p.Sys().GetMTime()))
PostStr += `&is_patch=0&`
PostStr += `visit_id=`
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
`Connection`: `keep-alive`,
`Pragma`: `no-cache`,
`Cache-Control`: `no-cache`,
- `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.Roomid),
+ `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.C.Roomid),
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
PostStr: url.PathEscape(PostStr),
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 5 * 1000,
Retry: 2,
}); err != nil {
var (
rt_obj = RT{
R: R{
- Id: `[` + strconv.Itoa(c.ParentAreaID) + `,` + strconv.Itoa(c.AreaID) + `,` + strconv.Itoa(loop_num) + `,` + strconv.Itoa(c.Roomid) + `]`,
+ Id: `[` + strconv.Itoa(c.C.ParentAreaID) + `,` + strconv.Itoa(c.C.AreaID) + `,` + strconv.Itoa(loop_num) + `,` + strconv.Itoa(c.C.Roomid) + `]`,
Device: `["` + LIVE_BUVID + `","` + new_uuid + `"]`,
Ets: res.Data.Timestamp,
Benchmark: res.Data.Secret_key,
PostStr = `s=` + wasm + `&` + PostStr
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
`Connection`: `keep-alive`,
`Pragma`: `no-cache`,
`Cache-Control`: `no-cache`,
- `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.Roomid),
+ `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.C.Roomid),
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
PostStr: url.PathEscape(PostStr),
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 5 * 1000,
Retry: 2,
}); err != nil {
apilog.L(`T: `, `Cookie无Key:`, missKey)
return
}
- if c.Roomid == 0 {
+ if c.C.Roomid == 0 {
apilog.L(`E: `, `失败!无Roomid`)
return
}
} //超额请求阻塞,超时将取消
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
req := reqf.New()
if err := req.Reqf(reqf.Rval{
- Url: `https://api.live.bilibili.com/xlive/web-room/v1/gift/bag_list?t=` + strconv.Itoa(int(p.Sys().GetMTime())) + `&room_id=` + strconv.Itoa(c.Roomid),
+ Url: `https://api.live.bilibili.com/xlive/web-room/v1/gift/bag_list?t=` + strconv.Itoa(int(p.Sys().GetMTime())) + `&room_id=` + strconv.Itoa(c.C.Roomid),
Header: map[string]string{
`Host`: `api.live.bilibili.com`,
`User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
`Connection`: `keep-alive`,
`Pragma`: `no-cache`,
`Cache-Control`: `no-cache`,
- `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.Roomid),
+ `Referer`: "https://live.bilibili.com/" + strconv.Itoa(c.C.Roomid),
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 3 * 1000,
Retry: 2,
}); err != nil {
func save_cookie(Cookies []*http.Cookie) {
for k, v := range reqf.Cookies_List_2_Map(Cookies) {
- c.Cookie.Store(k, v)
+ c.C.Cookie.Store(k, v)
}
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
} //超额请求阻塞,超时将取消
Cookie := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
`Referer`: `https://t.bilibili.com/pages/nav/index_new`,
`Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 3 * 1000,
Retry: 2,
}); err != nil {
Header: map[string]string{
`Referer`: "https://live.bilibili.com/" + Roomid,
},
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
Retry: 2,
}); err != nil {
req := reqf.New()
if err := req.Reqf(reqf.Rval{
Url: "https://api.bilibili.com/x/web-interface/search/type?context=&search_type=live_user&cover_type=user_cover&page=1&order=&category_id=&__refresh__=true&_extra=&highlight=1&single_column=0&keyword=" + url.PathEscape(s),
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
Retry: 2,
}); err != nil {
func IsConnected() bool {
apilog := apilog.Base_add(`IsConnected`)
- v, ok := c.K_v.LoadV(`网络中断不退出`).(bool)
+ v, ok := c.C.K_v.LoadV(`网络中断不退出`).(bool)
if !ok || !v {
return true
}
req := reqf.New()
if err := req.Reqf(reqf.Rval{
Url: "https://www.bilibili.com",
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Timeout: 10 * 1000,
JustResponseCode: true,
}); err != nil {
func Cmd() {
- cmdlog := c.Log.Base_add(`命令行操作`).L(`T: `, `回车查看帮助`)
+ cmdlog := c.C.Log.Base_add(`命令行操作`).L(`T: `, `回车查看帮助`)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if inputs := scanner.Text(); inputs == `` { //帮助
fmt.Print("\n")
fmt.Println("切换房间->输入数字回车")
- if c.Roomid == 0 {
- if _, ok := c.Cookie.LoadV(`bili_jct`).(string); ok {
+ if c.C.Roomid == 0 {
+ if _, ok := c.C.Cookie.LoadV(`bili_jct`).(string); ok {
fmt.Println("查看直播中主播->输入' live'回车")
} else {
fmt.Println("登陆->输入' login'回车")
fmt.Print("\n")
continue
}
- if _, ok := c.Cookie.LoadV(`bili_jct`).(string); ok {
+ if _, ok := c.C.Cookie.LoadV(`bili_jct`).(string); ok {
fmt.Println("发送弹幕->输入' 字符串'回车")
fmt.Println("查看直播中主播->输入' live'回车")
fmt.Println("获取小心心->输入' getheart'回车")
cmdlog.L(`W: `, "不支持功能键")
} else if inputs[0] == 32 { // 开头
//录制切换
- if strings.Contains(inputs, ` rec`) && c.Roomid != 0 {
- if !c.Liveing {
+ if strings.Contains(inputs, ` rec`) && c.C.Roomid != 0 {
+ if !c.C.Liveing {
cmdlog.L(`W: `, "不能切换录制状态,未在直播")
continue
}
- c.Danmu_Main_mq.Push_tag(`savestream`, nil)
+ c.C.Danmu_Main_mq.Push_tag(`savestream`, nil)
continue
}
//直播间切换
if strings.Contains(inputs, ` live`) {
- if _, ok := c.Cookie.LoadV(`bili_jct`).(string); !ok {
+ if _, ok := c.C.Cookie.LoadV(`bili_jct`).(string); !ok {
cmdlog.L(`W: `, "尚未登陆,未能获取关注主播")
continue
}
fmt.Print("\n")
if len(inputs) > 5 {
if room, ok := liveList[inputs]; ok {
- c.Roomid = room
- c.Danmu_Main_mq.Push_tag(`change_room`, nil)
+ c.C.Roomid = room
+ c.C.Danmu_Main_mq.Push_tag(`change_room`, nil)
continue
}
cmdlog.L(`W: `, "输入错误", inputs)
}
//登陆
if strings.Contains(inputs, ` login`) {
- if _, ok := c.Cookie.LoadV(`bili_jct`).(string); ok {
+ if _, ok := c.C.Cookie.LoadV(`bili_jct`).(string); ok {
cmdlog.L(`W: `, "已登陆")
continue
}
//获取cookie
- Get(`Cookie`)
+ Get(&c.C).Get(`Cookie`)
continue
}
//获取小心心
- if strings.Contains(inputs, ` getheart`) && c.Roomid != 0 {
- if _, ok := c.Cookie.LoadV(`bili_jct`).(string); !ok {
+ if strings.Contains(inputs, ` getheart`) && c.C.Roomid != 0 {
+ if _, ok := c.C.Cookie.LoadV(`bili_jct`).(string); !ok {
cmdlog.L(`W: `, "尚未登陆,不能获取小心心")
continue
}
continue
}
//重载弹幕
- if strings.Contains(inputs, ` reload`) && c.Roomid != 0 {
- c.Danmu_Main_mq.Push_tag(`flash_room`, nil)
+ if strings.Contains(inputs, ` reload`) && c.C.Roomid != 0 {
+ c.C.Danmu_Main_mq.Push_tag(`flash_room`, nil)
continue
}
//当前直播间信息
- if strings.Contains(inputs, ` room`) && c.Roomid != 0 {
+ if strings.Contains(inputs, ` room`) && c.C.Roomid != 0 {
fmt.Print("\n")
fmt.Println("当前直播间信息")
{
living := `未在直播`
- if c.Liveing {
+ if c.C.Liveing {
living = `直播中`
}
- fmt.Println(c.Uname, c.Title, living)
+ fmt.Println(c.C.Uname, c.C.Title, living)
}
{
- if c.Liveing {
- d := time.Since(c.Live_Start_Time).Round(time.Second)
+ if c.C.Liveing {
+ d := time.Since(c.C.Live_Start_Time).Round(time.Second)
h := d / time.Hour
d -= h * time.Hour
m := d / time.Minute
}
}
{
- fmt.Println(`营收:`, fmt.Sprintf("¥%.2f", c.Rev))
+ fmt.Println(`营收:`, fmt.Sprintf("¥%.2f", c.C.Rev))
}
- fmt.Println(`舰长数:`, c.GuardNum)
- fmt.Println(`分区排行:`, c.Note, `人气:`, c.Renqi)
- if c.Stream_url != "" {
- fmt.Println(`直播Web服务:`, c.Stream_url+`/now`)
+ fmt.Println(`舰长数:`, c.C.GuardNum)
+ fmt.Println(`分区排行:`, c.C.Note, `人气:`, c.C.Renqi)
+ if c.C.Stream_url != "" {
+ fmt.Println(`直播Web服务:`, c.C.Stream_url+`/now`)
}
fmt.Print("\n")
continue
}
{ //弹幕发送
- if c.Roomid == 0 {
+ if c.C.Roomid == 0 {
continue
}
- if _, ok := c.Cookie.LoadV(`bili_jct`).(string); !ok {
+ if _, ok := c.C.Cookie.LoadV(`bili_jct`).(string); !ok {
cmdlog.L(`W: `, "尚未登陆,不能发送弹幕")
continue
}
cmdlog.L(`W: `, "输入长度过短", inputs)
continue
}
- send.Danmu_s(inputs[1:], c.Roomid)
+ send.Danmu_s(inputs[1:], c.C.Roomid)
}
} else if room, err := strconv.Atoi(inputs); err == nil { //直接进入房间
- c.Roomid = room
+ c.C.Roomid = room
cmdlog.L(`I: `, "进入房间", room)
- c.Danmu_Main_mq.Push_tag(`change_room`, nil)
+ c.C.Danmu_Main_mq.Push_tag(`change_room`, nil)
} else { //其余字符串
- if c.Roomid == 0 {
+ if c.C.Roomid == 0 {
continue
}
- send.Danmu_s(inputs, c.Roomid)
+ send.Danmu_s(inputs, c.C.Roomid)
}
}
}
package F
import (
+ "encoding/json"
"net/http"
"strconv"
- "encoding/json"
- "time"
"strings"
+ "time"
c "github.com/qydysky/bili_danmu/CV"
p "github.com/qydysky/part"
- websocket "github.com/qydysky/part/websocket"
msgq "github.com/qydysky/part/msgq"
- web "github.com/qydysky/part/web"
reqf "github.com/qydysky/part/reqf"
+ web "github.com/qydysky/part/web"
+ websocket "github.com/qydysky/part/websocket"
"github.com/skratchdot/open-golang/open"
)
//需要加密的数据
type R struct {
- Id string `json:"id"`
- Device string `json:"device"`
- Ets int `json:"ets"`
+ Id string `json:"id"`
+ Device string `json:"device"`
+ Ets int `json:"ets"`
Benchmark string `json:"benchmark"`
- Time int `json:"time"`
- Ts int `json:"ts"`
- Ua string `json:"ua"`
+ Time int `json:"time"`
+ Ts int `json:"ts"`
+ Ua string `json:"ua"`
}
//发送的原始对象
type RT struct {
- R R `json:"r"`
+ R R `json:"r"`
T []int `json:"t"` //加密方法
}
//返回的加密对象
type S struct {
- Id string `json:"id"`//发送的数据中的Id项,以确保是对应的返回
- S string `json:"s"` //加密字符串
+ Id string `json:"id"` //发送的数据中的Id项,以确保是对应的返回
+ S string `json:"s"` //加密字符串
}
-
//全局对象
var (
- wslog = c.Log.Base(`api`).Base_add(`小心心加密`) //日志
- rec_chan = make(chan S,5)//收通道
- webpath string//web地址,由于实时获取空闲端口,故将在稍后web启动后赋值
- ws = websocket.New_server()//新建websocket实例
+ wslog = c.C.Log.Base(`api`).Base_add(`小心心加密`) //日志
+ rec_chan = make(chan S, 5) //收通道
+ webpath string //web地址,由于实时获取空闲端口,故将在稍后web启动后赋值
+ ws = websocket.New_server() //新建websocket实例
nodeJsUrl string
)
func init() {
go func() {
for {
- v,ok := c.K_v.Load("get_xiao_xinxin")
+ v, ok := c.C.K_v.Load("get_xiao_xinxin")
if !ok {
time.Sleep(time.Second)
continue
}
- if t,ok := v.(bool);!ok || !t {return}
+ if t, ok := v.(bool); !ok || !t {
+ return
+ }
break
}
-
+
//初始化web服务器,初始化websocket
- NodeJsUrl,ok := c.K_v.LoadV("小心心nodjs加密服务地址").(string)
+ NodeJsUrl, ok := c.C.K_v.LoadV("小心心nodjs加密服务地址").(string)
if ok && NodeJsUrl != "" {
nodeJsUrl = NodeJsUrl
if test(0) {
- wslog.L(`I: `,`使用NodeJs`,NodeJsUrl,`进行加密`)
+ wslog.L(`I: `, `使用NodeJs`, NodeJsUrl, `进行加密`)
} else {
- wslog.L(`E: `,`发生错误!`)
+ wslog.L(`E: `, `发生错误!`)
}
} else {
server()
}
- wslog.L(`T: `,`启动`)
+ wslog.L(`T: `, `启动`)
}()
}
func server() {
{
- ws_mq := ws.Interface()//获取websocket操作对象
+ ws_mq := ws.Interface() //获取websocket操作对象
ws_mq.Pull_tag(msgq.FuncMap{
- `recv`:func(data interface{})(bool){
- if tmp,ok := data.(websocket.Uinterface);ok {//websocket接收并响应
+ `recv`: func(data interface{}) bool {
+ if tmp, ok := data.(websocket.Uinterface); ok { //websocket接收并响应
//websocket.Uinterface{
// Id uintptr 会话id
// Data []byte 接收的websocket数据
wslog.L(`E: `, e, string(tmp.Data))
}
- select{
+ select {
case rec_chan <- s:
default:
}
}
return false
},
- `error`:func(data interface{})(bool){//websocket错误
+ `error`: func(data interface{}) bool { //websocket错误
wslog.L(`W: `, data)
return false
},
}
w := web.New(&http.Server{
- Addr: "127.0.0.1:"+strconv.Itoa(p.Sys().GetFreePort()),
- })//新建web实例
- w.Handle(map[string]func(http.ResponseWriter,*http.Request){//路径处理函数
- `/`:func(w http.ResponseWriter,r *http.Request){
+ Addr: "127.0.0.1:" + strconv.Itoa(p.Sys().GetFreePort()),
+ }) //新建web实例
+ w.Handle(map[string]func(http.ResponseWriter, *http.Request){ //路径处理函数
+ `/`: func(w http.ResponseWriter, r *http.Request) {
var path string = r.URL.Path[1:]
- if path == `` {path = `index.html`}
+ if path == `` {
+ path = `index.html`
+ }
http.ServeFile(w, r, "html/"+path)
},
- `/ws`:func(w http.ResponseWriter,r *http.Request){
+ `/ws`: func(w http.ResponseWriter, r *http.Request) {
//获取通道
- conn := ws.WS(w,r)
+ conn := ws.WS(w, r)
//由通道获取本次会话id,并测试 提示
go test(<-conn)
//等待会话结束,通道释放
<-conn
},
})
- webpath = `http://`+w.Server.Addr
+ webpath = `http://` + w.Server.Addr
//提示
- wslog.L(`I: `,`使用WebJs`,webpath,`进行加密`)
+ wslog.L(`I: `, `使用WebJs`, webpath, `进行加密`)
}
-func Wasm(uid uintptr,rt RT) (so RT, o string) {//maxloop 超时重试
+func Wasm(uid uintptr, rt RT) (so RT, o string) { //maxloop 超时重试
so = rt
- {//nodejs
+ { //nodejs
if nodeJsUrl != "" {
req := reqf.New()
if err := req.Reqf(reqf.Rval{
- Header:map[string]string{
+ Header: map[string]string{
`Content-Type`: `application/json`,
},
- Url:nodeJsUrl,
- PostStr:toNodeJsString(so),
- Proxy:c.Proxy,
- Timeout:3*1000,
- });err != nil {
- wslog.L(`E: `,err)
- so,o = Wasm(uid, so)
+ Url: nodeJsUrl,
+ PostStr: toNodeJsString(so),
+ Proxy: c.C.Proxy,
+ Timeout: 3 * 1000,
+ }); err != nil {
+ wslog.L(`E: `, err)
+ so, o = Wasm(uid, so)
return
}
- var res struct{
- Code int `json:"code"`
- S string `json:"s"`
+ var res struct {
+ Code int `json:"code"`
+ S string `json:"s"`
Message string `json:"message"`
}
- if e := json.Unmarshal(req.Respon, &res);e != nil {
- wslog.L(`E: `,e)
+ if e := json.Unmarshal(req.Respon, &res); e != nil {
+ wslog.L(`E: `, e)
} else if res.Code != 0 {
- wslog.L(`E: `,res.Message)
+ wslog.L(`E: `, res.Message)
} else {
o = res.S
}
}
}
- {//web
- for try:=5;try > 0 && ws.Len() == 0;try-=1 {//没有从池中取出
+ { //web
+ for try := 5; try > 0 && ws.Len() == 0; try -= 1 { //没有从池中取出
open.Run(webpath)
- wslog.L(`I: `,`浏览器打开`,webpath)
- time.Sleep(time.Second*time.Duration(10))
+ wslog.L(`I: `, `浏览器打开`, webpath)
+ time.Sleep(time.Second * time.Duration(10))
}
if ws.Len() == 0 {
- wslog.L(`W: `,`浏览器打开`,webpath,`失败,请手动打开`)
+ wslog.L(`W: `, `浏览器打开`, webpath, `失败,请手动打开`)
return
}
}
b, e := json.Marshal(so)
if e != nil {
- wslog.L(`E: `,e)
+ wslog.L(`E: `, e)
}
//获取websocket操作对象 发送
- ws.Interface().Push_tag(`send`,websocket.Uinterface{
- Id:uid,
- Data:b,
+ ws.Interface().Push_tag(`send`, websocket.Uinterface{
+ Id: uid,
+ Data: b,
})
for {
select {
- case r :=<- rec_chan:
- if r.Id != so.R.Id {break}//或许接收到之前的请求,校验Id字段
+ case r := <-rec_chan:
+ if r.Id != so.R.Id {
+ break
+ } //或许接收到之前的请求,校验Id字段
return so, r.S
- case <- time.After(time.Second*time.Duration(1)):
- wslog.L(`E: `,`超时!响应>1s,确认保持`,webpath,`开启`)
+ case <-time.After(time.Second * time.Duration(1)):
+ wslog.L(`E: `, `超时!响应>1s,确认保持`, webpath, `开启`)
return
}
}
}
}
-func Close(uid uintptr){
+func Close(uid uintptr) {
//nodejs不需要关闭
if nodeJsUrl != "" {
return
}
//获取websocket操作对象 关闭
- ws.Interface().Push_tag(`close`,websocket.Uinterface{
- Id:uid,
- Data:[]byte(`获取结束、关闭连接`),
+ ws.Interface().Push_tag(`close`, websocket.Uinterface{
+ Id: uid,
+ Data: []byte(`获取结束、关闭连接`),
})
}
func test(uid uintptr) bool {
- time.Sleep(time.Second*time.Duration(3))
- if _,s := Wasm(uid, RT{
- R:R{
- Id: "[9,371,1,22613059]",
- Device: "[\"AUTO8216117272375373\",\"77bee604-b591-4664-845b-b69603f8c71c\"]",
- Ets: 1611836581,
- Benchmark: "seacasdgyijfhofiuxoannn",
- Time: 60,
- Ts: 1611836642190,
- Ua:`Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0 Test`,
+ time.Sleep(time.Second * time.Duration(3))
+ if _, s := Wasm(uid, RT{
+ R: R{
+ Id: "[9,371,1,22613059]",
+ Device: "[\"AUTO8216117272375373\",\"77bee604-b591-4664-845b-b69603f8c71c\"]",
+ Ets: 1611836581,
+ Benchmark: "seacasdgyijfhofiuxoannn",
+ Time: 60,
+ Ts: 1611836642190,
+ Ua: `Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0 Test`,
},
T: []int{2, 5, 1, 4},
- });s != `e4249b7657c2d4a44955548eb814797d41ddd99bfdfa5974462b8c387d701b8c83898f6d7dde1772c67fad6a113d20c20e454be1d1627e7ea99617a8a1f99bd0` {
- wslog.L(`E: `,`测试未通过`,s)
+ }); s != `e4249b7657c2d4a44955548eb814797d41ddd99bfdfa5974462b8c387d701b8c83898f6d7dde1772c67fad6a113d20c20e454be1d1627e7ea99617a8a1f99bd0` {
+ wslog.L(`E: `, `测试未通过`, s)
return false
}
return true
func toNodeJsString(r RT) (o string) {
o += `{"t":{"id":`
- o += r.R.Id+`,`
- o += `"device":`+r.R.Device+`,`
- o += `"ets":`+strconv.Itoa(r.R.Ets)+`,`
- o += `"benchmark":"`+r.R.Benchmark+`",`
- o += `"time":`+strconv.Itoa(r.R.Time)+`,`
- o += `"ts":`+strconv.Itoa(r.R.Ts)+`,`
- o += `"ua":"`+r.R.Ua+`"},"r":[`
- o += strconv.Itoa(r.T[0])+`,`
- o += strconv.Itoa(r.T[1])+`,`
- o += strconv.Itoa(r.T[2])+`,`
+ o += r.R.Id + `,`
+ o += `"device":` + r.R.Device + `,`
+ o += `"ets":` + strconv.Itoa(r.R.Ets) + `,`
+ o += `"benchmark":"` + r.R.Benchmark + `",`
+ o += `"time":` + strconv.Itoa(r.R.Time) + `,`
+ o += `"ts":` + strconv.Itoa(r.R.Ts) + `,`
+ o += `"ua":"` + r.R.Ua + `"},"r":[`
+ o += strconv.Itoa(r.T[0]) + `,`
+ o += strconv.Itoa(r.T[1]) + `,`
+ o += strconv.Itoa(r.T[2]) + `,`
o += strconv.Itoa(r.T[3])
o += `]}`
return
-}
\ No newline at end of file
+}
/*
F额外功能区
*/
-var flog = c.Log.Base(`功能`)
+var flog = c.C.Log.Base(`功能`)
//功能开关选取函数
func IsOn(s string) bool {
- v, ok := c.K_v.LoadV(s).(bool)
+ v, ok := c.C.K_v.LoadV(s).(bool)
return ok && v
}
return
}
if ShowRev_start {
- c.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f", c.Rev))
+ c.C.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f", c.C.Rev))
return
}
ShowRev_start = true
for {
- c.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f", c.Rev))
- for c.Rev == ShowRev_old {
+ c.C.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f", c.C.Rev))
+ for c.C.Rev == ShowRev_old {
p.Sys().Timeoutf(60)
}
- ShowRev_old = c.Rev
+ ShowRev_old = c.C.Rev
}
}
`GB18030`: true,
`utf-8`: true,
}
- if v, ok := c.K_v.LoadV("Ass编码").(string); ok {
+ if v, ok := c.C.K_v.LoadV("Ass编码").(string); ok {
if v1, ok := accept[v]; ok && v1 {
- c.Log.Base(`Ass`).L(`T: `, "编码:", v)
+ c.C.Log.Base(`Ass`).L(`T: `, "编码:", v)
if v == `utf-8` {
ass.wrap = nil
}
}
if rel, err := filepath.Rel(savestream.base_path, ass.file); err == nil {
- c.Log.Base(`Ass`).L(`I: `, "保存到", rel+".ass")
+ c.C.Log.Base(`Ass`).L(`I: `, "保存到", rel+".ass")
} else {
- c.Log.Base(`Ass`).L(`I: `, "保存到", ass.file+".ass")
- c.Log.Base(`Ass`).L(`W: `, err)
+ c.C.Log.Base(`Ass`).L(`I: `, "保存到", ass.file+".ass")
+ c.C.Log.Base(`Ass`).L(`W: `, err)
}
p.File().FileWR(p.Filel{
File: ass.file + ".ass",
func init() {
//使用带tag的消息队列在功能间传递消息
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
`savestream`: func(data interface{}) bool {
if savestream.cancel.Islive() {
Savestream_wait()
},
})
//base_path
- if path, ok := c.K_v.LoadV("直播流保存位置").(string); ok {
+ if path, ok := c.C.K_v.LoadV("直播流保存位置").(string); ok {
if path, err := filepath.Abs(path); err == nil {
savestream.base_path = path + "/"
}
}
- if v, ok := c.K_v.LoadV(`直播hls流缓冲`).(float64); ok && v > 0 {
+ if v, ok := c.C.K_v.LoadV(`直播hls流缓冲`).(float64); ok && v > 0 {
savestream.hlsbuffersize = int(v)
}
- if v, ok := c.K_v.LoadV(`直播hls流均衡`).(bool); ok {
+ if v, ok := c.C.K_v.LoadV(`直播hls流均衡`).(bool); ok {
savestream.hls_banlance_host = v
}
}
//已go func形式调用,将会获取直播流
func Savestreamf() {
- l := c.Log.Base(`savestream`)
+ l := c.C.Log.Base(`savestream`)
//避免多次开播导致的多次触发
{
defer savestream.skipFunc.UnSet()
}
- want_qn, ok := c.K_v.LoadV("直播流清晰度").(float64)
+ want_qn, ok := c.C.K_v.LoadV("直播流清晰度").(float64)
if !ok || want_qn < 0 {
return
}
- c.Live_want_qn = int(want_qn)
+ c.C.Live_want_qn = int(want_qn)
- F.Get(`Live`)
+ F.Get(&c.C).Get(`Live`)
if savestream.cancel.Islive() {
return
//random host load balance
Host_list := []string{}
if savestream.hls_banlance_host {
- for _, v := range c.Live {
+ for _, v := range c.C.Live {
url_struct, e := url.Parse(v)
if e != nil {
continue
ConnectTimeout: 2000,
ReadTimeout: 1000,
Timeout: 2000,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Header: map[string]string{
`Host`: m3u8_url.Host,
`User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
)
for {
- F.Get(`Liveing`)
- if !c.Liveing {
+ F.Get(&c.C).Get(`Liveing`)
+ if !c.C.Liveing {
break
}
- F.Get(`Live`)
- if len(c.Live) == 0 {
+ F.Get(&c.C).Get(`Live`)
+ if len(c.C.Live) == 0 {
break
}
savestream.path = savestream.base_path
- savestream.path += strconv.Itoa(c.Roomid) + "_" + time.Now().Format("2006_01_02_15-04-05-000")
+ savestream.path += strconv.Itoa(c.C.Roomid) + "_" + time.Now().Format("2006_01_02_15-04-05-000")
savestream.wait = s.Init()
savestream.cancel = s.Init()
CookieM := make(map[string]string)
- c.Cookie.Range(func(k, v interface{}) bool {
+ c.C.Cookie.Range(func(k, v interface{}) bool {
CookieM[k.(string)] = v.(string)
return true
})
}()
l.L(`I: `, "尝试连接live")
if e := r.Reqf(reqf.Rval{
- Url: c.Live[0],
+ Url: c.C.Live[0],
Retry: 10,
SleepTime: 1000,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Header: map[string]string{
`Cookie`: reqf.Map_2_Cookies_String(CookieM),
},
}
}
- if strings.Contains(c.Live[0], "flv") {
+ if strings.Contains(c.C.Live[0], "flv") {
if rel, err := filepath.Rel(savestream.base_path, savestream.path); err == nil {
l.L(`I: `, "保存到", rel+".flv")
} else {
//随机选取服务器,获取超时时间
live_index := 0
- if len(c.Live) > 0 {
- live_index = int(p.Rand().MixRandom(0, int64(len(c.Live)-1)))
+ if len(c.C.Live) > 0 {
+ live_index = int(p.Rand().MixRandom(0, int64(len(c.C.Live)-1)))
}
- link, exp, e := flv_get_link(c.Live[live_index])
+ link, exp, e := flv_get_link(c.C.Live[live_index])
if e != nil {
l.L(`W: `, `流链接获取错误`, e)
break
}
}(req, reqf.Rval{
Url: link,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Header: map[string]string{
`Cookie`: reqf.Map_2_Cookies_String(CookieM),
},
expires := int64(exp) - p.Sys().GetSTime() - 120
// no expect qn
- if c.Live_want_qn < c.Live_qn {
+ if c.C.Live_want_qn < c.C.Live_qn {
expires = time.Now().Add(time.Minute * 2).Unix()
}
l.L(`I: `, "flv关闭,开始新连接")
- //即将过期,刷新c.Live
- F.Get(`Liveing`)
- if !c.Liveing {
+ //即将过期,刷新c.C.Live
+ F.Get(&c.C).Get(`Liveing`)
+ if !c.C.Liveing {
break
}
- F.Get(`Live`)
- if len(c.Live) == 0 {
+ F.Get(&c.C).Get(`Live`)
+ if len(c.C.Live) == 0 {
break
}
}
ConnectTimeout: 5000,
ReadTimeout: 1000,
Retry: 1,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
}); e != nil && !errors.Is(e, io.EOF) {
l.L(`I: `, e)
v.status = s_fail
break
}
- links, file_add, exp, e := hls_get_link(c.Live, last_download)
+ links, file_add, exp, e := hls_get_link(c.C.Live, last_download)
if e != nil {
if e == no_Modified {
time.Sleep(time.Duration(2) * time.Second)
}
//qn in expect , set expires
- if c.Live_want_qn >= c.Live_qn {
+ if c.C.Live_want_qn >= c.C.Live_qn {
expires = int64(exp)
}
} else if len(links) > 100 {
l.L(`W: `, `重试,等待下载切片:`, len(links))
- if F.Get(`Liveing`); !c.Liveing {
+ if F.Get(&c.C).Get(`Liveing`); !c.C.Liveing {
break
}
- if F.Get(`Live`); len(c.Live) == 0 {
+ if F.Get(&c.C).Get(`Live`); len(c.C.Live) == 0 {
break
}
ConnectTimeout: 2000,
ReadTimeout: 1000,
Timeout: 2000,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
}); e != nil {
//try other host
if index+1 < len(Host_list) {
//m3u8_url 将过期
if p.Sys().GetSTime()+60 > expires {
- if F.Get(`Liveing`); !c.Liveing {
+ if F.Get(&c.C).Get(`Liveing`); !c.C.Liveing {
break
}
- if F.Get(`Live`); len(c.Live) == 0 {
+ if F.Get(&c.C).Get(`Live`); len(c.C.Live) == 0 {
break
}
// set expect
}
savestream.cancel.Done()
- c.Log.Base(`savestream`).L(`I: `, "等待停止")
+ c.C.Log.Base(`savestream`).L(`I: `, "等待停止")
savestream.wait.Wait()
}
if !IsOn("调用obs") {
return
}
- l := c.Log.Base(`obs`)
+ l := c.C.Log.Base(`obs`)
if on {
if p.Sys().CheckProgram("obs")[0] != 0 {
return
}
- l := c.Log.Base("obs_R")
+ l := c.C.Log.Base("obs_R")
if p.Sys().CheckProgram("obs")[0] == 0 {
l.L(`W: `, "obs未启动")
} //ban字符重复低去除
res = append(res, pt)
}
- l := c.Log.Base("autoban")
+ l := c.C.Log.Base("autoban")
l.L(`W: `, res)
return true
}
list []string
timeout int
)
- for _, v := range c.K_v.LoadV(`自动弹幕机_内容`).([]interface{}) {
+ for _, v := range c.C.K_v.LoadV(`自动弹幕机_内容`).([]interface{}) {
list = append(list, v.(string))
}
- timeout = int(c.K_v.LoadV(`自动弹幕机_发送间隔s`).(float64))
+ timeout = int(c.C.K_v.LoadV(`自动弹幕机_发送间隔s`).(float64))
if timeout < 5 {
timeout = 5
}
}
autoskip.now += 1
autoskip.Lock()
- if autoskip.roomid != c.Roomid {
+ if autoskip.roomid != c.C.Roomid {
autoskip.buf = make(map[string]Autoskip_item)
- autoskip.roomid = c.Roomid
+ autoskip.roomid = c.C.Roomid
flog.Base_add(`弹幕合并`).L(`T: `, `房间更新:`, autoskip.roomid)
autoskip.Unlock()
continue
delete(autoskip.buf, k)
{ //超时显示
if v.Num > 3 {
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: `0multi`,
m: map[string]string{
`{num}`: strconv.Itoa(int(v.Num)),
}
autoskip.Lock()
defer autoskip.Unlock()
- if autoskip.roomid != c.Roomid {
+ if autoskip.roomid != c.C.Roomid {
autoskip.buf = make(map[string]Autoskip_item)
- autoskip.roomid = c.Roomid
+ autoskip.roomid = c.C.Roomid
flog.Base_add(`弹幕合并`).L(`T: `, `房间更新:`, autoskip.roomid)
return 0
}
}
func init() {
- if max_num, ok := c.K_v.LoadV(`每秒显示弹幕数`).(float64); ok && int(max_num) >= 1 {
+ if max_num, ok := c.C.K_v.LoadV(`每秒显示弹幕数`).(float64); ok && int(max_num) >= 1 {
flog.Base_add(`更少弹幕`).L(`T: `, `每秒弹幕数:`, int(max_num))
lessdanmu.max_num = int(max_num)
lessdanmu.limit = limit.New(int(max_num), 1000, 0) //timeout right now
if !IsOn("相似弹幕忽略") {
return true
}
- if lessdanmu.roomid != c.Roomid {
+ if lessdanmu.roomid != c.C.Roomid {
lessdanmu.buf = nil
- lessdanmu.roomid = c.Roomid
+ lessdanmu.roomid = c.C.Roomid
lessdanmu.threshold = 0.7
flog.Base_add(`更少弹幕`).L(`T: `, `房间更新:`, lessdanmu.roomid)
return true
jiezou.Lock()
if now > 1.3*jiezou.avg { //触发
- c.Log.Base("jiezou").L(`W: `, "节奏注意", now, jiezou.avg, S)
+ c.C.Log.Base("jiezou").L(`W: `, "节奏注意", now, jiezou.avg, S)
jiezou.avg = now //沉默
jiezou.Unlock()
//保存所有消息到json
func init() {
Save_to_json(0, []interface{}{`[`})
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
`change_room`: func(data interface{}) bool { //房间改变
Save_to_json(0, []interface{}{`[`})
return false
}
func Save_to_json(Loc int, Context []interface{}) {
- if path, ok := c.K_v.LoadV(`save_to_json`).(string); ok && path != `` {
+ if path, ok := c.C.K_v.LoadV(`save_to_json`).(string); ok && path != `` {
p.File().FileWR(p.Filel{
File: path,
Loc: int64(Loc),
flog := flog.Base_add(`进房弹幕`)
//检查与切换粉丝牌,只在cookie存在时启用
- F.Get(`CheckSwitch_FansMedal`)
+ F.Get(&c.C).Get(`CheckSwitch_FansMedal`)
- if v, _ := c.K_v.LoadV(`进房弹幕_有粉丝牌时才发`).(bool); v && c.Wearing_FansMedal == 0 {
+ if v, _ := c.C.K_v.LoadV(`进房弹幕_有粉丝牌时才发`).(bool); v && c.C.Wearing_FansMedal == 0 {
flog.L(`T: `, `无粉丝牌`)
return
}
- if v, _ := c.K_v.LoadV(`进房弹幕_仅发首日弹幕`).(bool); v {
+ if v, _ := c.C.K_v.LoadV(`进房弹幕_仅发首日弹幕`).(bool); v {
res := F.Get_weared_medal()
if res.TodayIntimacy > 0 {
flog.L(`T: `, `今日已发弹幕`)
return
}
}
- if array, ok := c.K_v.LoadV(`进房弹幕_内容`).([]interface{}); ok && len(array) != 0 {
+ if array, ok := c.C.K_v.LoadV(`进房弹幕_内容`).([]interface{}); ok && len(array) != 0 {
rand := p.Rand().MixRandom(0, int64(len(array)-1))
- send.Danmu_s(array[rand].(string), c.Roomid)
+ send.Danmu_s(array[rand].(string), c.C.Roomid)
}
}
//保持所有牌子点亮
func Keep_medal_light() {
- if v, _ := c.K_v.LoadV(`保持牌子亮着`).(bool); !v {
+ if v, _ := c.C.K_v.LoadV(`保持牌子亮着`).(bool); !v {
return
}
flog := flog.Base_add(`保持亮牌`)
- array, ok := c.K_v.LoadV(`进房弹幕_内容`).([]interface{})
+ array, ok := c.C.K_v.LoadV(`进房弹幕_内容`).([]interface{})
if !ok || len(array) == 0 {
flog.L(`I: `, `进房弹幕_内容 为 空,退出`)
return
//自动发送即将过期的银瓜子礼物
func AutoSend_silver_gift() {
- day, _ := c.K_v.LoadV(`发送还有几天过期的礼物`).(float64)
+ day, _ := c.C.K_v.LoadV(`发送还有几天过期的礼物`).(float64)
if day <= 0 {
return
}
flog := flog.Base_add(`自动送礼`).L(`T: `, `开始`)
- if c.UpUid == 0 {
- F.Get(`UpUid`)
+ if c.C.UpUid == 0 {
+ F.Get(&c.C).Get(`UpUid`)
}
var hasSend bool
//直播Web服务口
func init() {
flog := flog.Base_add(`直播Web服务`)
- if port_f, ok := c.K_v.LoadV(`直播Web服务口`).(float64); ok && port_f >= 0 {
+ if port_f, ok := c.C.K_v.LoadV(`直播Web服务口`).(float64); ok && port_f >= 0 {
port := int(port_f)
base_dir := savestream.base_path
}
path := filepath.Base(savestream.path)
- if strings.Contains(c.Live[0], "flv") {
+ if strings.Contains(c.C.Live[0], "flv") {
path += ".flv.dtmp"
} else {
path += "/0.m3u8.dtmp"
},
})
host := p.Sys().GetIntranetIp()
- c.Stream_url = strings.Replace(`http://`+s.Server.Addr, `0.0.0.0`, host, -1)
- flog.L(`I: `, `启动于`, c.Stream_url)
+ c.C.Stream_url = strings.Replace(`http://`+s.Server.Addr, `0.0.0.0`, host, -1)
+ flog.L(`I: `, `启动于`, c.C.Stream_url)
}
}
func init() {
communicate.Buf = new(psync.Map)
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
`change_room`: func(data interface{}) bool { //房间改变
communicate.Reset()
return false
数据为WS_OP_MESSAGE类型的数据分派
*/
-var msglog = c.Log.Base(`Msg`)
+var msglog = c.C.Log.Base(`Msg`)
//Msg类型数据处理方法map
var Msg_map = map[string]func(replyF, string){
mq "github.com/qydysky/part/msgq"
)
-var reply_log = c.Log.Base(`Reply`)
+var reply_log = c.C.Log.Base(`Reply`)
//返回数据分派
//传入接受到的ws数据
return
}
{ //语言tts
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{
uid: `0room`,
m: map[string]string{
`{msg}`: j.Data.InteractMsg,
uname := p.Json().GetValFromS(s, "data.uname")
if v, ok := uname.(string); ok {
{ //语言tts
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{
uid: `0follow`,
msg: fmt.Sprint(v + `关注了直播间`),
})
}
if price != 0 {
sh_log = append(sh, "¥", price/1000) //不在界面显示价格
- c.Danmu_Main_mq.Push_tag(`c.Rev_add`, float64(price)/1000)
+ c.C.Danmu_Main_mq.Push_tag(`c.Rev_add`, float64(price)/1000)
}
{ //语言tts
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: `0buyguide`,
m: map[string]string{
`{username}`: username,
}
{ //额外 ass 私信
Assf(fmt.Sprintln(sh...))
- c.Danmu_Main_mq.Push_tag(`guard_update`, nil) //使用连续付费的新舰长无法区分,刷新舰长数
+ c.C.Danmu_Main_mq.Push_tag(`guard_update`, nil) //使用连续付费的新舰长无法区分,刷新舰长数
if uid != 0 {
- c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+ c.C.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
Uid: uid,
- Msg: c.K_v.LoadV(`上舰私信`).(string),
+ Msg: c.C.K_v.LoadV(`上舰私信`).(string),
}) //上舰私信
}
- if c.K_v.LoadV(`额外私信对象`).(float64) != 0 {
- c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
- Uid: int(c.K_v.LoadV(`额外私信对象`).(float64)),
- Msg: c.K_v.LoadV(`上舰私信(额外)`).(string),
+ if c.C.K_v.LoadV(`额外私信对象`).(float64) != 0 {
+ c.C.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+ Uid: int(c.C.K_v.LoadV(`额外私信对象`).(float64)),
+ Msg: c.C.K_v.LoadV(`上舰私信(额外)`).(string),
}) //上舰私信-对额外
}
}
)
func (replyF) heartbeat(s int) {
- c.Danmu_Main_mq.Push_tag(`c.Renqi`, s) //使用连续付费的新舰长无法区分,刷新舰长数
+ c.C.Danmu_Main_mq.Push_tag(`c.Renqi`, s) //使用连续付费的新舰长无法区分,刷新舰长数
if s == 1 {
return
} //人气为1,不输出
if title != nil {
sh = append(sh, title)
- c.Title = title.(string)
+ c.C.Title = title.(string)
}
if area_name != nil {
sh = append(sh, area_name)
if total_coin != 0 {
allprice = float64(total_coin) / 1000
sh_log = append(sh, fmt.Sprintf("¥%.1f", allprice)) //不在界面显示价格
- c.Danmu_Main_mq.Push_tag(`c.Rev_add`, allprice)
+ c.C.Danmu_Main_mq.Push_tag(`c.Rev_add`, allprice)
}
if len(sh) == 0 {
//小于设定
{
var tmp = 20.0
- if v, ok := c.K_v.Load(`弹幕_礼物金额显示阈值`); ok {
+ if v, ok := c.C.K_v.Load(`弹幕_礼物金额显示阈值`); ok {
tmp = v.(float64)
}
if allprice < tmp {
}
{ //语言tts
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: `0gift`,
m: map[string]string{
`{num}`: strconv.Itoa(num),
Obsf(false)
Savestream_wait()
go ShowRevf()
- c.Liveing = false
+ c.C.Liveing = false
}
if p.Sys().Type(roomid) == "float64" {
Gui_show(Itos([]interface{}{"房间", roomid, "下播了"}), "0room")
go Savestreamf()
}
{
- c.Rev = 0.0 //营收
- c.Liveing = true //直播i标志
- c.Live_Start_Time = time.Now() //开播h时间
+ c.C.Rev = 0.0 //营收
+ c.C.Liveing = true //直播i标志
+ c.C.Live_Start_Time = time.Now() //开播h时间
}
if p.Sys().Type(roomid) == "float64" {
Gui_show(Itos([]interface{}{"房间", roomid, "开播了"}), "0room")
if price != 0 {
sh = append(sh, "\n") //界面不显示价格
logg = append(logg, "¥", price)
- c.Danmu_Main_mq.Push_tag(`c.Rev_add`, float64(price))
+ c.C.Danmu_Main_mq.Push_tag(`c.Rev_add`, float64(price))
}
fmt.Println("====")
fmt.Println(sh...)
logg = append(logg, message)
}
{ //语言tts
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: `0superchat`,
m: map[string]string{
`{uname}`: uname,
return
} else {
if v, ok := note.(string); ok {
- c.Note = v
+ c.C.Note = v
}
fmt.Println("排行", note)
msglog.L(`I: `, "排行", note)
msglog.L(`E: `, e)
}
if type_item.Data.Area_name != `` {
- c.Note = type_item.Data.Area_name + " "
+ c.C.Note = type_item.Data.Area_name + " "
if type_item.Data.Rank == 0 {
- c.Note += "50+"
+ c.C.Note += "50+"
} else {
- c.Note += strconv.Itoa(type_item.Data.Rank)
+ c.C.Note += strconv.Itoa(type_item.Data.Rank)
}
- fmt.Printf("%s\t%s\n", "热门榜", c.Note)
- msglog.L(`I: `, "热门榜", c.Note)
+ fmt.Printf("%s\t%s\n", "热门榜", c.C.Note)
+ msglog.L(`I: `, "热门榜", c.C.Note)
}
}
msglog.L(`E: `, e)
}
if type_item.Data.AreaName != `` {
- c.Note = type_item.Data.AreaName + " "
+ c.C.Note = type_item.Data.AreaName + " "
if type_item.Data.Rank == 0 {
- c.Note += "50+"
+ c.C.Note += "50+"
} else {
- c.Note += strconv.Itoa(type_item.Data.Rank)
+ c.C.Note += strconv.Itoa(type_item.Data.Rank)
}
- fmt.Printf("%s\t%s\n", "热门榜", c.Note)
- msglog.L(`I: `, "热门榜", c.Note)
+ fmt.Printf("%s\t%s\n", "热门榜", c.C.Note)
+ msglog.L(`I: `, "热门榜", c.C.Note)
}
}
tmp += strconv.Itoa(type_item.Data.Rank)
}
Gui_show(tmp, "0rank")
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: "0rank",
m: map[string]string{
`{Area_name}`: type_item.Data.Area_name,
tmp += strconv.Itoa(type_item.Data.Rank)
}
Gui_show(tmp, "0rank")
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: "0rank",
m: map[string]string{
`{Area_name}`: type_item.Data.AreaName,
}
{ //语言tts
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: img,
m: map[string]string{
`{guard_name}`: guard_name,
item.auth = i[1]
}
}
- item.roomid = c.Roomid
+ item.roomid = c.C.Roomid
}
msglog := msglog.Log_show_control(false)
`bili_jct`,
`DedeUserID`,
`LIVE_BUVID`,
- }); len(missKey) != 0 || c.Roomid == 0 {
+ }); len(missKey) != 0 || c.C.Roomid == 0 {
msglog.L(`E: `, `c.Roomid == 0 || Cookie无Key:`, missKey)
return
}
- send.Danmu_s(msg, c.Roomid)
+ send.Danmu_s(msg, c.C.Roomid)
}
//弹幕显示
msglog := msglog.Log_show_control(false)
//room change
- if item.roomid != 0 && item.roomid != c.Roomid {
+ if item.roomid != 0 && item.roomid != c.C.Roomid {
return
}
{ //语言tts 私信
if item.uid != "" {
if item.auth != nil {
- c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+ c.C.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
uid: item.uid,
m: map[string]string{
`{auth}`: fmt.Sprint(item.auth),
})
}
if i, e := strconv.Atoi(item.uid); e == nil {
- c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+ c.C.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
Uid: i,
- Msg: c.K_v.LoadV(`弹幕私信`).(string),
+ Msg: c.C.K_v.LoadV(`弹幕私信`).(string),
}) //上舰私信
}
- if c.K_v.LoadV(`额外私信对象`).(float64) != 0 {
- c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
- Uid: int(c.K_v.LoadV(`额外私信对象`).(float64)),
- Msg: c.K_v.LoadV(`弹幕私信(额外)`).(string),
+ if c.C.K_v.LoadV(`额外私信对象`).(float64) != 0 {
+ c.C.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+ Uid: int(c.C.K_v.LoadV(`额外私信对象`).(float64)),
+ Msg: c.C.K_v.LoadV(`弹幕私信(额外)`).(string),
}) //上舰私信-对额外
}
}
package reply
import (
- "os"
- "fmt"
"bytes"
- "time"
"errors"
+ "fmt"
+ "os"
+ "time"
+
// "math"
c "github.com/qydysky/bili_danmu/CV"
)
const (
- flv_header_size = 9
- tag_header_size = 11
+ flv_header_size = 9
+ tag_header_size = 11
previou_tag_size = 4
- video_tag = byte(0x09)
- audio_tag = byte(0x08)
+ video_tag = byte(0x09)
+ audio_tag = byte(0x08)
script_tag = byte(0x12)
//custom define
)
var (
- flv_header_sign = []byte{0x46,0x4c,0x56}
- flvlog = c.Log.Base(`flv解码`)
- send_sign = []byte{0x00}
+ flv_header_sign = []byte{0x46, 0x4c, 0x56}
+ flvlog = c.C.Log.Base(`flv解码`)
+ send_sign = []byte{0x00}
)
type flv_source struct {
- buf []byte
- Rval reqf.Rval
+ buf []byte
+ Rval reqf.Rval
Inuse bool
}
// }
type flv_tag struct {
- Tag byte
- Offset int64
+ Tag byte
+ Offset int64
Timestamp int32
- PreSize int32
+ PreSize int32
FirstByte byte
- Buf *[]byte
+ Buf *[]byte
}
// func Tag_stream(c chan []byte,co chan []byte) ( bool) {
// //check channel
// if c == nil || co == nil {return}
-
+
// var (
// buf []byte
// seach_stream_tag = func(buf []byte)(front_buf []byte,available_offset int64){
// return true
// }
-func Stream(path string,front_buf *[]byte,streamChan chan []byte,cancel chan struct{}) (error) {
- flvlog.L(`T: `,path)
- defer flvlog.L(`T: `,`退出`)
+func Stream(path string, front_buf *[]byte, streamChan chan []byte, cancel chan struct{}) error {
+ flvlog.L(`T: `, path)
+ defer flvlog.L(`T: `, `退出`)
//file
- f,err := os.OpenFile(path,os.O_RDONLY,0644)
+ f, err := os.OpenFile(path, os.O_RDONLY, 0644)
if err != nil {
return err
}
//get flv header(9byte) + FirstTagSize(4byte)
{
buf := make([]byte, flv_header_size+previou_tag_size)
- if _,err := f.Read(buf);err != nil {return err}
- if bytes.Index(buf,flv_header_sign) != 0 {return errors.New(`no flv`)}
+ if _, err := f.Read(buf); err != nil {
+ return err
+ }
+ if bytes.Index(buf, flv_header_sign) != 0 {
+ return errors.New(`no flv`)
+ }
*front_buf = append(*front_buf, buf...)
}
type flv_tag struct {
- Tag byte
- Offset int64
+ Tag byte
+ Offset int64
Timestamp int32
- PreSize int32
+ PreSize int32
FirstByte byte
- Buf *[]byte
+ Buf *[]byte
}
- var seachtag = func(f *os.File, begin_offset int64)(available_offset int64){
+ var seachtag = func(f *os.File, begin_offset int64) (available_offset int64) {
available_offset += begin_offset
- f.Seek(begin_offset, 0)//seek to begin
+ f.Seek(begin_offset, 0) //seek to begin
buf := make([]byte, 1024*1024*10)
- if size,_ := f.Read(buf);size == 0 {
+ if size, _ := f.Read(buf); size == 0 {
return
} else {
- for buf_offset:=0;buf_offset<size; {
- if tag_offset := bytes.IndexAny(buf[buf_offset:], string([]byte{video_tag,audio_tag,script_tag}));tag_offset == -1 {
+ for buf_offset := 0; buf_offset < size; {
+ if tag_offset := bytes.IndexAny(buf[buf_offset:], string([]byte{video_tag, audio_tag, script_tag})); tag_offset == -1 {
return
- } else if streamid_offset := bytes.Index(buf[tag_offset:], []byte{0x00,0x00,0x00});streamid_offset == -1 {
+ } else if streamid_offset := bytes.Index(buf[tag_offset:], []byte{0x00, 0x00, 0x00}); streamid_offset == -1 {
return
} else if streamid_offset == 8 {
available_offset += int64(tag_offset + buf_offset)
}
//get tag func
- var getTag = func(f *os.File)(t flv_tag){
- t.Offset,_ = f.Seek(0,1)
+ var getTag = func(f *os.File) (t flv_tag) {
+ t.Offset, _ = f.Seek(0, 1)
Buf := []byte{}
t.Buf = &Buf
buf := make([]byte, tag_header_size)
- if size,err := f.Read(buf);err != nil || size == 0 {
+ if size, err := f.Read(buf); err != nil || size == 0 {
t.Tag = eof_tag
return
}
Buf = append(Buf, buf...)
t.Tag = buf[0]
- t.Timestamp = F.Btoi32([]byte{buf[7],buf[4],buf[5],buf[6]},0)
+ t.Timestamp = F.Btoi32([]byte{buf[7], buf[4], buf[5], buf[6]}, 0)
- size := F.Btoi32(append([]byte{0x00},buf[1:4]...),0)
+ size := F.Btoi32(append([]byte{0x00}, buf[1:4]...), 0)
data := make([]byte, size)
- if size,err := f.Read(data);err != nil || size == 0 {
+ if size, err := f.Read(data); err != nil || size == 0 {
t.Tag = eof_tag
return
}
t.FirstByte = data[0]
pre_tag := make([]byte, previou_tag_size)
- if size,err := f.Read(pre_tag);err != nil || size == 0 {
+ if size, err := f.Read(pre_tag); err != nil || size == 0 {
t.Tag = eof_tag
return
- }
- t.PreSize = F.Btoi32(pre_tag,0)
-
+ }
+ t.PreSize = F.Btoi32(pre_tag, 0)
+
Buf = append(Buf, append(data, pre_tag...)...)
// if t.PreSize == 0{fmt.Println(t.Tag,size,data[size:])}
//find last_keyframe_video_offset
var (
last_keyframe_video_offsets []int64
- first_video_tag bool
- first_audio_tag bool
+ first_video_tag bool
+ first_audio_tag bool
// last_timestamps []int32
)
for {
*front_buf = append(*front_buf, *t.Buf...)
}
- if t.FirstByte & 0xf0 == 0x10 {
+ if t.FirstByte&0xf0 == 0x10 {
if len(last_keyframe_video_offsets) > 2 {
// last_timestamps = append(last_timestamps[1:], t.Timestamp)
last_keyframe_video_offsets = append(last_keyframe_video_offsets[1:], t.Offset)
first_audio_tag = true
*front_buf = append(*front_buf, *t.Buf...)
}
- } else {//eof_tag
- break;
+ } else { //eof_tag
+ break
}
}
//seed to the second last tag
- if len(last_keyframe_video_offsets) == 0 {flvlog.L(`W: `,`no keyframe`);return errors.New(`no keyframe`)}
- f.Seek(last_keyframe_video_offsets[0],0)
-
+ if len(last_keyframe_video_offsets) == 0 {
+ flvlog.L(`W: `, `no keyframe`)
+ return errors.New(`no keyframe`)
+ }
+ f.Seek(last_keyframe_video_offsets[0], 0)
// var (
// last_video_keyframe_timestramp int32
for {
//退出
select {
- case <-cancel:return nil;
- default:;
+ case <-cancel:
+ return nil
+ default:
}
t := getTag(f)
if t.Tag == eof_tag {
- f.Seek(last_available_offset,0)
+ f.Seek(last_available_offset, 0)
time.Sleep(time.Second)
continue
} else if t.PreSize == 0 {
- f.Seek(seachtag(f, last_available_offset),0)
+ f.Seek(seachtag(f, last_available_offset), 0)
continue
} else if t.Tag == video_tag {
- if t.FirstByte & 0xf0 == 0x10 {
+ if t.FirstByte&0xf0 == 0x10 {
streamChan <- buf
buf = []byte{}
}
} else if t.Tag == audio_tag {
buf = append(buf, *t.Buf...)
} else if t.Tag != script_tag {
- ;
+
}
-
+
last_available_offset = t.Offset
}
return nil
}
-func TimeStramp_Check(path string) (error) {
+func TimeStramp_Check(path string) error {
//file
- f,err := os.OpenFile(path,os.O_RDONLY,0644)
+ f, err := os.OpenFile(path, os.O_RDONLY, 0644)
if err != nil {
return err
}
//get flv header(9byte) + FirstTagSize(4byte)
{
buf := make([]byte, flv_header_size+previou_tag_size)
- if _,err := f.Read(buf);err != nil {return err}
- if bytes.Index(buf,flv_header_sign) != 0 {return errors.New(`no flv`)}
+ if _, err := f.Read(buf); err != nil {
+ return err
+ }
+ if bytes.Index(buf, flv_header_sign) != 0 {
+ return errors.New(`no flv`)
+ }
}
type flv_tag struct {
- Tag byte
- Offset int64
+ Tag byte
+ Offset int64
Timestamp int32
- PreSize int32
+ PreSize int32
FirstByte byte
}
//get tag func
- var getTag = func(f *os.File)(t flv_tag){
- t.Offset,_ = f.Seek(0,1)
+ var getTag = func(f *os.File) (t flv_tag) {
+ t.Offset, _ = f.Seek(0, 1)
buf := make([]byte, tag_header_size)
- if size,err := f.Read(buf);err != nil || size == 0 {
+ if size, err := f.Read(buf); err != nil || size == 0 {
t.Tag = eof_tag
return
}
t.Tag = buf[0]
- t.Timestamp = F.Btoi32([]byte{buf[7],buf[4],buf[5],buf[6]},0)
+ t.Timestamp = F.Btoi32([]byte{buf[7], buf[4], buf[5], buf[6]}, 0)
- size := F.Btoi32(append([]byte{0x00},buf[1:4]...),0)
+ size := F.Btoi32(append([]byte{0x00}, buf[1:4]...), 0)
data := make([]byte, size)
- if size,err := f.Read(data);err != nil || size == 0 {
+ if size, err := f.Read(data); err != nil || size == 0 {
t.Tag = eof_tag
return
}
t.FirstByte = data[0]
pre_tag := make([]byte, previou_tag_size)
- if size,err := f.Read(pre_tag);err != nil || size == 0 {
+ if size, err := f.Read(pre_tag); err != nil || size == 0 {
t.Tag = eof_tag
return
- }
- t.PreSize = F.Btoi32(pre_tag,0)
-
+ }
+ t.PreSize = F.Btoi32(pre_tag, 0)
+
// if t.PreSize == 0{fmt.Println(t.Tag,size,data[size:])}
return
continue
} else if t.Tag == video_tag || t.Tag == audio_tag {
if t.Timestamp < lasttimestramp {
- fmt.Printf("error: now %d < pre %d\n",t.Timestamp,lasttimestramp)
+ fmt.Printf("error: now %d < pre %d\n", t.Timestamp, lasttimestramp)
lasttimestramp = t.Timestamp
continue
}
- fmt.Printf("%d\n",t.Timestamp)
+ fmt.Printf("%d\n", t.Timestamp)
lasttimestramp = t.Timestamp
- if lasttimestramp > 10000 {return nil}
- } else {//eof_tag
- break;
+ if lasttimestramp > 10000 {
+ return nil
+ }
+ } else { //eof_tag
+ break
}
}
fmt.Printf("ok\n")
// this fuction read []byte and return flv header and all complete keyframe if possible.
// complete keyframe means the video and audio tags between two video key frames tag
-func Seach_stream_tag(buf []byte)(front_buf []byte, keyframe[][]byte,err error){
+func Seach_stream_tag(buf []byte) (front_buf []byte, keyframe [][]byte, err error) {
//get flv header(9byte) + FirstTagSize(4byte)
- if header_offset := bytes.Index(buf,flv_header_sign);header_offset != -1 {
- front_buf = buf[header_offset:header_offset+flv_header_size+previou_tag_size]
+ if header_offset := bytes.Index(buf, flv_header_sign); header_offset != -1 {
+ front_buf = buf[header_offset : header_offset+flv_header_size+previou_tag_size]
}
var (
- sign = 0x00
+ sign = 0x00
keyframe_num = -1
- tag_num = 0
+ tag_num = 0
)
- defer func(){
+ defer func() {
if sign != 0x07 {
front_buf = []byte{}
}
}
}()
- for buf_offset:=0;buf_offset+tag_header_size<len(buf); {
+ for buf_offset := 0; buf_offset+tag_header_size < len(buf); {
- tag_offset := buf_offset+bytes.IndexAny(buf[buf_offset:], string([]byte{video_tag,audio_tag,script_tag}));
+ tag_offset := buf_offset + bytes.IndexAny(buf[buf_offset:], string([]byte{video_tag, audio_tag, script_tag}))
if tag_offset == buf_offset-1 {
err = errors.New(`no found available tag`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//no found available video,audio,script tag
+ return //no found available video,audio,script tag
}
if tag_offset+tag_header_size > len(buf) {
err = errors.New(`reach end when get tag header`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
- streamid := int(F.Btoi32([]byte{0x00,buf[tag_offset+8],buf[tag_offset+9],buf[tag_offset+10]},0))
+ streamid := int(F.Btoi32([]byte{0x00, buf[tag_offset+8], buf[tag_offset+9], buf[tag_offset+10]}, 0))
if streamid != 0 {
buf_offset = tag_offset + 1
// fmt.Printf("streamid error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//streamid error
+ continue //streamid error
}
- tag_size := int(F.Btoi32([]byte{0x00,buf[tag_offset+1],buf[tag_offset+2],buf[tag_offset+3]},0))
+ tag_size := int(F.Btoi32([]byte{0x00, buf[tag_offset+1], buf[tag_offset+2], buf[tag_offset+3]}, 0))
if tag_offset+tag_header_size+tag_size+previou_tag_size > len(buf) {
err = errors.New(`reach end when get tag body`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
if tag_size == 0 {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size error
+ continue //tag_size error
}
- tag_size_check := int(F.Btoi32(buf[tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size],0))
- if tag_num + tag_size_check == 0 {tag_size_check = tag_size+tag_header_size}
+ tag_size_check := int(F.Btoi32(buf[tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size], 0))
+ if tag_num+tag_size_check == 0 {
+ tag_size_check = tag_size + tag_header_size
+ }
if tag_size_check != tag_size+tag_header_size {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size_check error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size_check error
+ continue //tag_size_check error
}
- time_stamp := int(F.Btoi32([]byte{buf[tag_offset+7], buf[tag_offset+4], buf[tag_offset+5], buf[tag_offset+6]},0))
-
+ time_stamp := int(F.Btoi32([]byte{buf[tag_offset+7], buf[tag_offset+4], buf[tag_offset+5], buf[tag_offset+6]}, 0))
+
// fmt.Printf("%x\n",buf[tag_offset:tag_offset+tag_header_size])
tag_num += 1
if time_stamp == 0 {
if len(front_buf) != 0 {
- if (buf[tag_offset] == video_tag) && (sign & 0x04 == 0x00) {
+ if (buf[tag_offset] == video_tag) && (sign&0x04 == 0x00) {
sign |= 0x04
front_buf = append(front_buf, buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
- } else if (buf[tag_offset] == audio_tag) && (sign & 0x02 == 0x00) {
+ } else if (buf[tag_offset] == audio_tag) && (sign&0x02 == 0x00) {
sign |= 0x02
front_buf = append(front_buf, buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
- } else if (buf[tag_offset] == script_tag) && (sign & 0x01 == 0x00) {
+ } else if (buf[tag_offset] == script_tag) && (sign&0x01 == 0x00) {
sign |= 0x01
front_buf = append(front_buf, buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
}
}
- buf_offset = tag_offset+tag_size_check+previou_tag_size
+ buf_offset = tag_offset + tag_size_check + previou_tag_size
continue
}
-
+
if buf[tag_offset] == video_tag {
- if buf[tag_offset+11] & 0xf0 == 0x10 {//key frame
+ if buf[tag_offset+11]&0xf0 == 0x10 { //key frame
keyframe_num += 1
- keyframe = append(keyframe,[]byte{})
+ keyframe = append(keyframe, []byte{})
}
if keyframe_num >= 0 {
if keyframe_num >= 0 {
keyframe[keyframe_num] = append(keyframe[keyframe_num], buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
}
- } else {;}
+ } else {
+ }
- buf_offset = tag_offset+tag_size_check+previou_tag_size
+ buf_offset = tag_offset + tag_size_check + previou_tag_size
}
-
+
return
}
//same as Seach_stream_tag but faster
-func Seach_keyframe_tag(buf []byte)(front_buf []byte, keyframe[][]byte,err error){
+func Seach_keyframe_tag(buf []byte) (front_buf []byte, keyframe [][]byte, err error) {
var (
sign = 0x00
// keyframe_num = -1
- tag_num = 0
+ tag_num = 0
buf_offset = 0
)
- defer func(){
+ defer func() {
if sign != 0x07 {
front_buf = []byte{}
}
}()
//front_buf
- if header_offset := bytes.Index(buf,flv_header_sign);header_offset != -1 {
- front_buf = buf[header_offset:header_offset+flv_header_size+previou_tag_size]
+ if header_offset := bytes.Index(buf, flv_header_sign); header_offset != -1 {
+ front_buf = buf[header_offset : header_offset+flv_header_size+previou_tag_size]
- for ;buf_offset+tag_header_size<len(buf); {
+ for buf_offset+tag_header_size < len(buf) {
- tag_offset := buf_offset+bytes.IndexAny(buf[buf_offset:], string([]byte{video_tag,audio_tag,script_tag}));
+ tag_offset := buf_offset + bytes.IndexAny(buf[buf_offset:], string([]byte{video_tag, audio_tag, script_tag}))
if tag_offset == buf_offset-1 {
err = errors.New(`no found available tag`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//no found available video,audio,script tag
+ return //no found available video,audio,script tag
}
if tag_offset+tag_header_size > len(buf) {
err = errors.New(`reach end when get tag header`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
-
- if buf[tag_offset+8] | buf[tag_offset+9] | buf[tag_offset+10] != 0 {
+
+ if buf[tag_offset+8]|buf[tag_offset+9]|buf[tag_offset+10] != 0 {
buf_offset = tag_offset + 1
// fmt.Printf("streamid error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//streamid error
+ continue //streamid error
}
-
- tag_size := int(F.Btoi32([]byte{0x00,buf[tag_offset+1],buf[tag_offset+2],buf[tag_offset+3]},0))
+
+ tag_size := int(F.Btoi32([]byte{0x00, buf[tag_offset+1], buf[tag_offset+2], buf[tag_offset+3]}, 0))
if tag_offset+tag_header_size+tag_size+previou_tag_size > len(buf) {
err = errors.New(`reach end when get tag body`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
if tag_size == 0 {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size error
+ continue //tag_size error
+ }
+
+ tag_size_check := int(F.Btoi32(buf[tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size], 0))
+ if tag_num+tag_size_check == 0 {
+ tag_size_check = tag_size + tag_header_size
}
-
- tag_size_check := int(F.Btoi32(buf[tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size],0))
- if tag_num + tag_size_check == 0 {tag_size_check = tag_size+tag_header_size}
if tag_size_check != tag_size+tag_header_size {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size_check error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size_check error
+ continue //tag_size_check error
}
-
+
tag_num += 1
-
- if buf[tag_offset+7] | buf[tag_offset+4] | buf[tag_offset+5] | buf[tag_offset+6] == 0 {
+
+ if buf[tag_offset+7]|buf[tag_offset+4]|buf[tag_offset+5]|buf[tag_offset+6] == 0 {
if len(front_buf) != 0 {
- if (buf[tag_offset] == video_tag) && (sign & 0x04 == 0x00) {
+ if (buf[tag_offset] == video_tag) && (sign&0x04 == 0x00) {
sign |= 0x04
front_buf = append(front_buf, buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
- } else if (buf[tag_offset] == audio_tag) && (sign & 0x02 == 0x00) {
+ } else if (buf[tag_offset] == audio_tag) && (sign&0x02 == 0x00) {
sign |= 0x02
front_buf = append(front_buf, buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
- } else if (buf[tag_offset] == script_tag) && (sign & 0x01 == 0x00) {
+ } else if (buf[tag_offset] == script_tag) && (sign&0x01 == 0x00) {
sign |= 0x01
front_buf = append(front_buf, buf[tag_offset:tag_offset+tag_size_check+previou_tag_size]...)
}
}
- buf_offset = tag_offset+tag_size_check+previou_tag_size
+ buf_offset = tag_offset + tag_size_check + previou_tag_size
+ }
+ if sign == 0x07 {
+ break
}
- if sign == 0x07 {break}
}
}
//keyframe
var last_keyframe_offset int
- for ;buf_offset+tag_header_size<len(buf); {
+ for buf_offset+tag_header_size < len(buf) {
- tag_offset := buf_offset+bytes.Index(buf[buf_offset:], []byte{video_tag})
+ tag_offset := buf_offset + bytes.Index(buf[buf_offset:], []byte{video_tag})
if tag_offset == buf_offset-1 {
err = errors.New(`no found available tag`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//no found available video,audio,script tag
+ return //no found available video,audio,script tag
}
if tag_offset+tag_header_size > len(buf) {
err = errors.New(`reach end when get tag header`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
- if buf[tag_offset+8] | buf[tag_offset+9] | buf[tag_offset+10] != 0 {
+ if buf[tag_offset+8]|buf[tag_offset+9]|buf[tag_offset+10] != 0 {
buf_offset = tag_offset + 1
// fmt.Printf("streamid error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//streamid error
+ continue //streamid error
}
- tag_size := int(F.Btoi32([]byte{0x00,buf[tag_offset+1],buf[tag_offset+2],buf[tag_offset+3]},0))
+ tag_size := int(F.Btoi32([]byte{0x00, buf[tag_offset+1], buf[tag_offset+2], buf[tag_offset+3]}, 0))
if tag_offset+tag_header_size+tag_size+previou_tag_size > len(buf) {
err = errors.New(`reach end when get tag body`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
if tag_size == 0 {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size error
+ continue //tag_size error
}
- tag_size_check := int(F.Btoi32(buf[tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size],0))
- if tag_num + tag_size_check == 0 {tag_size_check = tag_size+tag_header_size}
+ tag_size_check := int(F.Btoi32(buf[tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size], 0))
+ if tag_num+tag_size_check == 0 {
+ tag_size_check = tag_size + tag_header_size
+ }
if tag_size_check != tag_size+tag_header_size {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size_check error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size_check error
+ continue //tag_size_check error
}
-
+
// fmt.Printf("%x\n",buf[tag_offset:tag_offset+tag_header_size])
tag_num += 1
-
+
if buf[tag_offset] == video_tag {
- if buf[tag_offset+11] & 0xf0 == 0x10 {//key frame
+ if buf[tag_offset+11]&0xf0 == 0x10 { //key frame
if last_keyframe_offset != 0 {
- keyframe = append(keyframe,buf[last_keyframe_offset:tag_offset])
+ keyframe = append(keyframe, buf[last_keyframe_offset:tag_offset])
}
last_keyframe_offset = tag_offset
}
}
- buf_offset = tag_offset+tag_size_check+previou_tag_size
+ buf_offset = tag_offset + tag_size_check + previou_tag_size
}
return
//this fuction merge two stream and return the merge buffer,which has the newest frame.
//once len(merge_buf) isn't 0,old_buf can be drop and new_buf can be used from now on.or it's still need to keep buf until find the same tag.
-func Merge_stream(keyframe_lists [][][]byte,last_keyframe_timestramp int)(keyframe_timestamp int,merge_buf []byte,merged int){
+func Merge_stream(keyframe_lists [][][]byte, last_keyframe_timestramp int) (keyframe_timestamp int, merge_buf []byte, merged int) {
- if len(keyframe_lists) == 0 {return}
+ if len(keyframe_lists) == 0 {
+ return
+ }
// var keyframe_lists [][][]byte
// for i:=0;i<len(bufs);i+=1 {
// }
var (
- buf [][]byte
+ buf [][]byte
buf_o int
)
buf = keyframe_lists[0]
-
+
// fmt.Println(`buf:`,len(buf[0]),buf[0][:tag_header_size])
- // fmt.Println(`buf:`,buf[len(buf)-1][:tag_header_size])
+ // fmt.Println(`buf:`,buf[len(buf)-1][:tag_header_size])
// fmt.Println(`buf1:`,len(keyframe_lists[1]),keyframe_lists[1][0][:tag_header_size])
// fmt.Println(`buf1:`,keyframe_lists[1][len(keyframe_lists[1])-1][:tag_header_size])
- for i:=1;i<len(keyframe_lists);i+=1 {
- for n:=buf_o;n<len(buf);n+=1 {
- for o:=0;o<len(keyframe_lists[i]);o+=1 {
- // fmt.Println(keyframe_lists[o])
- // keyframe_list_i_header := fmt.Sprintf("%x",keyframe_lists[i][o][:tag_header_size-3])
- // old_buf_o := buf_o
- if bytes.Index(buf[n][1:4],keyframe_lists[i][o][1:4]) != -1 {
+ for i := 1; i < len(keyframe_lists); i += 1 {
+ for n := buf_o; n < len(buf); n += 1 {
+ for o := 0; o < len(keyframe_lists[i]); o += 1 {
+ // fmt.Println(keyframe_lists[o])
+ // keyframe_list_i_header := fmt.Sprintf("%x",keyframe_lists[i][o][:tag_header_size-3])
+ // old_buf_o := buf_o
+ if bytes.Index(buf[n][1:4], keyframe_lists[i][o][1:4]) != -1 {
// last_time_stamp := int(F.Btoi32([]byte{buf[n][7], buf[n][4], buf[n][5], buf[n][6]},0))
// tmp_kfs := make([][]byte,len(keyframe_lists[i][o:]))
- keyframe_timestamp,_ = Keyframe_timebase(keyframe_lists[i][o:],last_keyframe_timestramp)
+ keyframe_timestamp, _ = Keyframe_timebase(keyframe_lists[i][o:], last_keyframe_timestramp)
buf = append(buf[:n], keyframe_lists[i][o:]...)
merged = i
// merged = len(buf) != len(keyframe_lists[0])
- for n:=0;n<len(buf);n+=1 {
+ for n := 0; n < len(buf); n += 1 {
merge_buf = append(merge_buf, buf[n]...)
}
return
// return
}
-func Keyframe_timebase(buf [][]byte,last_keyframe_timestamp int)(keyframe_timestamp int,err error){
+func Keyframe_timebase(buf [][]byte, last_keyframe_timestamp int) (keyframe_timestamp int, err error) {
var (
- tag_num int
+ tag_num int
base_keyframe_time int
- keyframe_interval int
+ keyframe_interval int
)
//search keyframe
{
- var first_t,last_t int
- for buf_offset:=0;buf_offset+tag_header_size<len(buf[0]); {
+ var first_t, last_t int
+ for buf_offset := 0; buf_offset+tag_header_size < len(buf[0]); {
- tag_offset := buf_offset+bytes.IndexAny(buf[0][buf_offset:], string([]byte{video_tag,audio_tag,script_tag}));
+ tag_offset := buf_offset + bytes.IndexAny(buf[0][buf_offset:], string([]byte{video_tag, audio_tag, script_tag}))
if tag_offset == buf_offset-1 {
err = errors.New(`no found available tag`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//no found available video,audio,script tag
+ return //no found available video,audio,script tag
}
if tag_offset+tag_header_size > len(buf[0]) {
err = errors.New(`reach end when get tag header`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
-
- if buf[0][tag_offset+8] | buf[0][tag_offset+9] | buf[0][tag_offset+10] != 0 {
+
+ if buf[0][tag_offset+8]|buf[0][tag_offset+9]|buf[0][tag_offset+10] != 0 {
buf_offset = tag_offset + 1
// fmt.Printf("streamid error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//streamid error
+ continue //streamid error
}
-
- tag_size := int(F.Btoi32([]byte{0x00,buf[0][tag_offset+1],buf[0][tag_offset+2],buf[0][tag_offset+3]},0))
+
+ tag_size := int(F.Btoi32([]byte{0x00, buf[0][tag_offset+1], buf[0][tag_offset+2], buf[0][tag_offset+3]}, 0))
if tag_offset+tag_header_size+tag_size+previou_tag_size > len(buf[0]) {
err = errors.New(`reach end when get tag body`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
if tag_size == 0 {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size error
+ continue //tag_size error
+ }
+
+ tag_size_check := int(F.Btoi32(buf[0][tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size], 0))
+ if tag_num+tag_size_check == 0 {
+ tag_size_check = tag_size + tag_header_size
}
-
- tag_size_check := int(F.Btoi32(buf[0][tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size],0))
- if tag_num + tag_size_check == 0 {tag_size_check = tag_size+tag_header_size}
if tag_size_check != tag_size+tag_header_size {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size_check error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size_check error
+ continue //tag_size_check error
}
-
+
tag_num += 1
-
- time_stamp := int(F.Btoi32([]byte{buf[0][tag_offset+7], buf[0][tag_offset+4], buf[0][tag_offset+5], buf[0][tag_offset+6]},0))
-
+
+ time_stamp := int(F.Btoi32([]byte{buf[0][tag_offset+7], buf[0][tag_offset+4], buf[0][tag_offset+5], buf[0][tag_offset+6]}, 0))
+
// if tag_num == 1 && last_keyframe_timestamp != 0 {
// diff_time = last_keyframe_timestamp + 3000 - time_stamp
// fmt.Printf("时间戳调整 last:%d now:%d diff:%d\n",last_keyframe_timestamp,time_stamp,diff_time)
-
- if buf[0][tag_offset] == video_tag && buf[0][tag_offset+11] & 0xf0 == 0x10{
- first_t = time_stamp
- } else {
- last_t = time_stamp
- }
+
+ if buf[0][tag_offset] == video_tag && buf[0][tag_offset+11]&0xf0 == 0x10 {
+ first_t = time_stamp
+ } else {
+ last_t = time_stamp
+ }
// }
-
- buf_offset = tag_offset+tag_size_check+previou_tag_size
+
+ buf_offset = tag_offset + tag_size_check + previou_tag_size
+ }
+ for keyframe_interval = 100; keyframe_interval <= last_t-first_t; keyframe_interval += 100 {
}
- for keyframe_interval=100;keyframe_interval<=last_t-first_t;keyframe_interval+=100 {}
}
tag_num = 0
base_keyframe_time = 0
- for i:=0;i<len(buf);i+=1 {
- keyframe_timestamp = last_keyframe_timestamp+keyframe_interval
+ for i := 0; i < len(buf); i += 1 {
+ keyframe_timestamp = last_keyframe_timestamp + keyframe_interval
- for buf_offset:=0;buf_offset+tag_header_size<len(buf[i]); {
+ for buf_offset := 0; buf_offset+tag_header_size < len(buf[i]); {
- tag_offset := buf_offset+bytes.IndexAny(buf[i][buf_offset:], string([]byte{video_tag,audio_tag,script_tag}));
+ tag_offset := buf_offset + bytes.IndexAny(buf[i][buf_offset:], string([]byte{video_tag, audio_tag, script_tag}))
if tag_offset == buf_offset-1 {
err = errors.New(`no found available tag`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//no found available video,audio,script tag
+ return //no found available video,audio,script tag
}
if tag_offset+tag_header_size > len(buf[i]) {
err = errors.New(`reach end when get tag header`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
-
- if buf[i][tag_offset+8] | buf[i][tag_offset+9] | buf[i][tag_offset+10] != 0 {
+
+ if buf[i][tag_offset+8]|buf[i][tag_offset+9]|buf[i][tag_offset+10] != 0 {
buf_offset = tag_offset + 1
// fmt.Printf("streamid error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//streamid error
+ continue //streamid error
}
-
- tag_size := int(F.Btoi32([]byte{0x00,buf[i][tag_offset+1],buf[i][tag_offset+2],buf[i][tag_offset+3]},0))
+
+ tag_size := int(F.Btoi32([]byte{0x00, buf[i][tag_offset+1], buf[i][tag_offset+2], buf[i][tag_offset+3]}, 0))
if tag_offset+tag_header_size+tag_size+previou_tag_size > len(buf[i]) {
err = errors.New(`reach end when get tag body`)
// fmt.Printf("last %x\n",buf[tag_offset:tag_offset+tag_header_size])
- return//buf end
+ return //buf end
}
if tag_size == 0 {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size error
+ continue //tag_size error
+ }
+
+ tag_size_check := int(F.Btoi32(buf[i][tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size], 0))
+ if tag_num+tag_size_check == 0 {
+ tag_size_check = tag_size + tag_header_size
}
-
- tag_size_check := int(F.Btoi32(buf[i][tag_offset+tag_header_size+tag_size:tag_offset+tag_header_size+tag_size+previou_tag_size],0))
- if tag_num + tag_size_check == 0 {tag_size_check = tag_size+tag_header_size}
if tag_size_check != tag_size+tag_header_size {
buf_offset = tag_offset + 1
// fmt.Printf("tag_size_check error %x\n",buf[tag_offset:tag_offset+tag_header_size])
- continue//tag_size_check error
+ continue //tag_size_check error
}
-
+
tag_num += 1
-
- time_stamp := int(F.Btoi32([]byte{buf[i][tag_offset+7], buf[i][tag_offset+4], buf[i][tag_offset+5], buf[i][tag_offset+6]},0))
-
+
+ time_stamp := int(F.Btoi32([]byte{buf[i][tag_offset+7], buf[i][tag_offset+4], buf[i][tag_offset+5], buf[i][tag_offset+6]}, 0))
+
// if tag_num == 1 && last_keyframe_timestamp != 0 {
// diff_time = last_keyframe_timestamp + 3000 - time_stamp
// fmt.Printf("时间戳调整 last:%d now:%d diff:%d\n",last_keyframe_timestamp,time_stamp,diff_time)
- if buf[i][tag_offset] == video_tag && buf[i][tag_offset+11] & 0xf0 == 0x10{
- // if {//key frame
- base_keyframe_time = time_stamp
- time_stamp = keyframe_timestamp
- last_keyframe_timestamp = keyframe_timestamp
- // fmt.Printf("当前关键帧时间戳 %d %d=>%d\n",last_keyframe_timestamp,base_keyframe_time,keyframe_timestamp)
- // }
- } else {
- time_stamp += keyframe_timestamp-base_keyframe_time
- }
+ if buf[i][tag_offset] == video_tag && buf[i][tag_offset+11]&0xf0 == 0x10 {
+ // if {//key frame
+ base_keyframe_time = time_stamp
+ time_stamp = keyframe_timestamp
+ last_keyframe_timestamp = keyframe_timestamp
+ // fmt.Printf("当前关键帧时间戳 %d %d=>%d\n",last_keyframe_timestamp,base_keyframe_time,keyframe_timestamp)
+ // }
+ } else {
+ time_stamp += keyframe_timestamp - base_keyframe_time
+ }
// }
time_stamp_byte := F.Itob32(int32(time_stamp))
-
+
buf[i][tag_offset+7] = time_stamp_byte[0]
buf[i][tag_offset+4] = time_stamp_byte[1]
buf[i][tag_offset+5] = time_stamp_byte[2]
buf[i][tag_offset+6] = time_stamp_byte[3]
-
- buf_offset = tag_offset+tag_size_check+previou_tag_size
+
+ buf_offset = tag_offset + tag_size_check + previou_tag_size
}
}
return
-}
\ No newline at end of file
+}
func (t *Stream) LoadConfig() {
//读取配置
- if path, ok := c.K_v.LoadV("直播流保存位置").(string); ok {
+ if path, ok := c.C.K_v.LoadV("直播流保存位置").(string); ok {
if path, err := filepath.Abs(path); err == nil {
t.config.save_path = path + "/"
}
}
- if v, ok := c.K_v.LoadV(`直播hls流缓冲`).(float64); ok && v > 0 {
+ if v, ok := c.C.K_v.LoadV(`直播hls流缓冲`).(float64); ok && v > 0 {
t.config.bufsize = int(v)
}
- if v, ok := c.K_v.LoadV(`直播hls流均衡`).(bool); ok {
+ if v, ok := c.C.K_v.LoadV(`直播hls流均衡`).(bool); ok {
t.config.banlance_host = v
}
- if v, ok := c.K_v.LoadV(`直播流清晰度`).(int); ok {
+ if v, ok := c.C.K_v.LoadV(`直播流清晰度`).(int); ok {
t.config.want_qn = v
}
- if v, ok := c.K_v.LoadV(`直播流类型`).(string); ok {
+ if v, ok := c.C.K_v.LoadV(`直播流类型`).(string); ok {
t.config.want_type = v
}
}
func (t *Stream) Start() {
- t.log = c.Log.Base(`直播流保存`)
+ t.log = c.C.Log.Base(`直播流保存`)
}
var tts_limit = limit.New(1, 5000, 15000) //频率限制1次/5s,最大等待时间15s
-var tts_log = c.Log.Base_add(`TTS`)
+var tts_log = c.C.Log.Base_add(`TTS`)
var (
tts_ser = "baidu"
func init() {
{ //tts配置
- if v, ok := c.K_v.LoadV(`TTS_总开关`).(bool); ok && !v {
+ if v, ok := c.C.K_v.LoadV(`TTS_总开关`).(bool); ok && !v {
return
}
- if v, ok := c.K_v.LoadV(`TTS_使用程序路径`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_使用程序路径`).(string); ok && v != `` {
tts_prog = v
} else {
tts_log.L(`E: `, `TTS_使用程序路径不是字符串或为空`)
}
- if v, ok := c.K_v.LoadV(`TTS_使用程序参数`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_使用程序参数`).(string); ok && v != `` {
tts_prog_set = v
} else {
tts_log.L(`E: `, `TTS_使用程序参数不是字符串`)
}
- if v, ok := c.K_v.LoadV(`TTS_服务器`).(string); ok && v != "" {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器`).(string); ok && v != "" {
if _, ok := tts_ser_map[v]; ok {
tts_ser = v
} else {
//消息队列接收tts类消息,并传送到TTS朗读
//使用带tag的消息队列在功能间传递消息
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
`tts`: func(data interface{}) bool { //tts
d, _ := data.(Danmu_mq_t)
if s, ok := tts_setting_string[d.uid]; ok && len(d.m) != 0 && s != "" {
Timeout: 3 * 1000,
Retry: 1,
SleepTime: 5000,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
}); err != nil {
return err
}
)
func init() {
- if v, ok := c.K_v.LoadV(`TTS_服务器_youdaoId`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器_youdaoId`).(string); ok && v != `` {
youdaoId = v
}
- if v, ok := c.K_v.LoadV(`TTS_服务器_youdaoKey`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器_youdaoKey`).(string); ok && v != `` {
youdaoappKey = v
}
if tts_ser == `youdao` && (youdaoId == `` || youdaoappKey == ``) {
Timeout: 3 * 1000,
Retry: 1,
SleepTime: 5000,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
}); err != nil {
return err
}
)
func init() {
- if v, ok := c.K_v.LoadV(`TTS_服务器_xfId`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器_xfId`).(string); ok && v != `` {
xfId = v
}
- if v, ok := c.K_v.LoadV(`TTS_服务器_xfKey`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器_xfKey`).(string); ok && v != `` {
xfKey = v
}
- if v, ok := c.K_v.LoadV(`TTS_服务器_xfSecret`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器_xfSecret`).(string); ok && v != `` {
xfSecret = v
}
- if v, ok := c.K_v.LoadV(`TTS_服务器_xfVoice`).(string); ok && v != `` {
+ if v, ok := c.C.K_v.LoadV(`TTS_服务器_xfVoice`).(string); ok && v != `` {
if _, ok := xfVmap[v]; ok || v == `random` {
xfVoice = v
} else {
xfwsClient = ws.New_client(ws.Client{
Url: wsUrl,
- Proxy: c.Proxy,
+ Proxy: c.C.Proxy,
Header: map[string]string{
`User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0`,
`Accept`: `*/*`,
package send
import (
- "strconv"
"encoding/json"
"net/url"
+ "strconv"
c "github.com/qydysky/bili_danmu/CV"
p "github.com/qydysky/part"
- reqf "github.com/qydysky/part/reqf"
limit "github.com/qydysky/part/limit"
+ reqf "github.com/qydysky/part/reqf"
)
//每5s一个令牌,最多等20秒
//弹幕发送
func Danmu_s(msg string, roomid int) {
//等待令牌时阻塞,超时返回true
- if danmu_s_limit.TO() {return}
+ if danmu_s_limit.TO() {
+ return
+ }
- l := c.Log.Base("弹幕发送")
+ l := c.C.Log.Base("弹幕发送")
- if msg == "" || roomid == 0{
- l.L(`E: `,"输入参数不足")
+ if msg == "" || roomid == 0 {
+ l.L(`E: `, "输入参数不足")
return
}
- csrf,_ := c.Cookie.LoadV(`bili_jct`).(string)
- if csrf == `` {l.L(`E: `,"Cookie错误,无bili_jct=");return}
+ csrf, _ := c.C.Cookie.LoadV(`bili_jct`).(string)
+ if csrf == `` {
+ l.L(`E: `, "Cookie错误,无bili_jct=")
+ return
+ }
Cookie := make(map[string]string)
- c.Cookie.Range(func(k,v interface{})(bool){
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
PostStr := `color=16777215&fontsize=25&mode=1&msg=` + msg + `&rnd=` + strconv.Itoa(int(p.Sys().GetSTime())) + `&roomid=` + strconv.Itoa(roomid) + `&bubble=0&csrf_token=` + csrf + `&csrf=` + csrf
- l.L(`I: `,"发送", msg, "至", roomid)
+ l.L(`I: `, "发送", msg, "至", roomid)
r := reqf.New()
err := r.Reqf(reqf.Rval{
- Url:"https://api.live.bilibili.com/msg/send",
- PostStr:url.PathEscape(PostStr),
- Retry:2,
- Timeout:5*1000,
- Proxy:c.Proxy,
- Header:map[string]string{
- `Host`: `api.live.bilibili.com`,
- `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
- `Accept`: `application/json, text/javascript, */*; q=0.01`,
+ Url: "https://api.live.bilibili.com/msg/send",
+ PostStr: url.PathEscape(PostStr),
+ Retry: 2,
+ Timeout: 5 * 1000,
+ Proxy: c.C.Proxy,
+ Header: map[string]string{
+ `Host`: `api.live.bilibili.com`,
+ `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
+ `Accept`: `application/json, text/javascript, */*; q=0.01`,
`Accept-Language`: `zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2`,
`Accept-Encoding`: `gzip, deflate, br`,
- `Content-Type`: `application/x-www-form-urlencoded; charset=UTF-8`,
- `Origin`: `https://live.bilibili.com`,
- `Connection`: `keep-alive`,
- `Pragma`: `no-cache`,
- `Cache-Control`: `no-cache`,
- `Referer`:"https://live.bilibili.com/" + strconv.Itoa(roomid),
- `Cookie`:reqf.Map_2_Cookies_String(Cookie),
+ `Content-Type`: `application/x-www-form-urlencoded; charset=UTF-8`,
+ `Origin`: `https://live.bilibili.com`,
+ `Connection`: `keep-alive`,
+ `Pragma`: `no-cache`,
+ `Cache-Control`: `no-cache`,
+ `Referer`: "https://live.bilibili.com/" + strconv.Itoa(roomid),
+ `Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
})
if err != nil {
- l.L(`E: `,err)
+ l.L(`E: `, err)
return
}
-
- var res struct{
- Code int `json:"code"`
+
+ var res struct {
+ Code int `json:"code"`
Message string `json:"message"`
}
- if e := json.Unmarshal(r.Respon, &res);e != nil{
- l.L(`E: `,e)
+ if e := json.Unmarshal(r.Respon, &res); e != nil {
+ l.L(`E: `, e)
}
if res.Code != 0 {
- l.L(`E: `, `产生错误:`,res.Code, res.Message)
+ l.L(`E: `, `产生错误:`, res.Code, res.Message)
}
-}
\ No newline at end of file
+}
package send
import (
- "time"
- "net/url"
"encoding/json"
+ "net/url"
"strconv"
+ "time"
c "github.com/qydysky/bili_danmu/CV"
- reqf "github.com/qydysky/part/reqf"
limit "github.com/qydysky/part/limit"
+ reqf "github.com/qydysky/part/reqf"
)
//每2s一个令牌,最多等10秒
var gift_limit = limit.New(1, 2000, 10000)
-func Send_gift(gift_id,bag_id,gift_num int) {
- log := c.Log.Base_add(`发送礼物`)
+func Send_gift(gift_id, bag_id, gift_num int) {
+ log := c.C.Log.Base_add(`发送礼物`)
- if gift_limit.TO() {log.L(`W: `,"超时");return}
+ if gift_limit.TO() {
+ log.L(`W: `, "超时")
+ return
+ }
- if c.UpUid == 0 {log.L(`W: `,"还未获取到Up主uid");return}
+ if c.C.UpUid == 0 {
+ log.L(`W: `, "还未获取到Up主uid")
+ return
+ }
- {//发送请求(银瓜子礼物)
- csrf,_ := c.Cookie.LoadV(`bili_jct`).(string)
- if csrf == `` {log.L(`E: `,"Cookie错误,无bili_jct=");return}
+ { //发送请求(银瓜子礼物)
+ csrf, _ := c.C.Cookie.LoadV(`bili_jct`).(string)
+ if csrf == `` {
+ log.L(`E: `, "Cookie错误,无bili_jct=")
+ return
+ }
- var sendStr =
- `uid=`+strconv.Itoa(c.Uid)+`&`+
- `gift_id=`+strconv.Itoa(gift_id)+`&`+
- `ruid=`+strconv.Itoa(c.UpUid)+`&`+
- `send_ruid=0&`+
- `gift_num=`+strconv.Itoa(gift_num)+`&`+
- `bag_id=`+strconv.Itoa(bag_id)+`&`+
- `platform=pc&`+
- `biz_code=live&`+
- `biz_id=`+strconv.Itoa(c.Roomid)+`&`+
- `rnd=`+strconv.Itoa(int(time.Now().Unix()))+`&`+
- `storm_beat_id=0&`+
- `metadata=&`+
- `price=0&`+
- `csrf_token=`+csrf+`&`+
- `csrf=`+csrf+`&`+
- `visit_id=`
+ var sendStr = `uid=` + strconv.Itoa(c.C.Uid) + `&` +
+ `gift_id=` + strconv.Itoa(gift_id) + `&` +
+ `ruid=` + strconv.Itoa(c.C.UpUid) + `&` +
+ `send_ruid=0&` +
+ `gift_num=` + strconv.Itoa(gift_num) + `&` +
+ `bag_id=` + strconv.Itoa(bag_id) + `&` +
+ `platform=pc&` +
+ `biz_code=live&` +
+ `biz_id=` + strconv.Itoa(c.C.Roomid) + `&` +
+ `rnd=` + strconv.Itoa(int(time.Now().Unix())) + `&` +
+ `storm_beat_id=0&` +
+ `metadata=&` +
+ `price=0&` +
+ `csrf_token=` + csrf + `&` +
+ `csrf=` + csrf + `&` +
+ `visit_id=`
Cookie := make(map[string]string)
- c.Cookie.Range(func(k,v interface{})(bool){
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
-
+
req := reqf.New()
- if e:= req.Reqf(reqf.Rval{
- Url:`https://api.live.bilibili.com/gift/v2/live/bag_send`,
- PostStr:url.PathEscape(sendStr),
- Timeout:10*1000,
- Proxy:c.Proxy,
- Header:map[string]string{
- `Host`: `api.vc.bilibili.com`,
- `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
- `Accept`: `application/json, text/javascript, */*; q=0.01`,
+ if e := req.Reqf(reqf.Rval{
+ Url: `https://api.live.bilibili.com/gift/v2/live/bag_send`,
+ PostStr: url.PathEscape(sendStr),
+ Timeout: 10 * 1000,
+ Proxy: c.C.Proxy,
+ Header: map[string]string{
+ `Host`: `api.vc.bilibili.com`,
+ `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
+ `Accept`: `application/json, text/javascript, */*; q=0.01`,
`Accept-Language`: `zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2`,
`Accept-Encoding`: `gzip, deflate, br`,
- `Content-Type`: `application/x-www-form-urlencoded; charset=UTF-8`,
- `Origin`: `https://message.bilibili.com`,
- `Connection`: `keep-alive`,
- `Pragma`: `no-cache`,
- `Cache-Control`: `no-cache`,
- `Referer`:"https://message.bilibili.com",
- `Cookie`:reqf.Map_2_Cookies_String(Cookie),
+ `Content-Type`: `application/x-www-form-urlencoded; charset=UTF-8`,
+ `Origin`: `https://message.bilibili.com`,
+ `Connection`: `keep-alive`,
+ `Pragma`: `no-cache`,
+ `Cache-Control`: `no-cache`,
+ `Referer`: "https://message.bilibili.com",
+ `Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- });e != nil {
- log.L(`E: `,e)
+ }); e != nil {
+ log.L(`E: `, e)
return
}
-
- var res struct{
- Code int `json:"code"`
+
+ var res struct {
+ Code int `json:"code"`
Message string `json:"message"`
- Data struct{
+ Data struct {
Gift_name string `json:"gift_name"`
- Gift_num int `json:"gift_num"`
+ Gift_num int `json:"gift_num"`
} `json:"data"`
}
- if e := json.Unmarshal(req.Respon, &res);e != nil {
- log.L(`E: `,e)
+ if e := json.Unmarshal(req.Respon, &res); e != nil {
+ log.L(`E: `, e)
return
}
if res.Code != 0 {
- log.L(`W: `,res.Message)
+ log.L(`W: `, res.Message)
return
}
- log.L(`I: `,`给`,c.Roomid,`赠送了`,res.Data.Gift_num,`个`,res.Data.Gift_name)
+ log.L(`I: `, `给`, c.C.Roomid, `赠送了`, res.Data.Gift_num, `个`, res.Data.Gift_name)
}
}
package send
-
+
import (
- "net/url"
"errors"
- "strings"
+ "net/url"
"strconv"
+ "strings"
+
c "github.com/qydysky/bili_danmu/CV"
p "github.com/qydysky/part"
- reqf "github.com/qydysky/part/reqf"
limit "github.com/qydysky/part/limit"
+ reqf "github.com/qydysky/part/reqf"
uuid "github.com/gofrs/uuid"
)
return errors.New(`msg == "" || uid == 0`)
}
- log := c.Log.Base_add(`私信`)
+ log := c.C.Log.Base_add(`私信`)
- if c.Uid == 0 {
- log.L(`E: `,`client uid == 0`)
+ if c.C.Uid == 0 {
+ log.L(`E: `, `client uid == 0`)
return errors.New(`client uid == 0`)
- } else if c.Uid == uid {
- log.L(`W: `,`不能发送给自己`)
+ } else if c.C.Uid == uid {
+ log.L(`W: `, `不能发送给自己`)
return errors.New(`不能发送给自己`)
}
- csrf,_ := c.Cookie.LoadV(`bili_jct`).(string)
- if csrf == `` {return errors.New("Cookie错误,无bili_jct=")}
+ csrf, _ := c.C.Cookie.LoadV(`bili_jct`).(string)
+ if csrf == `` {
+ return errors.New("Cookie错误,无bili_jct=")
+ }
var new_uuid string
{
- if tmp_uuid,e := uuid.NewV4();e == nil {
+ if tmp_uuid, e := uuid.NewV4(); e == nil {
new_uuid = tmp_uuid.String()
} else {
- log.L(`E: `,e)
+ log.L(`E: `, e)
return e
}
}
- if pm_limit.TO() {return errors.New("TO")}
+ if pm_limit.TO() {
+ return errors.New("TO")
+ }
+
+ var send_str = `msg[sender_uid]=` + strconv.Itoa(c.C.Uid) + `&msg[receiver_id]=` + strconv.Itoa(uid) + `&msg[receiver_type]=1&msg[msg_type]=1&msg[msg_status]=0&msg[content]={"content":"` + msg + `"}&msg[timestamp]=` + strconv.Itoa(int(p.Sys().GetSTime())) + `&msg[new_face_version]=0&msg[dev_id]=` + strings.ToUpper(new_uuid) + `&from_firework=0&build=0&mobi_app=web&csrf_token=` + csrf + `&csrf=` + csrf
- var send_str = `msg[sender_uid]=`+strconv.Itoa(c.Uid)+`&msg[receiver_id]=`+strconv.Itoa(uid)+`&msg[receiver_type]=1&msg[msg_type]=1&msg[msg_status]=0&msg[content]={"content":"`+msg+`"}&msg[timestamp]=`+strconv.Itoa(int(p.Sys().GetSTime()))+`&msg[new_face_version]=0&msg[dev_id]=`+strings.ToUpper(new_uuid)+`&from_firework=0&build=0&mobi_app=web&csrf_token=`+csrf+`&csrf=`+csrf
-
Cookie := make(map[string]string)
- c.Cookie.Range(func(k,v interface{})(bool){
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
-
+
req := reqf.New()
- if e:= req.Reqf(reqf.Rval{
- Url:`https://api.vc.bilibili.com/web_im/v1/web_im/send_msg`,
- PostStr:url.PathEscape(send_str),
- Timeout:10*1000,
- Proxy:c.Proxy,
- Header:map[string]string{
- `Host`: `api.vc.bilibili.com`,
- `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
- `Accept`: `application/json, text/javascript, */*; q=0.01`,
+ if e := req.Reqf(reqf.Rval{
+ Url: `https://api.vc.bilibili.com/web_im/v1/web_im/send_msg`,
+ PostStr: url.PathEscape(send_str),
+ Timeout: 10 * 1000,
+ Proxy: c.C.Proxy,
+ Header: map[string]string{
+ `Host`: `api.vc.bilibili.com`,
+ `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0`,
+ `Accept`: `application/json, text/javascript, */*; q=0.01`,
`Accept-Language`: `zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2`,
`Accept-Encoding`: `gzip, deflate, br`,
- `Content-Type`: `application/x-www-form-urlencoded; charset=UTF-8`,
- `Origin`: `https://message.bilibili.com`,
- `Connection`: `keep-alive`,
- `Pragma`: `no-cache`,
- `Cache-Control`: `no-cache`,
- `Referer`:"https://message.bilibili.com",
- `Cookie`:reqf.Map_2_Cookies_String(Cookie),
+ `Content-Type`: `application/x-www-form-urlencoded; charset=UTF-8`,
+ `Origin`: `https://message.bilibili.com`,
+ `Connection`: `keep-alive`,
+ `Pragma`: `no-cache`,
+ `Cache-Control`: `no-cache`,
+ `Referer`: "https://message.bilibili.com",
+ `Cookie`: reqf.Map_2_Cookies_String(Cookie),
},
- });e != nil {
- log.L(`E: `,e)
+ }); e != nil {
+ log.L(`E: `, e)
return e
}
- if code := p.Json().GetValFromS(string(req.Respon), "code");code == nil || code.(float64) != 0 {
- log.L(`E: `,string(req.Respon))
+ if code := p.Json().GetValFromS(string(req.Respon), "code"); code == nil || code.(float64) != 0 {
+ log.L(`E: `, string(req.Respon))
return errors.New(string(req.Respon))
}
- log.L(`I: `,`发送私信给`,uid,`:`,msg)
+ log.L(`I: `, `发送私信给`, uid, `:`, msg)
return nil
-}
\ No newline at end of file
+}
package bili_danmu
import (
- "fmt"
"flag"
- "time"
+ "fmt"
"net/url"
- "strconv"
"os"
"os/signal"
-
- reply "github.com/qydysky/bili_danmu/Reply"
- send "github.com/qydysky/bili_danmu/Send"
+ "strconv"
+ "time"
+
c "github.com/qydysky/bili_danmu/CV"
F "github.com/qydysky/bili_danmu/F"
+ reply "github.com/qydysky/bili_danmu/Reply"
+ send "github.com/qydysky/bili_danmu/Send"
p "github.com/qydysky/part"
- ws "github.com/qydysky/part/websocket"
msgq "github.com/qydysky/part/msgq"
reqf "github.com/qydysky/part/reqf"
+ ws "github.com/qydysky/part/websocket"
)
func init() {
- go func(){//日期变化
+ go func() { //日期变化
var old = time.Now().Hour()
for {
- if now := time.Now().Hour();now == 0 && old != now {
- c.Danmu_Main_mq.Push_tag(`new day`,nil)
+ if now := time.Now().Hour(); now == 0 && old != now {
+ c.C.Danmu_Main_mq.Push_tag(`new day`, nil)
old = now
}
- time.Sleep(time.Second*time.Duration(100))
+ time.Sleep(time.Second * time.Duration(100))
}
}()
}
func Demo(roomid ...int) {
- var danmulog = c.Log.Base(`bilidanmu Demo`)
+ var danmulog = c.C.Log.Base(`bilidanmu Demo`)
defer danmulog.Block(1000)
//ctrl+c退出
- interrupt := make(chan os.Signal,2)
- go func(){
+ interrupt := make(chan os.Signal, 2)
+ go func() {
danmulog.L(`T: `, "两次ctrl+c强制退出")
for len(interrupt) < 2 {
- time.Sleep(time.Second*3)
+ time.Sleep(time.Second * 3)
}
danmulog.L(`I: `, "强制退出!").Block(1000)
os.Exit(1)
var (
change_room_chan = make(chan struct{})
- flash_room_chan = make(chan struct{})
+ flash_room_chan = make(chan struct{})
)
//-r 房间初始化
//如果连接中断,则等待
F.KeepConnect()
//获取cookie
- F.Get(`Cookie`)
+ F.Get(&c.C).Get(`Cookie`)
//获取LIVE_BUVID
- F.Get(`LIVE_BUVID`)
+ F.Get(&c.C).Get(`LIVE_BUVID`)
if room == 0 {
- c.Log.Block(1000)//等待所有日志输出完毕
+ c.C.Log.Block(1000) //等待所有日志输出完毕
fmt.Println("输入房间号或` live`获取正在直播的主播")
} else {
fmt.Print("房间号: ", strconv.Itoa(room), "\n")
- if c.Roomid == 0 {
- c.Roomid = room
- go func(){change_room_chan <- struct{}{}}()
+ if c.C.Roomid == 0 {
+ c.C.Roomid = room
+ go func() { change_room_chan <- struct{}{} }()
}
}
//命令行操作 切换房间 发送弹幕
go F.Cmd()
//使用带tag的消息队列在功能间传递消息
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `flash_room`:func(data interface{})(bool){//房间重进
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ `flash_room`: func(data interface{}) bool { //房间重进
select {
- case flash_room_chan <- struct{}{}:;
- default:;
+ case flash_room_chan <- struct{}{}:
+ default:
}
return false
},
- `change_room`:func(data interface{})(bool){//房间改变
- c.Rev = 0.0 //营收
- c.Renqi = 1//人气置1
- c.GuardNum = 0//舰长数
- c.Note = ``//分区排行
- c.Uname = ``//主播id
- c.Title = ``
- c.Wearing_FansMedal = 0
- for len(change_room_chan) != 0 {<-change_room_chan}
+ `change_room`: func(data interface{}) bool { //房间改变
+ c.C.Rev = 0.0 //营收
+ c.C.Renqi = 1 //人气置1
+ c.C.GuardNum = 0 //舰长数
+ c.C.Note = `` //分区排行
+ c.C.Uname = `` //主播id
+ c.C.Title = ``
+ c.C.Wearing_FansMedal = 0
+ for len(change_room_chan) != 0 {
+ <-change_room_chan
+ }
change_room_chan <- struct{}{}
return false
},
- `c.Rev_add`:func(data interface{})(bool){//收入
- c.Rev += data.(float64)
+ `c.Rev_add`: func(data interface{}) bool { //收入
+ c.C.Rev += data.(float64)
return false
},
- `c.Renqi`:func(data interface{})(bool){//人气更新
- if tmp,ok := data.(int);ok{
- c.Renqi = tmp
+ `c.Renqi`: func(data interface{}) bool { //人气更新
+ if tmp, ok := data.(int); ok {
+ c.C.Renqi = tmp
}
return false
},
- `gtk_close`:func(data interface{})(bool){//gtk关闭信号
+ `gtk_close`: func(data interface{}) bool { //gtk关闭信号
interrupt <- os.Interrupt
return false
},
})
//单独,避免队列执行耗时block从而无法接收更多消息
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `pm`:func(data interface{})(bool){//私信
- if tmp,ok := data.(send.Pm_item);ok{
- send.Send_pm(tmp.Uid,tmp.Msg)
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ `pm`: func(data interface{}) bool { //私信
+ if tmp, ok := data.(send.Pm_item); ok {
+ send.Send_pm(tmp.Uid, tmp.Msg)
}
return false
},
//捕获ctrl+c退出
signal.Notify(interrupt, os.Interrupt)
//获取uid
- F.Get(`Uid`)
+ F.Get(&c.C).Get(`Uid`)
//兑换硬币
- F.Get(`Silver_2_coin`)
+ F.Get(&c.C).Get(`Silver_2_coin`)
//每日签到
F.Dosign()
// //客户版本 不再需要
//附加功能 自动发送即将过期礼物
go reply.AutoSend_silver_gift()
- for exit_sign:=true;exit_sign; {
+ for exit_sign := true; exit_sign; {
- danmulog.L(`T: `,"准备")
+ danmulog.L(`T: `, "准备")
//如果连接中断,则等待
F.KeepConnect()
//获取热门榜
- F.Get(`Note`)
+ F.Get(&c.C).Get(`Note`)
- danmulog.L(`I: `,"连接到房间", c.Roomid)
+ danmulog.L(`I: `, "连接到房间", c.C.Roomid)
Cookie := make(map[string]string)
- c.Cookie.Range(func(k,v interface{})(bool){
+ c.C.Cookie.Range(func(k, v interface{}) bool {
Cookie[k.(string)] = v.(string)
return true
})
- F.Get(`Liveing`)
+ F.Get(&c.C).Get(`Liveing`)
//检查与切换粉丝牌,只在cookie存在时启用
- F.Get(`CheckSwitch_FansMedal`)
+ F.Get(&c.C).Get(`CheckSwitch_FansMedal`)
//直播状态
- if c.Liveing {
- danmulog.L(`I: `,"直播中")
+ if c.C.Liveing {
+ danmulog.L(`I: `, "直播中")
} else {
- danmulog.L(`I: `,"未直播")
+ danmulog.L(`I: `, "未直播")
}
//对每个弹幕服务器尝试
- F.Get(`WSURL`)
- for i:=0;i<len(c.WSURL);i+=1 {
- v := c.WSURL[i]
+ F.Get(&c.C).Get(`WSURL`)
+ for i := 0; i < len(c.C.WSURL); i += 1 {
+ v := c.C.WSURL[i]
//ws启动
u, _ := url.Parse(v)
ws_c := ws.New_client(ws.Client{
- Url:v,
- TO:35 * 1000,
- Proxy:c.Proxy,
- Func_abort_close:func(){danmulog.L(`I: `,`服务器连接中断`)},
- Func_normal_close:func(){danmulog.L(`I: `,`服务器连接关闭`)},
+ Url: v,
+ TO: 35 * 1000,
+ Proxy: c.C.Proxy,
+ Func_abort_close: func() { danmulog.L(`I: `, `服务器连接中断`) },
+ Func_normal_close: func() { danmulog.L(`I: `, `服务器连接关闭`) },
Header: map[string]string{
- `Cookie`:reqf.Map_2_Cookies_String(Cookie),
- `Host`: u.Hostname(),
- `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0`,
- `Accept`: `*/*`,
+ `Cookie`: reqf.Map_2_Cookies_String(Cookie),
+ `Host`: u.Hostname(),
+ `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0`,
+ `Accept`: `*/*`,
`Accept-Language`: `zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2`,
- `Origin`: `https://live.bilibili.com`,
- `Pragma`: `no-cache`,
- `Cache-Control`: `no-cache`,
+ `Origin`: `https://live.bilibili.com`,
+ `Pragma`: `no-cache`,
+ `Cache-Control`: `no-cache`,
},
}).Handle()
if ws_c.Isclose() {
- danmulog.L(`E: `,"连接错误", ws_c.Error())
+ danmulog.L(`E: `, "连接错误", ws_c.Error())
continue
}
//SendChan 传入发送[]byte
//RecvChan 接收[]byte
- danmulog.L(`T: `,"连接", v)
- ws_c.SendChan <- F.HelloGen(c.Roomid, c.Token)
- if F.HelloChe(<- ws_c.RecvChan) {
- danmulog.L(`I: `,"已连接到房间", c.Uname, `(`, c.Roomid, `)`)
- reply.Gui_show(`进入直播间: `+c.Uname+` (`+strconv.Itoa(c.Roomid)+`)`, `0room`)
- if c.Title != `` {
- danmulog.L(`I: `,c.Title)
- reply.Gui_show(`房间标题: `+c.Title, `0room`)
+ danmulog.L(`T: `, "连接", v)
+ ws_c.SendChan <- F.HelloGen(c.C.Roomid, c.C.Token)
+ if F.HelloChe(<-ws_c.RecvChan) {
+ danmulog.L(`I: `, "已连接到房间", c.C.Uname, `(`, c.C.Roomid, `)`)
+ reply.Gui_show(`进入直播间: `+c.C.Uname+` (`+strconv.Itoa(c.C.Roomid)+`)`, `0room`)
+ if c.C.Title != `` {
+ danmulog.L(`I: `, c.C.Title)
+ reply.Gui_show(`房间标题: `+c.C.Title, `0room`)
}
//30s获取一次人气
- go func(){
- p.Sys().MTimeoutf(500)//500ms
- danmulog.L(`T: `,"获取人气")
- go func(){
+ go func() {
+ p.Sys().MTimeoutf(500) //500ms
+ danmulog.L(`T: `, "获取人气")
+ go func() {
heartbeatmsg, heartinterval := F.Heartbeat()
for !ws_c.Isclose() {
ws_c.SendChan <- heartbeatmsg
- time.Sleep(time.Millisecond*time.Duration(heartinterval*1000))
+ time.Sleep(time.Millisecond * time.Duration(heartinterval*1000))
}
}()
//订阅消息,以便刷新舰长数
- F.Get(`GuardNum`)
+ F.Get(&c.C).Get(`GuardNum`)
//使用带tag的消息队列在功能间传递消息
- c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `guard_update`:func(data interface{})(bool){//舰长更新
- go F.Get(`GuardNum`)
+ c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+ `guard_update`: func(data interface{}) bool { //舰长更新
+ go F.Get(&c.C).Get(`GuardNum`)
return false
},
- `flash_room`:func(data interface{})(bool){//重进房时退出当前房间
+ `flash_room`: func(data interface{}) bool { //重进房时退出当前房间
return true
},
- `change_room`:func(data interface{})(bool){//换房时退出当前房间
+ `change_room`: func(data interface{}) bool { //换房时退出当前房间
return true
},
- `new day`:func(data interface{})(bool){//日期更换
+ `new day`: func(data interface{}) bool { //日期更换
//每日签到
F.Dosign()
// //获取用户版本 不再需要
// go F.Get(`VERSION`)
//每日兑换硬币
- go F.Silver_2_coin()
+ go F.Get(&c.C).Silver_2_coin()
//小心心
go F.F_x25Kn()
//附加功能 每日发送弹幕
`bili_jct`,
`DedeUserID`,
`LIVE_BUVID`,
- });len(missKey) == 0 {
+ }); len(missKey) == 0 {
//附加功能 弹幕机 无cookie无法发送弹幕
reply.Danmuji_auto()
}
- {//附加功能 进房间发送弹幕 直播流保存 营收
+ { //附加功能 进房间发送弹幕 直播流保存 营收
go reply.Entry_danmu()
go reply.Savestreamf()
go reply.ShowRevf()
var break_sign bool
for !isclose {
select {
- case i := <- ws_c.RecvChan:
+ case i := <-ws_c.RecvChan:
if len(i) == 0 && ws_c.Isclose() {
isclose = true
} else {
go reply.Reply(i)
}
- case <- interrupt:
+ case <-interrupt:
ws_c.Close()
- danmulog.L(`I: `,"停止,等待服务器断开连接")
+ danmulog.L(`I: `, "停止,等待服务器断开连接")
break_sign = true
exit_sign = false
- case <- flash_room_chan:
+ case <-flash_room_chan:
ws_c.Close()
- danmulog.L(`I: `,"停止,等待服务器断开连接")
- F.Get(`WSURL`)
+ danmulog.L(`I: `, "停止,等待服务器断开连接")
+ F.Get(&c.C).Get(`WSURL`)
i = 0
- case <- change_room_chan:
+ case <-change_room_chan:
ws_c.Close()
- danmulog.L(`I: `,"停止,等待服务器断开连接")
+ danmulog.L(`I: `, "停止,等待服务器断开连接")
break_sign = true
}
}
- if break_sign {break}
+ if break_sign {
+ break
+ }
}
- {//附加功能 直播流停止
+ { //附加功能 直播流停止
reply.Savestream_wait()
reply.Save_to_json(-1, []interface{}{`{}]`})
}
}
close(interrupt)
- danmulog.L(`I: `,"结束退出")
+ danmulog.L(`I: `, "结束退出")
}
}
-