]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
粉丝勋章fix
authorqydysky <qydysky@foxmail.com>
Tue, 5 Apr 2022 06:16:46 +0000 (14:16 +0800)
committerqydysky <qydysky@foxmail.com>
Tue, 5 Apr 2022 06:16:46 +0000 (14:16 +0800)
心跳响应包fix

13 files changed:
CV/Var.go
F/api.go
Json/getMyMedals.go [new file with mode: 0644]
Reply/F.go
Reply/Msg.go
Reply/Reply.go
Reply/gtk.go
Reply/tts.go
Reply/ws_msg/WATCHED_CHANGE.go [new file with mode: 0644]
demo/go.mod
demo/go.sum
go.mod
go.sum

index 5c0990ab8b7ac6e458f08877537b359c6bbe90c2..c17aa5ca4cca3b47f1ae45007d1c4cd1c8855f17 100644 (file)
--- a/CV/Var.go
+++ b/CV/Var.go
@@ -1,49 +1,51 @@
 package cv
 
 import (
+       "encoding/json"
+       "io/ioutil"
        "time"
-       syncmap "github.com/qydysky/part/map"
-       mq "github.com/qydysky/part/msgq"
-       s "github.com/qydysky/part/buf"
+
        log "github.com/qydysky/part/log"
+       mq "github.com/qydysky/part/msgq"
+       syncmap "github.com/qydysky/part/sync"
 )
 
-
 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
+       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服务
+       Stream_url string //直播Web服务
 )
 
 //消息队列
 type Danmu_Main_mq_item struct {
        Class string
-       Data interface{}
+       Data  interface{}
 }
+
 //200长度防止push击穿
 var Danmu_Main_mq = mq.New(200)
 
@@ -51,38 +53,43 @@ var Danmu_Main_mq = mq.New(200)
 var K_v syncmap.Map
 
 func init() {
-       buf := s.New()
-       buf.Load("config/config_K_v.json")
-       for k,v := range buf.B {
+       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//全局代理
+       Proxy string //全局代理
 )
+
 func init() {
-       Proxy,_ = K_v.LoadV("http代理地址").(string)
+       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,
+       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{}){
+       if array, ok := K_v.Load(`日志显示`); ok {
+               for _, v := range array.([]interface{}) {
                        logmap[v.(string)] = log.On
                }
        }
@@ -102,21 +109,21 @@ func init() {
 
 var (
        AcceptQn = map[int]string{
-               10000:"原画",
-               800:"4K",
-               401:"蓝光(杜比)",
-               400:"蓝光",
-               250:"超清",
-               150:"高清",
-               80:"流畅",
+               10000: "原画",
+               800:   "4K",
+               401:   "蓝光(杜比)",
+               400:   "蓝光",
+               250:   "超清",
+               150:   "高清",
+               80:    "流畅",
        }
-       Qn = map[int]string{// no change
-               10000:"原画",
-               800:"4K",
-               401:"蓝光(杜比)",
-               400:"蓝光",
-               250:"超清",
-               150:"高清",
-               80:"流畅",
+       Qn = map[int]string{ // no change
+               10000: "原画",
+               800:   "4K",
+               401:   "蓝光(杜比)",
+               400:   "蓝光",
+               250:   "超清",
+               150:   "高清",
+               80:    "流畅",
        }
-)
\ No newline at end of file
+)
index c91a4d2a22da15eb2a549af5477e035aaa015b8e..f2d446b6701d26de9b0c3cd0240b29e9f32149a7 100644 (file)
--- a/F/api.go
+++ b/F/api.go
@@ -1394,28 +1394,11 @@ func Get_cookie() (missKey []string) {
 
 //短信登录
 func Get_cookie_by_msg() {
-       /*
-
-               https://passport.bilibili.com/x/passport-login/web/sms/send
-
-
-       */
-}
-
-//牌子
-type TGet_list_in_room struct {
-       Medal_id       int    `json:"medal_id"`       //牌子id
-       Medal_name     string `json:"medal_name"`     //牌子名
-       Target_id      int    `json:"target_id"`      //牌子up主uid
-       Target_name    string `json:"target_name"`    //牌子up主名
-       Room_id        int    `json:"roomid"`         //牌子直播间
-       Last_wear_time int    `json:"last_wear_time"` //佩戴有效截止时间(佩戴本身不会刷新,发弹幕,送小心心,送金瓜子礼物才会刷新)
-       Today_intimacy int    `json:"today_intimacy"` //今日亲密(0:未发送弹幕 100:已发送弹幕)
-       Is_lighted     int    `json:"is_lighted"`     //牌子是否熄灭(0:熄灭 1:亮)
+       /*https://passport.bilibili.com/x/passport-login/web/sms/send*/
 }
 
 //获取牌子信息
-func Get_list_in_room() (array []TGet_list_in_room) {
+func Get_list_in_room() (array []J.GetMyMedals_Items) {
 
        apilog := apilog.Base_add(`获取牌子`)
        //验证cookie
@@ -1434,11 +1417,11 @@ func Get_list_in_room() (array []TGet_list_in_room) {
        })
 
        { //获取牌子列表
-               var medalList []TGet_list_in_room
+               var medalList []J.GetMyMedals_Items
                for pageNum := 1; true; pageNum += 1 {
                        r := reqf.New()
                        if e := r.Reqf(reqf.Rval{
-                               Url: `https://api.live.bilibili.com/fans_medal/v5/live_fans_medal/iApiMedal?page=` + strconv.Itoa(pageNum) + `&pageSize=10`,
+                               Url: `https://api.live.bilibili.com/xlive/app-ucenter/v1/user/GetMyMedals?page=` + strconv.Itoa(pageNum) + `&pageSize=10`,
                                Header: map[string]string{
                                        `Cookie`: reqf.Map_2_Cookies_String(Cookie),
                                },
@@ -1450,31 +1433,20 @@ func Get_list_in_room() (array []TGet_list_in_room) {
                                return
                        }
 
-                       var res struct {
-                               Code    int    `json:"code"`
-                               Msg     string `json:"msg"`
-                               Message string `json:"message"`
-                               Data    struct {
-                                       FansMedalList []TGet_list_in_room `json:"fansMedalList"`
-                                       Pageinfo      struct {
-                                               Totalpages int `json:"totalpages"`
-                                               CurPage    int `json:"curPage"`
-                                       } `json:"pageinfo"`
-                               } `json:"data"`
-                       }
+                       var res J.GetMyMedals
 
                        if e := json.Unmarshal(r.Respon, &res); e != nil {
                                apilog.L(`E: `, e)
                        }
 
                        if res.Code != 0 {
-                               apilog.L(`E: `, `返回code`, res.Code, res.Msg)
+                               apilog.L(`E: `, `返回code`, res.Code, res.Message)
                                return
                        }
 
-                       medalList = append(medalList, res.Data.FansMedalList...)
+                       medalList = append(medalList, res.Data.Items...)
 
-                       if res.Data.Pageinfo.CurPage == res.Data.Pageinfo.Totalpages {
+                       if res.Data.PageInfo.CurPage == res.Data.PageInfo.TotalPage {
                                break
                        }
 
@@ -1595,10 +1567,10 @@ func CheckSwitch_FansMedal() (missKey []string) {
        {
                medal_list := Get_list_in_room()
                for _, v := range medal_list {
-                       if v.Target_id != c.UpUid {
+                       if v.TargetID != c.UpUid {
                                continue
                        }
-                       medal_id = v.Medal_id
+                       medal_id = v.MedalID
                }
                if medal_id == 0 { //无牌
                        apilog.L(`I: `, `无主播粉丝牌`)
diff --git a/Json/getMyMedals.go b/Json/getMyMedals.go
new file mode 100644 (file)
index 0000000..890a6bc
--- /dev/null
@@ -0,0 +1,38 @@
+package part
+
+type GetMyMedals struct {
+       Code    int              `json:"code"`
+       Message string           `json:"message"`
+       TTL     int              `json:"ttl"`
+       Data    GetMyMedals_Data `json:"data"`
+}
+type GetMyMedals_Items struct {
+       CanDeleted       bool   `json:"can_deleted"`
+       DayLimit         int    `json:"day_limit"`
+       GuardLevel       int    `json:"guard_level"`
+       GuardMedalTitle  string `json:"guard_medal_title"`
+       Intimacy         int    `json:"intimacy"`
+       IsLighted        int    `json:"is_lighted"`
+       Level            int    `json:"level"`
+       MedalName        string `json:"medal_name"`
+       MedalColorBorder int    `json:"medal_color_border"`
+       MedalColorEnd    int    `json:"medal_color_end"`
+       MedalColorStart  int    `json:"medal_color_start"`
+       MedalID          int    `json:"medal_id"`
+       NextIntimacy     int    `json:"next_intimacy"`
+       TodayFeed        int    `json:"today_feed"`
+       Roomid           int    `json:"roomid"`
+       Status           int    `json:"status"`
+       TargetID         int    `json:"target_id"`
+       TargetName       string `json:"target_name"`
+       Uname            string `json:"uname"`
+}
+type GetMyMedals_PageInfo struct {
+       CurPage   int `json:"cur_page"`
+       TotalPage int `json:"total_page"`
+}
+type GetMyMedals_Data struct {
+       Items    []GetMyMedals_Items  `json:"items"`
+       PageInfo GetMyMedals_PageInfo `json:"page_info"`
+       Count    int                  `json:"count"`
+}
index d6698c3d196410b27540b7df1d91b54e49ee63c7..c3da740028037243d44fc07f9dd5c32d32c10070 100644 (file)
@@ -1,24 +1,27 @@
 package reply
 
 import (
+       "bytes"
+       "context"
+       "encoding/base64"
+       "encoding/json"
+       "errors"
        "fmt"
-       "os"
        "io"
        "io/fs"
+       "io/ioutil"
+       "math"
+       "net/http"
+       "net/url"
+       "os"
+       "os/exec"
+       "path"
+       "path/filepath"
        "strconv"
        "strings"
        "sync"
-       "math"
        "time"
-       "os/exec"
-    "path/filepath"
-       "path"
-    "net/http"
-       "context"
-       "net/url"
-       "errors"
-       "bytes"
-       "encoding/base64"
+
        // "runtime"
 
        "golang.org/x/text/encoding/simplifiedchinese"
@@ -30,15 +33,15 @@ import (
        p "github.com/qydysky/part"
        funcCtrl "github.com/qydysky/part/funcCtrl"
        idpool "github.com/qydysky/part/idpool"
+       limit "github.com/qydysky/part/limit"
        msgq "github.com/qydysky/part/msgq"
        reqf "github.com/qydysky/part/reqf"
-       web "github.com/qydysky/part/web"
-       b "github.com/qydysky/part/buf"
        s "github.com/qydysky/part/signal"
-       limit "github.com/qydysky/part/limit"
+       psync "github.com/qydysky/part/sync"
        util "github.com/qydysky/part/util"
+       web "github.com/qydysky/part/web"
 
-       "github.com/christopher-dG/go-obs-websocket"
+       obsws "github.com/christopher-dG/go-obs-websocket"
 )
 
 /*
@@ -54,31 +57,38 @@ func IsOn(s string) bool {
 
 //字符重复度检查
 //a在buf中出现的字符占a的百分数
-func cross(a string,buf []string) (float32) {
+func cross(a string, buf []string) float32 {
        var s float32
        var matched bool
-       for _,v1 := range a {
-               for _,v2 := range buf {
-                       for _,v3 := range v2 {
-                               if v3 == v1 {matched = true;break}
+       for _, v1 := range a {
+               for _, v2 := range buf {
+                       for _, v3 := range v2 {
+                               if v3 == v1 {
+                                       matched = true
+                                       break
+                               }
+                       }
+                       if matched {
+                               break
                        }
-                       if matched {break}
                }
-               if matched {s += 1}
+               if matched {
+                       s += 1
+               }
                matched = false
        }
        return s / float32(len([]rune(a)))
 }
 
 //在a中仅出现一次出现的字符占a的百分数
-func selfcross(a string) (float32) {
+func selfcross(a string) float32 {
        buf := make(map[rune]bool)
-       for _,v := range a {
-               if _,ok := buf[v]; !ok {
+       for _, v := range a {
+               if _, ok := buf[v]; !ok {
                        buf[v] = true
                }
        }
-       return 1 - float32(len(buf)) / float32(len([]rune(a)))
+       return 1 - float32(len(buf))/float32(len([]rune(a)))
 }
 
 //在a的每个字符串中
@@ -87,22 +97,27 @@ func selfcross(a string) (float32) {
 //*单字符串中的重复出现计为1次
 func selfcross2(a []string) (float32, string) {
        buf := make(map[rune]float32)
-       for _,v := range a {
+       for _, v := range a {
                block := make(map[rune]bool)
-               for _,v1 := range v {
-                       if _,ok := block[v1]; ok {continue}
+               for _, v1 := range v {
+                       if _, ok := block[v1]; ok {
+                               continue
+                       }
                        block[v1] = true
                        buf[v1] += 1
                }
        }
        var (
-               max float32
+               max  float32
                maxS string
-               all float32
+               all  float32
        )
-       for k,v := range buf {
+       for k, v := range buf {
                all += v
-               if v > max {max = v;maxS = string(k)}
+               if v > max {
+                       max = v
+                       maxS = string(k)
+               }
        }
        return max / all, maxS
 }
@@ -110,67 +125,71 @@ func selfcross2(a []string) (float32, string) {
 //功能区
 //ShowRev 显示h营收
 var (
-       ShowRev_old float64
+       ShowRev_old   float64
        ShowRev_start bool
 )
 
-func ShowRevf(){
-       if!IsOn("统计营收") {return}
+func ShowRevf() {
+       if !IsOn("统计营收") {
+               return
+       }
        if ShowRev_start {
-               c.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f",c.Rev))
+               c.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f", c.Rev))
                return
        }
        ShowRev_start = true
        for {
-               c.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f",c.Rev))
-               for c.Rev == ShowRev_old {p.Sys().Timeoutf(60)}
+               c.Log.Base(`功能`).L(`I: `, fmt.Sprintf("营收 ¥%.2f", c.Rev))
+               for c.Rev == ShowRev_old {
+                       p.Sys().Timeoutf(60)
+               }
                ShowRev_old = c.Rev
        }
 }
 
 //Ass 弹幕转字幕
 type Ass struct {
-       file string//弹幕ass文件名
-       startT time.Time//开始记录的基准时间
-       header string//ass开头
-       wrap func(io.Writer)(io.Writer)//编码
+       file   string                    //弹幕ass文件名
+       startT time.Time                 //开始记录的基准时间
+       header string                    //ass开头
+       wrap   func(io.Writer) io.Writer //编码
 }
 
 var (
-       Ass_height = 720//字幕高度
-       Ass_width = 1280//字幕宽度
-       Ass_font = 50//字幕字体大小
-       Ass_T = 7//单条字幕显示时间
-       Ass_loc = 7//字幕位置 小键盘对应的位置
+       Ass_height = 720  //字幕高度
+       Ass_width  = 1280 //字幕宽度
+       Ass_font   = 50   //字幕字体大小
+       Ass_T      = 7    //单条字幕显示时间
+       Ass_loc    = 7    //字幕位置 小键盘对应的位置
 )
 
-var ass = Ass {
-header:`[Script Info]
+var ass = Ass{
+       header: `[Script Info]
 Title: Default Ass file
 ScriptType: v4.00+
 WrapStyle: 0
 ScaledBorderAndShadow: yes
-PlayResX: `+strconv.Itoa(Ass_height)+`
-PlayResY: `+strconv.Itoa(Ass_width)+`
+PlayResX: ` + strconv.Itoa(Ass_height) + `
+PlayResY: ` + strconv.Itoa(Ass_width) + `
 
 [V4+ Styles]
 Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
-Style: Default,,`+strconv.Itoa(Ass_font)+`,&H40FFFFFF,&H000017FF,&H80000000,&H40000000,0,0,0,0,100,100,0,0,1,4,4,`+strconv.Itoa(Ass_loc)+`,20,20,50,1
+Style: Default,,` + strconv.Itoa(Ass_font) + `,&H40FFFFFF,&H000017FF,&H80000000,&H40000000,0,0,0,0,100,100,0,0,1,4,4,` + strconv.Itoa(Ass_loc) + `,20,20,50,1
 
 [Events]
 Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
 `,
-wrap:simplifiedchinese.GB18030.NewEncoder().Writer,
+       wrap: simplifiedchinese.GB18030.NewEncoder().Writer,
 }
 
-func init(){
+func init() {
        accept := map[string]bool{
-               `GB18030`:true,
-               `utf-8`:true,
+               `GB18030`: true,
+               `utf-8`:   true,
        }
-       if v,ok := c.K_v.LoadV("Ass编码").(string);ok{
-               if v1,ok := accept[v];ok && v1 {
-                       c.Log.Base(`Ass`).L(`T: `,"编码:", v)
+       if v, ok := c.K_v.LoadV("Ass编码").(string); ok {
+               if v1, ok := accept[v]; ok && v1 {
+                       c.Log.Base(`Ass`).L(`T: `, "编码:", v)
                        if v == `utf-8` {
                                ass.wrap = nil
                        }
@@ -179,34 +198,42 @@ func init(){
 }
 
 //设定字幕文件名,为""时停止输出
-func Ass_f(file string, st time.Time){
+func Ass_f(file string, st time.Time) {
        ass.file = file
-       if file == "" {return}
+       if file == "" {
+               return
+       }
 
-       if rel, err := filepath.Rel(savestream.base_path, ass.file);err == nil {
-               c.Log.Base(`Ass`).L(`I: `,"保存到", rel + ".ass")
+       if rel, err := filepath.Rel(savestream.base_path, ass.file); err == nil {
+               c.Log.Base(`Ass`).L(`I: `, "保存到", rel+".ass")
        } else {
-               c.Log.Base(`Ass`).L(`I: `, "保存到", ass.file + ".ass")
+               c.Log.Base(`Ass`).L(`I: `, "保存到", ass.file+".ass")
                c.Log.Base(`Ass`).L(`W: `, err)
        }
        p.File().FileWR(p.Filel{
-               File:ass.file + ".ass",
-               Loc:0,
-               Context:[]interface{}{ass.header},
-               WrapWriter:ass.wrap,
+               File:       ass.file + ".ass",
+               Loc:        0,
+               Context:    []interface{}{ass.header},
+               WrapWriter: ass.wrap,
        })
        ass.startT = st
 }
 
 //传入要显示的单条字幕
-func Assf(s string){
-       if !IsOn("生成Ass弹幕") {return}
-       if ass.file == "" {return}
+func Assf(s string) {
+       if !IsOn("生成Ass弹幕") {
+               return
+       }
+       if ass.file == "" {
+               return
+       }
 
-       if s == "" {return}
+       if s == "" {
+               return
+       }
 
-       st := time.Since(ass.startT) + time.Duration(p.Rand().MixRandom(0, 2000)) * time.Millisecond
-       et := st + time.Duration(Ass_T) * time.Second
+       st := time.Since(ass.startT) + time.Duration(p.Rand().MixRandom(0, 2000))*time.Millisecond
+       et := st + time.Duration(Ass_T)*time.Second
 
        var b string
        // b += "Comment: " + strconv.Itoa(loc) + " "+ Dtos(showedt) + "\n"
@@ -214,10 +241,10 @@ func Assf(s string){
        b += dtos(st) + `,` + dtos(et)
        b += `,Default,,0,0,0,,{\fad(200,500)\blur3}` + s + "\n"
        p.File().FileWR(p.Filel{
-               File:ass.file + ".ass",
-               Loc:-1,
-               Context:[]interface{}{b},
-               WrapWriter:ass.wrap,
+               File:       ass.file + ".ass",
+               Loc:        -1,
+               Context:    []interface{}{b},
+               WrapWriter: ass.wrap,
        })
 }
 
@@ -235,37 +262,38 @@ func dtos(t time.Duration) string {
 
 //直播流保存
 type Savestream struct {
-       base_path string
-       path string
+       base_path  string
+       path       string
        hls_stream struct {
-               b []byte//发送给客户的m3u8字节
+               b []byte //发送给客户的m3u8字节
                t time.Time
        }
-       front []byte//flv头及首tag or hls的初始化m4s
-       stream *msgq.Msgq//发送给客户的flv流关键帧间隔片 or hls的fmp4片
+       front  []byte     //flv头及首tag or hls的初始化m4s
+       stream *msgq.Msgq //发送给客户的flv流关键帧间隔片 or hls的fmp4片
 
-       m4s_hls int//hls list 中的m4s数量
-       hlsbuffersize int//hls list缓冲m4s数量
-       hls_banlance_host bool//使用均衡hls服务器
+       m4s_hls           int  //hls list 中的m4s数量
+       hlsbuffersize     int  //hls list缓冲m4s数量
+       hls_banlance_host bool //使用均衡hls服务器
 
-       wait *s.Signal
-       cancel *s.Signal
+       wait     *s.Signal
+       cancel   *s.Signal
        skipFunc funcCtrl.SkipFunc
 }
 
 type hls_generate struct {
-       hls_first_fmp4_name string 
-       hls_file_header []byte//发送给客户的m3u8不变头
-       m4s_list []*m4s_link_item//m4s列表 缓冲
+       hls_first_fmp4_name string
+       hls_file_header     []byte           //发送给客户的m3u8不变头
+       m4s_list            []*m4s_link_item //m4s列表 缓冲
 }
 
-type m4s_link_item struct {//使用指针以设置是否已下载
-       Url string// m4s链接
-       Base string//m4s文件名
-       Offset_line int//m3u8中的行下标
-       status int//该m4s下载状态 s_noload:未下载 s_loading正在下载 s_fin下载完成 s_fail下载失败
-       isshow bool
+type m4s_link_item struct { //使用指针以设置是否已下载
+       Url         string // m4s链接
+       Base        string //m4s文件名
+       Offset_line int    //m3u8中的行下标
+       status      int    //该m4s下载状态 s_noload:未下载 s_loading正在下载 s_fin下载完成 s_fail下载失败
+       isshow      bool
 }
+
 //m4s状态
 const (
        s_noload = iota
@@ -274,15 +302,15 @@ const (
        s_fail
 )
 
-var savestream = Savestream {
-       stream:msgq.New(10),//队列最多保留10个关键帧间隔片
-       m4s_hls:8,
+var savestream = Savestream{
+       stream:  msgq.New(10), //队列最多保留10个关键帧间隔片
+       m4s_hls: 8,
 }
 
-func init(){
+func init() {
        //使用带tag的消息队列在功能间传递消息
        c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
-               `savestream`:func(data interface{})(bool){
+               `savestream`: func(data interface{}) bool {
                        if savestream.cancel.Islive() {
                                Savestream_wait()
                        } else {
@@ -293,99 +321,107 @@ func init(){
                },
        })
        //base_path
-       if path,ok := c.K_v.LoadV("直播流保存位置").(string);ok{
-               if path,err := filepath.Abs(path);err == nil{
-                       savestream.base_path = path+"/"
+       if path, ok := 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.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.K_v.LoadV(`直播hls流均衡`).(bool); ok {
                savestream.hls_banlance_host = v
        }
 }
 
 //已go func形式调用,将会获取直播流
-func Savestreamf(){
+func Savestreamf() {
        l := c.Log.Base(`savestream`)
 
        //避免多次开播导致的多次触发
        {
                if savestream.skipFunc.NeedSkip() {
-                       l.L(`T: `,`已存在实例`)
+                       l.L(`T: `, `已存在实例`)
                        return
                }
                defer savestream.skipFunc.UnSet()
        }
 
        want_qn, ok := c.K_v.LoadV("直播流清晰度").(float64)
-       if !ok || want_qn < 0 {return}
+       if !ok || want_qn < 0 {
+               return
+       }
        c.Live_want_qn = int(want_qn)
 
        F.Get(`Live`)
 
-       if savestream.cancel.Islive() {return}
+       if savestream.cancel.Islive() {
+               return
+       }
 
        //random host load balance
        Host_list := []string{}
        if savestream.hls_banlance_host {
-               for _,v := range c.Live { 
-                       url_struct,e := url.Parse(v)
-                       if e != nil {continue}
+               for _, v := range c.Live {
+                       url_struct, e := url.Parse(v)
+                       if e != nil {
+                               continue
+                       }
                        Host_list = append(Host_list, url_struct.Hostname())
                }
        }
 
        var (
-               no_found_link = errors.New("no_found_link")
-               no_Modified = errors.New("no_Modified")
+               no_found_link     = errors.New("no_found_link")
+               no_Modified       = errors.New("no_Modified")
                last_hls_Modified time.Time
-               hls_get_link = func(m3u8_urls []string,last_download *m4s_link_item) (need_download []*m4s_link_item,m3u8_file_addition []byte,expires int,err error) {
+               hls_get_link      = func(m3u8_urls []string, last_download *m4s_link_item) (need_download []*m4s_link_item, m3u8_file_addition []byte, expires int, err error) {
                        var (
-                               r *reqf.Req
+                               r        *reqf.Req
                                m3u8_url *url.URL
                        )
-                       for index:=0;index<len(m3u8_urls);index+=1 {
+                       for index := 0; index < len(m3u8_urls); index += 1 {
                                r = reqf.New()
-                               if tmp,e := url.Parse(m3u8_urls[index]);e != nil {
+                               if tmp, e := url.Parse(m3u8_urls[index]); e != nil {
                                        err = e
                                        return
                                } else {
                                        m3u8_url = tmp
                                }
-                               
+
                                rval := reqf.Rval{
-                                       Url:m3u8_url.String(),
-                                       ConnectTimeout:2000,
-                                       ReadTimeout:1000,
-                                       Timeout:2000,
-                                       Proxy: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`,
-                                               `Accept`: `*/*`,
+                                       Url:            m3u8_url.String(),
+                                       ConnectTimeout: 2000,
+                                       ReadTimeout:    1000,
+                                       Timeout:        2000,
+                                       Proxy:          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`,
+                                               `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`,
                                                `Accept-Encoding`: `gzip, deflate, br`,
-                                               `Origin`: `https://live.bilibili.com`,
-                                               `Connection`: `keep-alive`,
-                                               `Pragma`: `no-cache`,
-                                               `Cache-Control`: `no-cache`,
-                                               `Referer`:"https://live.bilibili.com/",
+                                               `Origin`:          `https://live.bilibili.com`,
+                                               `Connection`:      `keep-alive`,
+                                               `Pragma`:          `no-cache`,
+                                               `Cache-Control`:   `no-cache`,
+                                               `Referer`:         "https://live.bilibili.com/",
                                        },
                                }
                                if !last_hls_Modified.IsZero() {
                                        rval.Header[`If-Modified-Since`] = last_hls_Modified.Add(time.Second).Format("Mon, 02 Jan 2006 15:04:05 CST")
                                }
-                               if e := r.Reqf(rval);e != nil {
-                                       if index+1<len(m3u8_urls) {continue}
+                               if e := r.Reqf(rval); e != nil {
+                                       if index+1 < len(m3u8_urls) {
+                                               continue
+                                       }
                                        err = e
                                        return
                                }
                                break
                        }
 
-                       if usedt := r.UsedTime.Seconds();usedt > 3000 {
+                       if usedt := r.UsedTime.Seconds(); usedt > 3000 {
                                l.L(`I: `, `hls列表下载慢`, usedt, `ms`)
                        }
                        if r.Response.StatusCode == http.StatusNotModified {
@@ -394,8 +430,8 @@ func Savestreamf(){
                                return
                        }
                        //last_hls_Modified
-                       if t,ok := r.Response.Header[`Last-Modified`];ok && len(t) > 0 {
-                               if lm,e := time.Parse("Mon, 02 Jan 2006 15:04:05 CST", t[0]);e == nil {
+                       if t, ok := r.Response.Header[`Last-Modified`]; ok && len(t) > 0 {
+                               if lm, e := time.Parse("Mon, 02 Jan 2006 15:04:05 CST", t[0]); e == nil {
                                        last_hls_Modified = lm
                                } else {
                                        l.L(`T: `, e)
@@ -404,12 +440,12 @@ func Savestreamf(){
 
                        query := m3u8_url.Query()
                        trid := query.Get("trid")
-                       expires,_ = strconv.Atoi(query.Get("expires"))
+                       expires, _ = strconv.Atoi(query.Get("expires"))
                        buf := r.Respon
 
                        //base-64
                        if len(buf) != 0 && !bytes.Contains(buf, []byte("#")) {
-                               buf,err = base64.StdEncoding.DecodeString(string(buf))
+                               buf, err = base64.StdEncoding.DecodeString(string(buf))
                                if err != nil {
                                        l.L(`W: `, err, string(buf))
                                        return
@@ -418,29 +454,31 @@ func Savestreamf(){
 
                        var m4s_links []*m4s_link_item
                        lines := bytes.Split(buf, []byte("\n"))
-                       for i:=0;i<len(lines);i+=1 {
+                       for i := 0; i < len(lines); i += 1 {
                                line := lines[i]
                                m4s_link := ""
 
                                if bytes.Contains(line, []byte("EXT-X-MAP")) {
-                                       o := bytes.Index(line,[]byte(`EXT-X-MAP:URI="`)) + 15
-                                       e := bytes.Index(line[o:],[]byte(`"`)) + o
+                                       o := bytes.Index(line, []byte(`EXT-X-MAP:URI="`)) + 15
+                                       e := bytes.Index(line[o:], []byte(`"`)) + o
                                        m4s_link = string(line[o:e])
                                } else if bytes.Contains(line, []byte(".m4s")) {
                                        m4s_link = string(line)
                                }
 
-                               if m4s_link == "" {continue}
+                               if m4s_link == "" {
+                                       continue
+                               }
 
-                               u, e := url.Parse("./"+m4s_link+"?trid="+trid)
+                               u, e := url.Parse("./" + m4s_link + "?trid=" + trid)
                                if e != nil {
                                        err = e
                                        return
                                }
                                m4s_links = append(m4s_links, &m4s_link_item{
-                                       Url:m3u8_url.ResolveReference(u).String(),
-                                       Base:m4s_link,
-                                       Offset_line:i,
+                                       Url:         m3u8_url.ResolveReference(u).String(),
+                                       Base:        m4s_link,
+                                       Offset_line: i,
                                })
                        }
                        if len(m4s_links) == 0 {
@@ -455,12 +493,12 @@ func Savestreamf(){
                        }
 
                        var found bool
-                       for i:=0;i<len(m4s_links);i+=1 {
+                       for i := 0; i < len(m4s_links); i += 1 {
                                if found {
-                                       offset := m4s_links[i].Offset_line-1
-                                       for i:=offset;i<len(lines);i+=1 {
+                                       offset := m4s_links[i].Offset_line - 1
+                                       for i := offset; i < len(lines); i += 1 {
                                                m3u8_file_addition = append(m3u8_file_addition, lines[i]...)
-                                               m3u8_file_addition = append(m3u8_file_addition,[]byte("\n")...)
+                                               m3u8_file_addition = append(m3u8_file_addition, []byte("\n")...)
                                        }
                                        m3u8_file_addition = m3u8_file_addition[:len(m3u8_file_addition)-1]
 
@@ -470,10 +508,10 @@ func Savestreamf(){
                                found = (*last_download).Base == m4s_links[i].Base
                        }
                        if !found {
-                               offset := m4s_links[1].Offset_line-1
-                               for i:=offset;i<len(lines);i+=1 {
+                               offset := m4s_links[1].Offset_line - 1
+                               for i := offset; i < len(lines); i += 1 {
                                        m3u8_file_addition = append(m3u8_file_addition, lines[i]...)
-                                       m3u8_file_addition = append(m3u8_file_addition,[]byte("\n")...)
+                                       m3u8_file_addition = append(m3u8_file_addition, []byte("\n")...)
                                }
                                m3u8_file_addition = m3u8_file_addition[:len(m3u8_file_addition)-1]
 
@@ -482,16 +520,16 @@ func Savestreamf(){
 
                        return
                }
-               flv_get_link = func(link string) (need_download string,expires int,err error) {
+               flv_get_link = func(link string) (need_download string, expires int, err error) {
                        need_download = link
 
-                       url_struct,e := url.Parse(link)
+                       url_struct, e := url.Parse(link)
                        if e != nil {
                                err = e
                                return
                        }
                        query := url_struct.Query()
-                       expires,_ = strconv.Atoi(query.Get("expires"))
+                       expires, _ = strconv.Atoi(query.Get("expires"))
 
                        return
                }
@@ -499,10 +537,14 @@ func Savestreamf(){
 
        for {
                F.Get(`Liveing`)
-               if !c.Liveing {break}
+               if !c.Liveing {
+                       break
+               }
 
                F.Get(`Live`)
-               if len(c.Live)==0 {break}
+               if len(c.Live) == 0 {
+                       break
+               }
 
                savestream.path = savestream.base_path
 
@@ -512,64 +554,66 @@ func Savestreamf(){
                savestream.cancel = s.Init()
 
                CookieM := make(map[string]string)
-               c.Cookie.Range(func(k,v interface{})(bool){
+               c.Cookie.Range(func(k, v interface{}) bool {
                        CookieM[k.(string)] = v.(string)
                        return true
                })
 
-               {//重试
+               { //重试
                        r := reqf.New()
-                       go func(){
+                       go func() {
                                savestream.cancel.Wait()
                                r.Close()
                        }()
-                       l.L(`I: `,"尝试连接live")
+                       l.L(`I: `, "尝试连接live")
                        if e := r.Reqf(reqf.Rval{
-                               Url:c.Live[0],
-                               Retry:10,
-                               SleepTime:1000,
-                               Proxy:c.Proxy,
-                               Header:map[string]string{
-                                       `Cookie`:reqf.Map_2_Cookies_String(CookieM),
+                               Url:       c.Live[0],
+                               Retry:     10,
+                               SleepTime: 1000,
+                               Proxy:     c.Proxy,
+                               Header: map[string]string{
+                                       `Cookie`: reqf.Map_2_Cookies_String(CookieM),
                                },
-                               Timeout:5*1000,
-                               JustResponseCode:true,
-                       }); e != nil{l.L(`W: `,e)}
+                               Timeout:          5 * 1000,
+                               JustResponseCode: true,
+                       }); e != nil {
+                               l.L(`W: `, e)
+                       }
 
                        if r.Response == nil {
-                               l.L(`W: `,`live响应错误`)
+                               l.L(`W: `, `live响应错误`)
                                savestream.wait.Done()
                                savestream.cancel.Done()
-                               time.Sleep(time.Second*5)
+                               time.Sleep(time.Second * 5)
                                continue
                        } else if r.Response.StatusCode != 200 {
-                               l.L(`W: `,`live响应错误`,r.Response.Status,string(r.Respon))
+                               l.L(`W: `, `live响应错误`, r.Response.Status, string(r.Respon))
                                savestream.wait.Done()
                                savestream.cancel.Done()
-                               time.Sleep(time.Second*5)
+                               time.Sleep(time.Second * 5)
                                continue
                        }
                }
 
-               if strings.Contains(c.Live[0],"flv") {
-                       if rel, err := filepath.Rel(savestream.base_path, savestream.path);err == nil {
-                               l.L(`I: `,"保存到", rel + ".flv")
+               if strings.Contains(c.Live[0], "flv") {
+                       if rel, err := filepath.Rel(savestream.base_path, savestream.path); err == nil {
+                               l.L(`I: `, "保存到", rel+".flv")
                        } else {
-                               l.L(`I: `,"保存到", savestream.path + ".flv")
+                               l.L(`I: `, "保存到", savestream.path+".flv")
                                l.L(`W: `, err)
                        }
                        Ass_f(savestream.path, time.Now())
 
                        // no expect qn
                        exit_chan := s.Init()
-                       go func(){
+                       go func() {
                                savestream.cancel.Wait()
                                exit_chan.Done()
                        }()
 
                        type link_stream struct {
-                               id *idpool.Id
-                               front []byte
+                               id       *idpool.Id
+                               front    []byte
                                keyframe [][]byte
                                // sync_buf []byte
                                close func()
@@ -577,38 +621,40 @@ func Savestreamf(){
 
                        //chans
                        var (
-                               reqs = msgq.New(10)
+                               reqs    = msgq.New(10)
                                id_pool = idpool.New()
                        )
 
                        //文件
                        out, err := os.Create(savestream.path + ".flv" + ".dtmp")
                        if err != nil {
-                               l.L(`E: `,err)
+                               l.L(`E: `, err)
                                return
                        }
 
                        //数据整合
                        {
                                type id_close struct {
-                                       id uintptr
+                                       id    uintptr
                                        close func()
                                }
 
                                var (
-                                       reqs_used_id []id_close
+                                       reqs_used_id   []id_close
                                        reqs_remove_id []id_close
 
                                        reqs_keyframe [][][]byte
 
-                                       reqs_func_block funcCtrl.BlockFunc
+                                       reqs_func_block         funcCtrl.BlockFunc
                                        last_keyframe_timestamp int
                                )
-                               reqs.Pull_tag(map[string]func(interface{})(bool){
-                                       `req`:func(data interface{})(bool){
-                                               req,ok := data.(link_stream)
+                               reqs.Pull_tag(map[string]func(interface{}) bool{
+                                       `req`: func(data interface{}) bool {
+                                               req, ok := data.(link_stream)
 
-                                               if !ok {return false}
+                                               if !ok {
+                                                       return false
+                                               }
 
                                                if len(req.keyframe) == 0 {
                                                        // fmt.Println(`没有keyframe,退出`)
@@ -617,7 +663,7 @@ func Savestreamf(){
                                                }
                                                // fmt.Println(`处理req_id`,req.id.Id,`keyframe_len`,len(req.keyframe))
 
-                                               if offset,_ := out.Seek(0,1);offset == 0 {
+                                               if offset, _ := out.Seek(0, 1); offset == 0 {
                                                        // fmt.Println(`添加头`,len(req.front))
                                                        //stream
                                                        savestream.front = req.front
@@ -627,7 +673,7 @@ func Savestreamf(){
                                                reqs_func_block.Block()
                                                defer reqs_func_block.UnBlock()
 
-                                               for i:=0;i<len(reqs_remove_id);i+=1 {
+                                               for i := 0; i < len(reqs_remove_id); i += 1 {
                                                        if reqs_remove_id[i].id == req.id.Id {
                                                                req.close()
                                                                return false
@@ -637,7 +683,7 @@ func Savestreamf(){
                                                var reqs_keyframe_index int = len(reqs_used_id)
                                                {
                                                        var isnew bool = true
-                                                       for i:=0;i<len(reqs_used_id);i+=1 {
+                                                       for i := 0; i < len(reqs_used_id); i += 1 {
                                                                if reqs_used_id[i].id == req.id.Id {
                                                                        reqs_keyframe_index = i
                                                                        isnew = false
@@ -647,19 +693,19 @@ func Savestreamf(){
                                                        if isnew {
                                                                // fmt.Println(`新req`,req.id.Id,reqs_keyframe_index)
                                                                reqs_used_id = append(reqs_used_id, id_close{
-                                                                       id:req.id.Id,
-                                                                       close:req.close,
+                                                                       id:    req.id.Id,
+                                                                       close: req.close,
                                                                })
                                                        }
                                                }
 
                                                if len(reqs_used_id) == 1 {
                                                        // l.L(`T: `,"单req写入",len(req.keyframe))
-                                                       last_keyframe_timestamp,_ = Keyframe_timebase(req.keyframe,last_keyframe_timestamp)
+                                                       last_keyframe_timestamp, _ = Keyframe_timebase(req.keyframe, last_keyframe_timestamp)
 
-                                                       for i:=0;i<len(req.keyframe);i+=1 {
+                                                       for i := 0; i < len(req.keyframe); i += 1 {
                                                                //stream
-                                                               savestream.stream.Push_tag("stream",req.keyframe[i])
+                                                               savestream.stream.Push_tag("stream", req.keyframe[i])
                                                                out.Write(req.keyframe[i])
                                                        }
                                                        return false
@@ -672,45 +718,47 @@ func Savestreamf(){
 
                                                // fmt.Println(`merge,添加reqs_keyframe数据`,reqs_keyframe_index,len(reqs_keyframe[reqs_keyframe_index]))
 
-                                               for _,v := range reqs_keyframe {
+                                               for _, v := range reqs_keyframe {
                                                        if len(v) == 0 {
                                                                // fmt.Println(`merge,req无数据`,k)
                                                                return false
                                                        }
                                                }
 
-                                               if success_last_keyframe_timestamp,b,merged := Merge_stream(reqs_keyframe,last_keyframe_timestamp);merged == 0 {
+                                               if success_last_keyframe_timestamp, b, merged := Merge_stream(reqs_keyframe, last_keyframe_timestamp); merged == 0 {
                                                        // fmt.Println(`merge失败,reqs_keyframe[1]`,reqs_keyframe[1][0][:11],reqs_keyframe[1][len(reqs_keyframe[1])-1][:11])
                                                        size := 0
-                                                       for i:=1;i<len(reqs_keyframe);i+=1 {size += len(reqs_keyframe[i])}
+                                                       for i := 1; i < len(reqs_keyframe); i += 1 {
+                                                               size += len(reqs_keyframe[i])
+                                                       }
 
                                                        if reqs_keyframe_index == 0 {
                                                                // l.L(`T: `,"flv拼合失败,reqs_keyframe[0]写入")
                                                                // fmt.Println(`merge失败,reqs_keyframe[0]写入`,len(req.keyframe))
 
-                                                               last_keyframe_timestamp,_ = Keyframe_timebase(req.keyframe,last_keyframe_timestamp)
+                                                               last_keyframe_timestamp, _ = Keyframe_timebase(req.keyframe, last_keyframe_timestamp)
 
-                                                               for i:=0;i<len(req.keyframe);i+=1 {
+                                                               for i := 0; i < len(req.keyframe); i += 1 {
                                                                        //stream
-                                                                       savestream.stream.Push_tag("stream",req.keyframe[i])
+                                                                       savestream.stream.Push_tag("stream", req.keyframe[i])
                                                                        out.Write(req.keyframe[i])
                                                                }
                                                                // reqs_keyframe[0] = [][]byte{reqs_keyframe[0][len(reqs_keyframe[0])-1]}
                                                        } else if size > 4 {
                                                                if reqs_keyframe_index == len(reqs_used_id)-1 {
-                                                                       l.L(`T: `,"flv强行拼合")
+                                                                       l.L(`T: `, "flv强行拼合")
 
-                                                                       for i:=0;i<reqs_keyframe_index;i+=1 {
+                                                                       for i := 0; i < reqs_keyframe_index; i += 1 {
                                                                                reqs_remove_id = append(reqs_remove_id, reqs_used_id[i])
                                                                                reqs_used_id[i].close()
                                                                        }
                                                                        reqs_used_id = reqs_used_id[reqs_keyframe_index:]
 
-                                                                       last_keyframe_timestamp,_ = Keyframe_timebase(req.keyframe,last_keyframe_timestamp)
+                                                                       last_keyframe_timestamp, _ = Keyframe_timebase(req.keyframe, last_keyframe_timestamp)
 
-                                                                       for i:=0;i<len(req.keyframe);i+=1 {
+                                                                       for i := 0; i < len(req.keyframe); i += 1 {
                                                                                //stream
-                                                                               savestream.stream.Push_tag("stream",req.keyframe[i])
+                                                                               savestream.stream.Push_tag("stream", req.keyframe[i])
                                                                                out.Write(req.keyframe[i])
                                                                        }
 
@@ -722,11 +770,11 @@ func Savestreamf(){
                                                        }
                                                } else {
                                                        // fmt.Println(`merge成功`,len(b))
-                                                       l.L(`T: `,"flv拼合成功")
+                                                       l.L(`T: `, "flv拼合成功")
 
                                                        last_keyframe_timestamp = success_last_keyframe_timestamp
 
-                                                       for i:=0;i<merged;i+=1 {
+                                                       for i := 0; i < merged; i += 1 {
                                                                reqs_remove_id = append(reqs_remove_id, reqs_used_id[i])
                                                                reqs_used_id[i].close()
                                                        }
@@ -735,16 +783,16 @@ func Savestreamf(){
                                                        reqs_used_id = reqs_used_id[merged:]
 
                                                        //stream
-                                                       savestream.stream.Push_tag("stream",b)
+                                                       savestream.stream.Push_tag("stream", b)
                                                        out.Write(b)
                                                }
 
                                                return false
                                        },
                                        // 11区        1
-                                       `close`:func(data interface{})(bool){
+                                       `close`: func(data interface{}) bool {
                                                // defer l.L(`I: `,"处理退出")
-                                               for i:=0;i<len(reqs_used_id);i+=1 {
+                                               for i := 0; i < len(reqs_used_id); i += 1 {
                                                        reqs_used_id[i].close()
                                                }
                                                reqs_used_id = []id_close{}
@@ -762,74 +810,76 @@ func Savestreamf(){
 
                                live_index := 0
                                if len(c.Live) > 0 {
-                                       live_index = int(p.Rand().MixRandom(0,int64(len(c.Live)-1)))
+                                       live_index = int(p.Rand().MixRandom(0, int64(len(c.Live)-1)))
                                }
-                               link,exp,e := flv_get_link(c.Live[live_index])
+                               link, exp, e := flv_get_link(c.Live[live_index])
                                if e != nil {
-                                       l.L(`W: `,`流链接获取错误`,e)
+                                       l.L(`W: `, `流链接获取错误`, e)
                                        break
                                }
 
                                // 新建chan
                                var (
-                                       bc = make(chan []byte,1<<17)
-                                       req = reqf.New()
+                                       bc       = make(chan []byte, 1<<17)
+                                       req      = reqf.New()
                                        req_exit = s.Init()
                                )
 
-                               l.L(`I: `,`新建请求`,req.Id())
+                               l.L(`I: `, `新建请求`, req.Id())
 
                                //新建请求
-                               go func(r *reqf.Req,rval reqf.Rval){
-                                       go func(){
+                               go func(r *reqf.Req, rval reqf.Rval) {
+                                       go func() {
                                                select {
-                                               case <-exit_chan.WaitC():;
-                                               case <-req_exit.WaitC():;
+                                               case <-exit_chan.WaitC():
+                                               case <-req_exit.WaitC():
                                                }
                                                r.Close()
                                        }()
                                        defer req_exit.Done()
                                        e := r.Reqf(rval)
                                        if r.Response == nil {
-                                               l.L(`W: `,`请求退出`,r.Id(),e)
+                                               l.L(`W: `, `请求退出`, r.Id(), e)
                                        } else if r.Response.StatusCode != 200 {
-                                               l.L(`W: `,`请求退出`,r.Id(),e,r.Response.Status,string(r.Respon))
+                                               l.L(`W: `, `请求退出`, r.Id(), e, r.Response.Status, string(r.Respon))
                                        } else {
-                                               l.L(`W: `,`请求退出`,r.Id())
+                                               l.L(`W: `, `请求退出`, r.Id())
                                        }
-                               }(req,reqf.Rval{
-                                       Url:link,
-                                       Proxy:c.Proxy,
-                                       Header:map[string]string{
-                                               `Cookie`:reqf.Map_2_Cookies_String(CookieM),
+                               }(req, reqf.Rval{
+                                       Url:   link,
+                                       Proxy: c.Proxy,
+                                       Header: map[string]string{
+                                               `Cookie`: reqf.Map_2_Cookies_String(CookieM),
                                        },
                                        //SaveToPath:savestream.path + ".flv",
-                                       SaveToChan:bc,
-                                       Timeout:int(int64(exp) - p.Sys().GetSTime())*1000,
-                                       ReadTimeout:5*1000,
-                                       ConnectTimeout:10*1000,
+                                       SaveToChan:     bc,
+                                       Timeout:        int(int64(exp)-p.Sys().GetSTime()) * 1000,
+                                       ReadTimeout:    5 * 1000,
+                                       ConnectTimeout: 10 * 1000,
                                })
 
                                //返回通道
                                var item = link_stream{
-                                               close:req.Close,
-                                               id:id_pool.Get(),
-                                       }
-                               l.L(`I: `,`新建连接`,item.id.Id)
+                                       close: req.Close,
+                                       id:    id_pool.Get(),
+                               }
+                               l.L(`I: `, `新建连接`, item.id.Id)
 
                                //解析
-                               go func(bc chan[]byte,item *link_stream,exit_chan *s.Signal){
+                               go func(bc chan []byte, item *link_stream, exit_chan *s.Signal) {
                                        var (
-                                               buf []byte
+                                               buf           []byte
                                                skip_buf_size int
                                        )
                                        defer req_exit.Done()
-                                       defer l.L(`W: `,`连接退出`,item.id.Id)
+                                       defer l.L(`W: `, `连接退出`, item.id.Id)
                                        for exit_chan.Islive() && req_exit.Islive() {
                                                select {
-                                               case <-exit_chan.WaitC():return;
-                                               case <-req_exit.WaitC():return;
-                                               case b :=<- bc:
+                                               case <-exit_chan.WaitC():
+                                                       return
+                                               case <-req_exit.WaitC():
+                                                       return
+                                               case b := <-bc:
                                                        if len(b) == 0 {
                                                                // fmt.Println(`req退出`,item.id.Id)
                                                                id_pool.Put(item.id)
@@ -839,19 +889,21 @@ func Savestreamf(){
 
                                                        buf = append(buf, b...)
 
-                                                       if len(buf) < skip_buf_size {break}
+                                                       if len(buf) < skip_buf_size {
+                                                               break
+                                                       }
 
-                                                       front,list,_ := Seach_stream_tag(buf)
+                                                       front, list, _ := Seach_stream_tag(buf)
 
                                                        if len(front) != 0 && len(item.front) == 0 {
                                                                // fmt.Println(item.id.Id,`获取到header`,len(front))
-                                                               item.front = make([]byte,len(front))
+                                                               item.front = make([]byte, len(front))
                                                                copy(item.front, front)
                                                        }
 
                                                        if len(list) == 0 || len(item.front) == 0 {
                                                                // fmt.Println(`再次查询bufsize`,skip_buf_size)
-                                                               skip_buf_size = 2*len(buf)
+                                                               skip_buf_size = 2 * len(buf)
                                                                break
                                                        }
 
@@ -859,31 +911,31 @@ func Savestreamf(){
 
                                                        {
                                                                last_keyframe := list[len(list)-1]
-                                                               cut_offset := bytes.LastIndex(buf, last_keyframe)+len(last_keyframe)
+                                                               cut_offset := bytes.LastIndex(buf, last_keyframe) + len(last_keyframe)
                                                                // fmt.Printf("buf截断 当前%d=>%d 下一header %b\n",len(buf),len(buf)-cut_offset,buf[:11])
                                                                buf = buf[cut_offset:]
                                                        }
 
-                                                       skip_buf_size = len(buf)+len(list[0])
-                                                       reqs.Push_tag(`req`,*item)
+                                                       skip_buf_size = len(buf) + len(list[0])
+                                                       reqs.Push_tag(`req`, *item)
                                                }
                                        }
-                               }(bc,&item,exit_chan)
+                               }(bc, &item, exit_chan)
 
-                               expires := int64(exp) - p.Sys().GetSTime()-120
+                               expires := int64(exp) - p.Sys().GetSTime() - 120
                                // no expect qn
                                if c.Live_want_qn < c.Live_qn {
-                                       expires = time.Now().Add(time.Minute*2).Unix()
+                                       expires = time.Now().Add(time.Minute * 2).Unix()
                                }
 
                                //等待过期/退出
                                {
                                        var exit_sign bool
                                        select {
-                                       case <- req_exit.Chan:;//本次连接错误,退出重试
-                                       case <- exit_chan.Chan://要求退出
-                                               exit_sign = true//
-                                       case <- time.After(time.Second*time.Duration(int(expires))):;
+                                       case <-req_exit.Chan: //本次连接错误,退出重试
+                                       case <-exit_chan.Chan: //要求退出
+                                               exit_sign = true //
+                                       case <-time.After(time.Second * time.Duration(int(expires))):
                                        }
                                        if exit_sign {
                                                //退出
@@ -892,94 +944,106 @@ func Savestreamf(){
                                        }
                                }
 
-                               l.L(`I: `,"flv关闭,开始新连接")
+                               l.L(`I: `, "flv关闭,开始新连接")
 
                                //即将过期,刷新c.Live
                                F.Get(`Liveing`)
-                               if !c.Liveing {break}
+                               if !c.Liveing {
+                                       break
+                               }
                                F.Get(`Live`)
-                               if len(c.Live)==0 {break}
+                               if len(c.Live) == 0 {
+                                       break
+                               }
                        }
 
                        exit_chan.Done()
-                       reqs.Push_tag(`close`,nil)
+                       reqs.Push_tag(`close`, nil)
                        out.Close()
 
                        p.FileMove(savestream.path+".flv.dtmp", savestream.path+".flv")
                } else {
                        savestream.path += "/"
-                       if rel, err := filepath.Rel(savestream.base_path, savestream.path);err == nil {
-                               l.L(`I: `,"保存到", rel+`/0.m3u8`)
+                       if rel, err := filepath.Rel(savestream.base_path, savestream.path); err == nil {
+                               l.L(`I: `, "保存到", rel+`/0.m3u8`)
                        } else {
-                               l.L(`I: `,"保存到", savestream.path)
+                               l.L(`I: `, "保存到", savestream.path)
                                l.L(`W: `, err)
                        }
                        Ass_f(savestream.path+"0", time.Now())
 
                        var (
-                               hls_msg = msgq.New(20)
-                               hls_gen hls_generate
+                               hls_msg       = msgq.New(20)
+                               hls_gen       hls_generate
                                DISCONTINUITY int
-                               SEQUENCE int
+                               SEQUENCE      int
                        )
 
                        //hls stream gen 用户m3u8生成
-                       go func(){
+                       go func() {
                                per_second := time.Tick(time.Second)
                                for {
                                        select {
-                                       case <- savestream.cancel.WaitC():return;//exit
-                                       case now :=<- per_second:hls_msg.Push_tag(`clock`, now);
+                                       case <-savestream.cancel.WaitC():
+                                               return //exit
+                                       case now := <-per_second:
+                                               hls_msg.Push_tag(`clock`, now)
                                        }
                                }
                        }()
 
                        //hls stream gen 用户m3u8生成
-                       hls_msg.Pull_tag(map[string]func(interface{})(bool){
-                               `header`:func(d interface{})(bool){
-                                       if b,ok := d.([]byte);ok {
+                       hls_msg.Pull_tag(map[string]func(interface{}) bool{
+                               `header`: func(d interface{}) bool {
+                                       if b, ok := d.([]byte); ok {
                                                hls_gen.hls_file_header = b
                                        }
                                        return false
                                },
-                               `body`:func(d interface{})(bool){
-                                       links,ok := d.([]*m4s_link_item)
-                                       if !ok {return false}
+                               `body`: func(d interface{}) bool {
+                                       links, ok := d.([]*m4s_link_item)
+                                       if !ok {
+                                               return false
+                                       }
                                        //remove hls first m4s
                                        if len(links) > 0 &&
                                                len((*links[0]).Base) > 0 &&
-                                               (*links[0]).Base[0] == 104 {links = links[1:]}
+                                               (*links[0]).Base[0] == 104 {
+                                               links = links[1:]
+                                       }
 
                                        hls_gen.m4s_list = append(hls_gen.m4s_list, links...)
-                                       
+
                                        return false
                                },
-                               `clock`:func(now interface{})(bool){
+                               `clock`: func(now interface{}) bool {
                                        //buffer
-                                       if len(hls_gen.m4s_list) - savestream.hlsbuffersize < 0 {
+                                       if len(hls_gen.m4s_list)-savestream.hlsbuffersize < 0 {
                                                return false
                                        }
 
                                        //add block
                                        var (
-                                               m4s_num int
+                                               m4s_num          int
                                                has_DICONTINUITY bool
-                                               res []byte
-                                               threshold = savestream.m4s_hls
+                                               res              []byte
+                                               threshold        = savestream.m4s_hls
                                        )
-                                       if threshold < 3 {threshold=3}
+                                       if threshold < 3 {
+                                               threshold = 3
+                                       }
                                        {
                                                //m4s list
                                                m4s_list_b := []byte{}
-                                               for k,v := range hls_gen.m4s_list {
+                                               for k, v := range hls_gen.m4s_list {
                                                        if v.status != s_fin {
                                                                //#EXT-X-DISCONTINUITY-SEQUENCE
                                                                //reset hls lists
                                                                if !has_DICONTINUITY && m4s_num < threshold {
                                                                        m4s_list := append(util.SliceCopy(hls_gen.m4s_list[:k]).([]*m4s_link_item), &m4s_link_item{
-                                                                               Base:"DICONTINUITY",
-                                                                               status:s_fin,
-                                                                               isshow:true,
+                                                                               Base:   "DICONTINUITY",
+                                                                               status: s_fin,
+                                                                               isshow: true,
                                                                        })
                                                                        hls_gen.m4s_list = append(m4s_list, hls_gen.m4s_list[k:]...)
                                                                        m4s_list_b = append(m4s_list_b, []byte("#EXT-X-DICONTINUITY\n")...)
@@ -995,7 +1059,9 @@ func Savestreamf(){
                                                                continue
                                                        }
 
-                                                       if m4s_num >= savestream.m4s_hls {break}
+                                                       if m4s_num >= savestream.m4s_hls {
+                                                               break
+                                                       }
 
                                                        m4s_num += 1
                                                        // if m4s_num == 1 {SEQUENCE = strings.ReplaceAll(v.Base, ".m4s", "")}
@@ -1013,7 +1079,7 @@ func Savestreamf(){
                                                        //add #EXT-X-MEDIA-SEQUENCE
                                                        res = append(res, []byte("#EXT-X-MEDIA-SEQUENCE:"+strconv.Itoa(SEQUENCE)+"\n")...)
                                                        //add #INFO
-                                                       res = append(res, []byte(fmt.Sprintf("#INFO-BUFFER:%d/%d\n",m4s_num,len(hls_gen.m4s_list)))...)
+                                                       res = append(res, []byte(fmt.Sprintf("#INFO-BUFFER:%d/%d\n", m4s_num, len(hls_gen.m4s_list)))...)
                                                        //add m4s
                                                        res = append(res, m4s_list_b...)
                                                        //去除最后一个换行
@@ -1025,11 +1091,11 @@ func Savestreamf(){
                                        var skip_del bool
                                        if m4s_num < threshold {
                                                var (
-                                                       index int//the first useable fmp4 index of section
+                                                       index            int //the first useable fmp4 index of section
                                                        DICONTINUITY_num int
-                                                       catch bool//catch useable fmp4?
+                                                       catch            bool //catch useable fmp4?
                                                )
-                                               for i:=0;i<len(hls_gen.m4s_list);i+=1 {
+                                               for i := 0; i < len(hls_gen.m4s_list); i += 1 {
                                                        if hls_gen.m4s_list[i].status != s_fin {
                                                                catch = false
                                                                continue
@@ -1043,12 +1109,14 @@ func Savestreamf(){
                                                                        //find a nice index, remove all bad fmp4s
                                                                        skip := 0
                                                                        skip_del = true
-                                                                       for ;index>=0;index-=1 {
-                                                                               if hls_gen.m4s_list[index].status == s_fin {continue}
-                                                                               skip+=1
-                                                                               hls_gen.m4s_list = append(hls_gen.m4s_list[:index],hls_gen.m4s_list[index+1:]...)
+                                                                       for ; index >= 0; index -= 1 {
+                                                                               if hls_gen.m4s_list[index].status == s_fin {
+                                                                                       continue
+                                                                               }
+                                                                               skip += 1
+                                                                               hls_gen.m4s_list = append(hls_gen.m4s_list[:index], hls_gen.m4s_list[index+1:]...)
                                                                        }
-                                                                       l.L(`I: `,"卡顿,跳过",skip,"个tag")
+                                                                       l.L(`I: `, "卡顿,跳过", skip, "个tag")
                                                                        break
                                                                }
                                                        }
@@ -1057,13 +1125,17 @@ func Savestreamf(){
                                        }
 
                                        //设置到全局变量,方便流服务器获取
-                                       if len(res) != 0 {savestream.hls_stream.b = res}
-                                       savestream.hls_stream.t,_ = now.(time.Time)
+                                       if len(res) != 0 {
+                                               savestream.hls_stream.b = res
+                                       }
+                                       savestream.hls_stream.t, _ = now.(time.Time)
 
                                        //del
-                                       for del_num:=1;!skip_del&&del_num > 0;hls_gen.m4s_list = hls_gen.m4s_list[1:] {
+                                       for del_num := 1; !skip_del && del_num > 0; hls_gen.m4s_list = hls_gen.m4s_list[1:] {
                                                del_num -= 1
-                                               if !hls_gen.m4s_list[0].isshow {continue}
+                                               if !hls_gen.m4s_list[0].isshow {
+                                                       continue
+                                               }
                                                //#EXT-X-DICONTINUITY
                                                if hls_gen.m4s_list[0].Base == "DICONTINUITY" {
                                                        DISCONTINUITY += 1
@@ -1073,23 +1145,23 @@ func Savestreamf(){
                                                if hls_gen.m4s_list[0].isshow {
                                                        SEQUENCE += 1
 
-                                                       {//stream hls2mp4
+                                                       { //stream hls2mp4
                                                                var buf []byte
                                                                //stream front
                                                                if len(savestream.front) == 0 {
-                                                                       buf,_,e := get_m4s_cache(savestream.path+hls_gen.hls_first_fmp4_name)
+                                                                       buf, _, e := get_m4s_cache(savestream.path + hls_gen.hls_first_fmp4_name)
                                                                        if e == nil {
                                                                                savestream.front = buf
                                                                        } else {
-                                                                               l.L(`W: `,`推送mp4流错误,无法读取文件` ,e)
+                                                                               l.L(`W: `, `推送mp4流错误,无法读取文件`, e)
                                                                        }
                                                                }
                                                                //stream body
-                                                               buf,_,e := get_m4s_cache(savestream.path+hls_gen.m4s_list[0].Base)
+                                                               buf, _, e := get_m4s_cache(savestream.path + hls_gen.m4s_list[0].Base)
                                                                if e == nil {
                                                                        savestream.stream.Push_tag(`stream`, buf)
                                                                } else {
-                                                                       l.L(`W: `,`推送mp4流错误,无法读取文件` ,e)
+                                                                       l.L(`W: `, `推送mp4流错误,无法读取文件`, e)
                                                                }
                                                        }
                                                }
@@ -1097,31 +1169,31 @@ func Savestreamf(){
 
                                        return false
                                },
-                               `close`:func(d interface{})(bool){
-                                       savestream.hls_stream.b = []byte{}//退出置空
+                               `close`: func(d interface{}) bool {
+                                       savestream.hls_stream.b = []byte{} //退出置空
                                        savestream.hls_stream.t = time.Now()
                                        return true
                                },
                        })
 
                        var (
-                               last_download *m4s_link_item
-                               miss_download = make(chan *m4s_link_item,100)
+                               last_download  *m4s_link_item
+                               miss_download  = make(chan *m4s_link_item, 100)
                                download_limit = funcCtrl.BlockFuncN{
-                                       Max:2,
-                               }//limit
+                                       Max: 2,
+                               } //limit
                        )
-                       expires := time.Now().Add(time.Minute*2).Unix()
+                       expires := time.Now().Add(time.Minute * 2).Unix()
 
                        var (
-                               path_front string
+                               path_front  string
                                path_behind string
                        )
 
                        for {
                                //退出,等待下载完成
                                if !savestream.cancel.Islive() {
-                                       l.L(`I: `,"退出,等待片段下载")
+                                       l.L(`I: `, "退出,等待片段下载")
                                        download_limit.None()
                                        download_limit.UnNone()
 
@@ -1131,22 +1203,22 @@ func Savestreamf(){
                                                links = append(links, <-miss_download)
                                        }
 
-                                       for k,v :=range links {
-                                               l.L(`I: `,"正在下载最后片段:",k+1,"/",len(links))
+                                       for k, v := range links {
+                                               l.L(`I: `, "正在下载最后片段:", k+1, "/", len(links))
                                                v.status = s_loading
                                                r := reqf.New()
                                                if e := r.Reqf(reqf.Rval{
-                                                       Url:v.Url,
-                                                       SaveToPath:savestream.path+v.Base,
-                                                       ConnectTimeout:5000,
-                                                       ReadTimeout:1000,
-                                                       Retry: 1,
-                                                       Proxy:c.Proxy,
+                                                       Url:            v.Url,
+                                                       SaveToPath:     savestream.path + v.Base,
+                                                       ConnectTimeout: 5000,
+                                                       ReadTimeout:    1000,
+                                                       Retry:          1,
+                                                       Proxy:          c.Proxy,
                                                }); e != nil && !errors.Is(e, io.EOF) {
-                                                       l.L(`I: `,e)
+                                                       l.L(`I: `, e)
                                                        v.status = s_fail
                                                } else {
-                                                       if usedt := r.UsedTime.Seconds();usedt > 700 {
+                                                       if usedt := r.UsedTime.Seconds(); usedt > 700 {
                                                                l.L(`I: `, `hls切片下载慢`, usedt, `ms`)
                                                        }
                                                        v.status = s_fin
@@ -1156,16 +1228,16 @@ func Savestreamf(){
                                        break
                                }
 
-                               links,file_add,exp,e := hls_get_link(c.Live,last_download)
+                               links, file_add, exp, e := hls_get_link(c.Live, last_download)
                                if e != nil {
                                        if e == no_Modified {
-                                               time.Sleep(time.Duration(2)*time.Second)
+                                               time.Sleep(time.Duration(2) * time.Second)
                                                continue
                                        } else if reqf.IsTimeout(e) || strings.Contains(e.Error(), "x509") {
-                                               l.L(`I: `,e)
+                                               l.L(`I: `, e)
                                                continue
                                        } else {
-                                               l.L(`W: `,e)
+                                               l.L(`W: `, e)
                                                break
                                        }
                                }
@@ -1174,13 +1246,15 @@ func Savestreamf(){
                                if last_download == nil {
                                        var res []byte
                                        {
-                                               for row,i:=bytes.SplitAfter(file_add, []byte("\n")),0;i<len(row);i+=1 {
+                                               for row, i := bytes.SplitAfter(file_add, []byte("\n")), 0; i < len(row); i += 1 {
                                                        if bytes.Contains(row[i], []byte("#EXT")) {
                                                                //set stream front
-                                                               if op := bytes.Index(row[i], []byte(`#EXT-X-MAP:URI="`));op != -1 {
-                                                                       hls_gen.hls_first_fmp4_name = string(row[i][op+16:len(row[i])-2])
+                                                               if op := bytes.Index(row[i], []byte(`#EXT-X-MAP:URI="`)); op != -1 {
+                                                                       hls_gen.hls_first_fmp4_name = string(row[i][op+16 : len(row[i])-2])
+                                                               }
+                                                               if bytes.Contains(row[i], []byte("#EXT-X-MEDIA-SEQUENCE")) || bytes.Contains(row[i], []byte("#EXTINF")) {
+                                                                       continue
                                                                }
-                                                               if bytes.Contains(row[i], []byte("#EXT-X-MEDIA-SEQUENCE")) || bytes.Contains(row[i], []byte("#EXTINF")){continue}
                                                                res = append(res, row[i]...)
                                                        }
                                                }
@@ -1189,7 +1263,7 @@ func Savestreamf(){
                                }
 
                                if len(links) == 0 {
-                                       time.Sleep(time.Duration(2)*time.Second)
+                                       time.Sleep(time.Duration(2) * time.Second)
                                        continue
                                }
 
@@ -1200,39 +1274,39 @@ func Savestreamf(){
 
                                //use guess
                                if last_download != nil {
-                                       previou,_ := strconv.Atoi((*last_download).Base[:len((*last_download).Base)-4])
-                                       now,_ := strconv.Atoi(links[0].Base[:len(links[0].Base)-4])
+                                       previou, _ := strconv.Atoi((*last_download).Base[:len((*last_download).Base)-4])
+                                       now, _ := strconv.Atoi(links[0].Base[:len(links[0].Base)-4])
                                        if previou < now-1 {
-                                               if diff := now - previou;diff > 100 {
-                                                       l.L(`W: `,`diff too large `,diff)
+                                               if diff := now - previou; diff > 100 {
+                                                       l.L(`W: `, `diff too large `, diff)
                                                        break
                                                } else {
-                                                       l.L(`I: `,`猜测hls`,previou,`-`,now,`(`,diff,`)`)
+                                                       l.L(`I: `, `猜测hls`, previou, `-`, now, `(`, diff, `)`)
                                                }
 
-                                               {//file_add
-                                                       for i:=now-1;i>previou;i-=1 {
-                                                               file_add = append([]byte(strconv.Itoa(i)+".m4s"),file_add...)
+                                               { //file_add
+                                                       for i := now - 1; i > previou; i -= 1 {
+                                                               file_add = append([]byte(strconv.Itoa(i)+".m4s"), file_add...)
                                                        }
                                                }
-                                               {//links
+                                               { //links
                                                        if path_front == "" || path_behind == "" {
                                                                u, e := url.Parse(links[0].Url)
                                                                if e != nil {
-                                                                       l.L(`E: `,`fault to enable guess`,e)
+                                                                       l.L(`E: `, `fault to enable guess`, e)
                                                                        return
                                                                }
-                                                               path_front = u.Scheme+"://"+path.Dir(u.Host+u.Path)+"/"
-                                                               path_behind = "?"+u.RawQuery
+                                                               path_front = u.Scheme + "://" + path.Dir(u.Host+u.Path) + "/"
+                                                               path_behind = "?" + u.RawQuery
                                                        }
 
                                                        //出错期间没能获取到的
-                                                       for i:=now-1;i>previou;i-=1 {
-                                                               base := strconv.Itoa(i)+".m4s"
+                                                       for i := now - 1; i > previou; i -= 1 {
+                                                               base := strconv.Itoa(i) + ".m4s"
                                                                links = append([]*m4s_link_item{
                                                                        &m4s_link_item{
-                                                                               Url:path_front+base+path_behind,
-                                                                               Base:base,
+                                                                               Url:  path_front + base + path_behind,
+                                                                               Base: base,
                                                                        },
                                                                }, links...)
                                                        }
@@ -1241,15 +1315,19 @@ func Savestreamf(){
                                }
 
                                if len(links) > 10 {
-                                       l.L(`T: `,`等待下载切片:`,len(links))
+                                       l.L(`T: `, `等待下载切片:`, len(links))
                                } else if len(links) > 100 {
-                                       l.L(`W: `,`重试,等待下载切片:`,len(links))
+                                       l.L(`W: `, `重试,等待下载切片:`, len(links))
 
-                                       if F.Get(`Liveing`);!c.Liveing {break}
-                                       if F.Get(`Live`);len(c.Live) == 0 {break}
+                                       if F.Get(`Liveing`); !c.Liveing {
+                                               break
+                                       }
+                                       if F.Get(`Live`); len(c.Live) == 0 {
+                                               break
+                                       }
 
                                        // set expect
-                                       expires = time.Now().Add(time.Minute*2).Unix()
+                                       expires = time.Now().Add(time.Minute * 2).Unix()
                                        continue
                                }
 
@@ -1258,68 +1336,72 @@ func Savestreamf(){
 
                                f := p.File()
                                f.FileWR(p.Filel{
-                                       File:savestream.path+"0.m3u8.dtmp",
-                                       Loc:-1,
-                                       Context:[]interface{}{file_add},
+                                       File:    savestream.path + "0.m3u8.dtmp",
+                                       Loc:     -1,
+                                       Context: []interface{}{file_add},
                                })
 
-                               for i:=0;i<len(links);i+=1 {
+                               for i := 0; i < len(links); i += 1 {
                                        //fmp4切片下载
-                                       go func(link *m4s_link_item,path string){
+                                       go func(link *m4s_link_item, path string) {
                                                //use url struct
                                                var link_url *url.URL
                                                {
-                                                       if tmp,e := url.Parse(link.Url);e != nil {
+                                                       if tmp, e := url.Parse(link.Url); e != nil {
                                                                l.L(`E: `, e)
                                                                return
-                                                       } else {link_url = tmp}
+                                                       } else {
+                                                               link_url = tmp
+                                                       }
                                                }
 
                                                download_limit.Block()
                                                defer download_limit.UnBlock()
 
                                                link.status = s_loading
-                                               for index:=0;index<len(Host_list);index+=1 {
+                                               for index := 0; index < len(Host_list); index += 1 {
                                                        link_url.Host = Host_list[index]
 
                                                        r := reqf.New()
                                                        if e := r.Reqf(reqf.Rval{
-                                                               Url: link_url.String(),
-                                                               SaveToPath: path + link.Base,
+                                                               Url:            link_url.String(),
+                                                               SaveToPath:     path + link.Base,
                                                                ConnectTimeout: 2000,
-                                                               ReadTimeout: 1000,
-                                                               Timeout: 2000,
-                                                               Proxy: c.Proxy,
-                                                       });e != nil{
+                                                               ReadTimeout:    1000,
+                                                               Timeout:        2000,
+                                                               Proxy:          c.Proxy,
+                                                       }); e != nil {
                                                                //try other host
-                                                               if index+1<len(Host_list) {continue}
+                                                               if index+1 < len(Host_list) {
+                                                                       continue
+                                                               }
 
                                                                if reqf.IsTimeout(e) || strings.Contains(e.Error(), "x509") {
                                                                        l.L(`T: `, link.Base, `将重试!`)
                                                                        //避免影响后续猜测
                                                                        link.Offset_line = 0
-                                                                       go func(link *m4s_link_item){miss_download <- link}(link)
+                                                                       go func(link *m4s_link_item) { miss_download <- link }(link)
                                                                } else {
                                                                        l.L(`W: `, e)
                                                                        link.status = s_fail
                                                                }
                                                        } else {
-                                                               if usedt := r.UsedTime.Seconds();usedt > 700 {
+                                                               if usedt := r.UsedTime.Seconds(); usedt > 700 {
                                                                        l.L(`I: `, `hls切片下载慢`, usedt, `ms`)
                                                                }
                                                                link.status = s_fin
                                                                //存入cache
-                                                               if _,ok := m4s_cache.Load(path + link.Base);!ok{
-                                                                       m4s_cache.Store(path + link.Base, r.Respon)
-                                                                       go func(){//移除
-                                                                               time.Sleep(time.Second*time.Duration(savestream.hlsbuffersize+savestream.m4s_hls+2))
+                                                               if _, ok := m4s_cache.Load(path + link.Base); !ok {
+                                                                       m4s_cache.Store(path+link.Base, r.Respon)
+                                                                       go func() { //移除
+                                                                               time.Sleep(time.Second * time.Duration(savestream.hlsbuffersize+savestream.m4s_hls+2))
                                                                                m4s_cache.Delete(path + link.Base)
                                                                        }()
                                                                }
                                                                break
                                                        }
                                                }
-                                       }(links[i],savestream.path)
+                                       }(links[i], savestream.path)
 
                                        //只记录最新
                                        if links[i].Offset_line > 0 {
@@ -1329,21 +1411,25 @@ func Savestreamf(){
 
                                //m3u8_url 将过期
                                if p.Sys().GetSTime()+60 > expires {
-                                       if F.Get(`Liveing`);!c.Liveing {break}
-                                       if F.Get(`Live`);len(c.Live) == 0 {break}
+                                       if F.Get(`Liveing`); !c.Liveing {
+                                               break
+                                       }
+                                       if F.Get(`Live`); len(c.Live) == 0 {
+                                               break
+                                       }
                                        // set expect
-                                       expires = time.Now().Add(time.Minute*2).Unix()
+                                       expires = time.Now().Add(time.Minute * 2).Unix()
                                } else {
                                        time.Sleep(time.Second)
                                }
                        }
 
-                       if p.Checkfile().IsExist(savestream.path+"0.m3u8.dtmp") {
+                       if p.Checkfile().IsExist(savestream.path + "0.m3u8.dtmp") {
                                f := p.File()
                                f.FileWR(p.Filel{
-                                       File:savestream.path+"0.m3u8.dtmp",
-                                       Loc:-1,
-                                       Context:[]interface{}{"#EXT-X-ENDLIST"},
+                                       File:    savestream.path + "0.m3u8.dtmp",
+                                       Loc:     -1,
+                                       Context: []interface{}{"#EXT-X-ENDLIST"},
                                })
                                p.FileMove(savestream.path+"0.m3u8.dtmp", savestream.path+"0.m3u8")
                        }
@@ -1352,15 +1438,15 @@ func Savestreamf(){
                }
                //set ro ``
                savestream.path = ``
-               savestream.front = []byte{}//flv头及首tag置空
+               savestream.front = []byte{} //flv头及首tag置空
                savestream.stream.Push_tag("close", nil)
-               Ass_f("", time.Now())//ass
-               l.L(`I: `,"结束")
+               Ass_f("", time.Now()) //ass
+               l.L(`I: `, "结束")
 
                if !savestream.cancel.Islive() {
                        // l.L(`I: `,"退出")
                        break
-               }//cancel
+               } //cancel
                /*
                        Savestream需要外部组件
                        ffmpeg http://ffmpeg.org/download.html
@@ -1380,62 +1466,74 @@ func Savestreamf(){
 }
 
 //已func形式调用,将会停止保存直播流
-func Savestream_wait(){
-       if !savestream.cancel.Islive() {return}
+func Savestream_wait() {
+       if !savestream.cancel.Islive() {
+               return
+       }
 
        savestream.cancel.Done()
-       c.Log.Base(`savestream`).L(`I: `,"等待停止")
+       c.Log.Base(`savestream`).L(`I: `, "等待停止")
        savestream.wait.Wait()
 }
 
 type Obs struct {
-       c obsws.Client
-       Prog string//程序路径
+       c    obsws.Client
+       Prog string //程序路径
 }
 
-var obs = Obs {
-       c:obsws.Client{Host: "127.0.0.1", Port: 4444},
-       Prog:"obs",
+var obs = Obs{
+       c:    obsws.Client{Host: "127.0.0.1", Port: 4444},
+       Prog: "obs",
 }
 
-func Obsf(on bool){
-       if !IsOn("调用obs") {return}
+func Obsf(on bool) {
+       if !IsOn("调用obs") {
+               return
+       }
        l := c.Log.Base(`obs`)
 
        if on {
-               if p.Sys().CheckProgram("obs")[0] != 0 {l.L(`W: `,"obs已经启动");return}
+               if p.Sys().CheckProgram("obs")[0] != 0 {
+                       l.L(`W: `, "obs已经启动")
+                       return
+               }
                if p.Sys().CheckProgram("obs")[0] == 0 {
                        if obs.Prog == "" {
-                               l.L(`E: `,"未知的obs程序位置")
+                               l.L(`E: `, "未知的obs程序位置")
                                return
                        }
-                       l.L(`I: `,"启动obs")
+                       l.L(`I: `, "启动obs")
                        p.Exec().Start(exec.Command(obs.Prog))
                        p.Sys().Timeoutf(3)
                }
 
                // Connect a client.
                if err := obs.c.Connect(); err != nil {
-                       l.L(`E: `,err)
+                       l.L(`E: `, err)
                        return
                }
        } else {
-               if p.Sys().CheckProgram("obs")[0] == 0 {l.L(`W: `,"obs未启动");return}
+               if p.Sys().CheckProgram("obs")[0] == 0 {
+                       l.L(`W: `, "obs未启动")
+                       return
+               }
                obs.c.Disconnect()
        }
 }
 
-func Obs_R(on bool){
-       if !IsOn("调用obs") {return}
+func Obs_R(on bool) {
+       if !IsOn("调用obs") {
+               return
+       }
 
        l := c.Log.Base("obs_R")
 
        if p.Sys().CheckProgram("obs")[0] == 0 {
-               l.L(`W: `,"obs未启动")
+               l.L(`W: `, "obs未启动")
                return
        } else {
                if err := obs.c.Connect(); err != nil {
-                       l.L(`E: `,err)
+                       l.L(`E: `, err)
                        return
                }
        }
@@ -1443,30 +1541,30 @@ func Obs_R(on bool){
        if on {
                req := obsws.NewStartRecordingRequest()
                if err := req.Send(obs.c); err != nil {
-                       l.L(`E: `,err)
+                       l.L(`E: `, err)
                        return
                }
                resp, err := req.Receive()
                if err != nil {
-                       l.L(`E: `,err)
+                       l.L(`E: `, err)
                        return
                }
                if resp.Status() == "ok" {
-                       l.L(`I: `,"开始录制")
+                       l.L(`I: `, "开始录制")
                }
        } else {
                req := obsws.NewStopRecordingRequest()
                if err := req.Send(obs.c); err != nil {
-                       l.L(`E: `,err)
+                       l.L(`E: `, err)
                        return
                }
                resp, err := req.Receive()
                if err != nil {
-                       l.L(`E: `,err)
+                       l.L(`E: `, err)
                        return
                }
                if resp.Status() == "ok" {
-                       l.L(`I: `,"停止录制")
+                       l.L(`I: `, "停止录制")
                }
                p.Sys().Timeoutf(3)
        }
@@ -1474,21 +1572,22 @@ func Obs_R(on bool){
 
 type Autoban struct {
        Banbuf []string
-       buf []string
+       buf    []string
 }
 
-var autoban = Autoban {
-}
+var autoban = Autoban{}
 
 func Autobanf(s string) bool {
-       if !IsOn("Autoban") {return false}
+       if !IsOn("Autoban") {
+               return false
+       }
 
        if len(autoban.Banbuf) == 0 {
                f := p.File().FileWR(p.Filel{
-                       File:"Autoban.txt",
+                       File: "Autoban.txt",
                })
 
-               for _,v := range strings.Split(f, "\n") {
+               for _, v := range strings.Split(f, "\n") {
                        autoban.Banbuf = append(autoban.Banbuf, v)
                }
        }
@@ -1497,66 +1596,82 @@ func Autobanf(s string) bool {
                autoban.buf = append(autoban.buf, s)
                return false
        }
-       defer func(){
+       defer func() {
                autoban.buf = append(autoban.buf[1:], s)
        }()
 
        var res []float32
        {
                pt := float32(len([]rune(s)))
-               if pt <= 5 {return false}//字数过少去除
+               if pt <= 5 {
+                       return false
+               } //字数过少去除
                res = append(res, pt)
        }
        {
-               pt := selfcross(s);
+               pt := selfcross(s)
                // if pt > 0.5 {return false}//自身重复高去除
                // res = append(res, pt)
 
-               pt1 := cross(s, autoban.buf);
-               if pt + pt1 > 0.3 {return false}//历史重复高去除
+               pt1 := cross(s, autoban.buf)
+               if pt+pt1 > 0.3 {
+                       return false
+               } //历史重复高去除
                res = append(res, pt, pt1)
        }
        {
-               pt := cross(s, autoban.Banbuf);
-               if pt < 0.8 {return false}//ban字符重复低去除
+               pt := cross(s, autoban.Banbuf)
+               if pt < 0.8 {
+                       return false
+               } //ban字符重复低去除
                res = append(res, pt)
        }
        l := c.Log.Base("autoban")
-       l.L(`W: `,res)
+       l.L(`W: `, res)
        return true
 }
 
 type Danmuji struct {
-       Buf map[string]string
-       Inuse_auto bool
+       Buf           map[string]string
+       Inuse_auto    bool
        reflect_limit *limit.Limit
 
        mute bool
 }
 
 var danmuji = Danmuji{
-       Inuse_auto:IsOn("自动弹幕机"),
-       Buf:map[string]string{
-               "弹幕机在么":"在",
+       Inuse_auto: IsOn("自动弹幕机"),
+       Buf: map[string]string{
+               "弹幕机在么": "在",
        },
-       reflect_limit:limit.New(1,4000,8000),
+       reflect_limit: limit.New(1, 4000, 8000),
 }
 
-func init(){//初始化反射型弹幕机
-       buf := b.New()
-       buf.Load("config/config_auto_reply.json")
-       for k,v := range buf.B {
-               if k == v {continue}
+func init() { //初始化反射型弹幕机
+       bb, err := ioutil.ReadFile("config/config_auto_reply.json")
+       if err != nil {
+               return
+       }
+       var buf map[string]interface{}
+       json.Unmarshal(bb, &buf)
+       for k, v := range buf {
+               if k == v {
+                       continue
+               }
                danmuji.Buf[k] = v.(string)
        }
 }
 
 func Danmujif(s string) {
-       if !IsOn("反射弹幕机") {return}
+       if !IsOn("反射弹幕机") {
+               return
+       }
 
-       if danmuji.reflect_limit.TO() {return}
+       if danmuji.reflect_limit.TO() {
+               return
+       }
 
-       for k,v := range danmuji.Buf {
+       for k, v := range danmuji.Buf {
                if strings.Contains(s, k) {
                        Msg_senddanmu(v)
                        break
@@ -1565,24 +1680,32 @@ func Danmujif(s string) {
 }
 
 func Danmuji_auto() {
-       if !IsOn("反射弹幕机") || !IsOn("自动弹幕机") || danmuji.mute {return}
+       if !IsOn("反射弹幕机") || !IsOn("自动弹幕机") || danmuji.mute {
+               return
+       }
 
        danmuji.mute = true
 
        var (
-               list []string
+               list    []string
                timeout int
        )
-       for _,v := range c.K_v.LoadV(`自动弹幕机_内容`).([]interface{}){
+       for _, v := range c.K_v.LoadV(`自动弹幕机_内容`).([]interface{}) {
                list = append(list, v.(string))
        }
        timeout = int(c.K_v.LoadV(`自动弹幕机_发送间隔s`).(float64))
-       if timeout < 5 {timeout = 5}
+       if timeout < 5 {
+               timeout = 5
+       }
 
-       go func(){
-               for i := 0; true; i++{
-                       if i >= len(list) {i = 0}
-                       if msg := list[i];msg != ``{Msg_senddanmu(msg)}
+       go func() {
+               for i := 0; true; i++ {
+                       if i >= len(list) {
+                               i = 0
+                       }
+                       if msg := list[i]; msg != `` {
+                               Msg_senddanmu(msg)
+                       }
                        p.Sys().Timeoutf(timeout)
                }
        }()
@@ -1590,66 +1713,70 @@ func Danmuji_auto() {
 
 type Autoskip struct {
        roomid int
-       buf map[string]Autoskip_item
+       buf    map[string]Autoskip_item
        sync.Mutex
-       now uint
+       now    uint
        ticker *time.Ticker
 }
 
 type Autoskip_item struct {
        Exprie uint
-       Num uint
+       Num    uint
 }
 
 var autoskip = Autoskip{
-       buf:make(map[string]Autoskip_item),
-       ticker:time.NewTicker(time.Duration(2)*time.Second),
+       buf:    make(map[string]Autoskip_item),
+       ticker: time.NewTicker(time.Duration(2) * time.Second),
 }
 
-func init(){
-       go func(){
+func init() {
+       go func() {
                for {
                        <-autoskip.ticker.C
-                       if len(autoskip.buf) == 0 {continue}
+                       if len(autoskip.buf) == 0 {
+                               continue
+                       }
                        autoskip.now += 1
                        autoskip.Lock()
                        if autoskip.roomid != c.Roomid {
                                autoskip.buf = make(map[string]Autoskip_item)
                                autoskip.roomid = c.Roomid
-                               flog.Base_add(`弹幕合并`).L(`T: `,`房间更新:`,autoskip.roomid)
+                               flog.Base_add(`弹幕合并`).L(`T: `, `房间更新:`, autoskip.roomid)
                                autoskip.Unlock()
                                continue
                        }
-                       for k,v := range autoskip.buf{
+                       for k, v := range autoskip.buf {
                                if v.Exprie <= autoskip.now {
-                                       delete(autoskip.buf,k)
-                                       {//超时显示
+                                       delete(autoskip.buf, k)
+                                       { //超时显示
                                                if v.Num > 3 {
-                                                       c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-                                                               uid:`0multi`,
-                                                               m:map[string]string{
-                                                                       `{num}`:strconv.Itoa(int(v.Num)),
-                                                                       `{msg}`:k,
+                                                       c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+                                                               uid: `0multi`,
+                                                               m: map[string]string{
+                                                                       `{num}`: strconv.Itoa(int(v.Num)),
+                                                                       `{msg}`: k,
                                                                },
                                                        })
                                                        Msg_showdanmu(Danmu_item{
-                                                               msg:strconv.Itoa(int(v.Num)) + " x " + k,
-                                                               uid:`0multi`,
-                                                               roomid:autoskip.roomid,
+                                                               msg:    strconv.Itoa(int(v.Num)) + " x " + k,
+                                                               uid:    `0multi`,
+                                                               roomid: autoskip.roomid,
                                                        })
                                                } else if v.Num > 1 {
                                                        Msg_showdanmu(Danmu_item{
-                                                               msg:strconv.Itoa(int(v.Num)) + " x " + k,
-                                                               uid:`0default`,
-                                                               roomid:autoskip.roomid,
+                                                               msg:    strconv.Itoa(int(v.Num)) + " x " + k,
+                                                               uid:    `0default`,
+                                                               roomid: autoskip.roomid,
                                                        })
                                                }
                                        }
                                }
                        }
-                       {//copy map
+                       { //copy map
                                tmp := make(map[string]Autoskip_item)
-                               for k,v := range autoskip.buf {tmp[k] = v}
+                               for k, v := range autoskip.buf {
+                                       tmp[k] = v
+                               }
                                autoskip.buf = tmp
                        }
                        autoskip.Unlock()
@@ -1658,60 +1785,64 @@ func init(){
 }
 
 func Autoskipf(s string) uint {
-       if !IsOn("弹幕合并") || s == ""{return 0}
+       if !IsOn("弹幕合并") || s == "" {
+               return 0
+       }
        autoskip.Lock()
        defer autoskip.Unlock()
        if autoskip.roomid != c.Roomid {
                autoskip.buf = make(map[string]Autoskip_item)
                autoskip.roomid = c.Roomid
-               flog.Base_add(`弹幕合并`).L(`T: `,`房间更新:`,autoskip.roomid)
+               flog.Base_add(`弹幕合并`).L(`T: `, `房间更新:`, autoskip.roomid)
                return 0
        }
-       {//验证是否已经存在
-               if v,ok := autoskip.buf[s];ok && autoskip.now < v.Exprie{
+       { //验证是否已经存在
+               if v, ok := autoskip.buf[s]; ok && autoskip.now < v.Exprie {
                        autoskip.buf[s] = Autoskip_item{
-                               Exprie:v.Exprie,
-                               Num:v.Num+1,
+                               Exprie: v.Exprie,
+                               Num:    v.Num + 1,
                        }
                        return v.Num
                }
        }
-       {//设置
+       { //设置
                autoskip.buf[s] = Autoskip_item{
-                       Exprie:autoskip.now + 8,
-                       Num:1,
+                       Exprie: autoskip.now + 8,
+                       Num:    1,
                }
        }
        return 0
 }
 
 type Lessdanmu struct {
-       roomid int
-       buf []string
-       limit *limit.Limit
-       max_num int
+       roomid    int
+       buf       []string
+       limit     *limit.Limit
+       max_num   int
        threshold float32
 }
 
 var lessdanmu = Lessdanmu{
-       threshold:0.7,
+       threshold: 0.7,
 }
 
 func init() {
-       if max_num,ok := c.K_v.LoadV(`每秒显示弹幕数`).(float64);ok && int(max_num) >= 1 {
-               flog.Base_add(`更少弹幕`).L(`T: `,`每秒弹幕数:`,int(max_num))
+       if max_num, ok := 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
+               lessdanmu.limit = limit.New(int(max_num), 1000, 0) //timeout right now
        }
 }
 
 func Lessdanmuf(s string) (show bool) {
-       if !IsOn("相似弹幕忽略") {return true}
+       if !IsOn("相似弹幕忽略") {
+               return true
+       }
        if lessdanmu.roomid != c.Roomid {
                lessdanmu.buf = nil
                lessdanmu.roomid = c.Roomid
                lessdanmu.threshold = 0.7
-               flog.Base_add(`更少弹幕`).L(`T: `,`房间更新:`,lessdanmu.roomid)
+               flog.Base_add(`更少弹幕`).L(`T: `, `房间更新:`, lessdanmu.roomid)
                return true
        }
        if len(lessdanmu.buf) < 20 {
@@ -1720,7 +1851,9 @@ func Lessdanmuf(s string) (show bool) {
        }
 
        o := cross(s, lessdanmu.buf)
-       if o == 1 {return false}//完全无用
+       if o == 1 {
+               return false
+       } //完全无用
 
        Jiezouf(lessdanmu.buf)
        lessdanmu.buf = append(lessdanmu.buf[1:], s)
@@ -1791,24 +1924,30 @@ type Shortdanmu struct {
        lastdanmu []rune
 }
 
-var shortdanmu = Shortdanmu{
-}
+var shortdanmu = Shortdanmu{}
 
 func Shortdanmuf(s string) string {
-       if !IsOn("精简弹幕") {return s}
-       if len(shortdanmu.lastdanmu) == 0 {shortdanmu.lastdanmu = []rune(s);return s}
+       if !IsOn("精简弹幕") {
+               return s
+       }
+       if len(shortdanmu.lastdanmu) == 0 {
+               shortdanmu.lastdanmu = []rune(s)
+               return s
+       }
 
        var new string
 
-       for k,v := range []rune(s) {
+       for k, v := range []rune(s) {
                if k >= len(shortdanmu.lastdanmu) {
                        new += string([]rune(s)[k:])
                        break
                }
                if v != shortdanmu.lastdanmu[k] {
                        switch k {
-                       case 0, 1, 2:new = s
-                       default:new = "..." + string([]rune(s)[k-1:])
+                       case 0, 1, 2:
+                               new = s
+                       default:
+                               new = "..." + string([]rune(s)[k-1:])
                        }
                        break
                }
@@ -1820,41 +1959,50 @@ func Shortdanmuf(s string) string {
 
 type Jiezou struct {
        alertdanmu string
-       skipS map[string]interface{}
+       skipS      map[string]interface{}
 
-       avg float32
+       avg  float32
        turn int
        sync.Mutex
 }
 
 var jiezou = Jiezou{
-       alertdanmu:"",
-       skipS:map[string]interface{}{//常见语气词忽略
-               "了":nil,
-               "的":nil,
-               "哈":nil,
-               "是":nil,
-               ",":nil,
-               "这":nil,
+       alertdanmu: "",
+       skipS: map[string]interface{}{ //常见语气词忽略
+               "了": nil,
+               "的": nil,
+               "哈": nil,
+               "是": nil,
+               ",": nil,
+               "这": nil,
        },
 }
 
 func Jiezouf(s []string) bool {
-       if !IsOn("Jiezou") {return false}
-       now,S := selfcross2(s)
-       jiezou.avg = (8 * jiezou.avg + 2 * now)/10
-       if jiezou.turn < len(s) {jiezou.turn += 1;return false}
+       if !IsOn("Jiezou") {
+               return false
+       }
+       now, S := selfcross2(s)
+       jiezou.avg = (8*jiezou.avg + 2*now) / 10
+       if jiezou.turn < len(s) {
+               jiezou.turn += 1
+               return false
+       }
 
-       if _,ok := jiezou.skipS[S]; ok {return false}
+       if _, ok := jiezou.skipS[S]; ok {
+               return false
+       }
 
        jiezou.Lock()
-       if now > 1.3 * jiezou.avg {//触发
-               c.Log.Base("jiezou").L(`W: `,"节奏注意", now, jiezou.avg, S)
+       if now > 1.3*jiezou.avg { //触发
+               c.Log.Base("jiezou").L(`W: `, "节奏注意", now, jiezou.avg, S)
                jiezou.avg = now //沉默
                jiezou.Unlock()
 
                //发送弹幕
-               if jiezou.alertdanmu != "" {Msg_senddanmu(jiezou.alertdanmu)}
+               if jiezou.alertdanmu != "" {
+                       Msg_senddanmu(jiezou.alertdanmu)
+               }
                return true
        }
        jiezou.Unlock()
@@ -1862,162 +2010,168 @@ func Jiezouf(s []string) bool {
 }
 
 //保存所有消息到json
-func init(){
+func init() {
        Save_to_json(0, []interface{}{`[`})
        c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
-               `change_room`:func(data interface{})(bool){//房间改变
+               `change_room`: func(data interface{}) bool { //房间改变
                        Save_to_json(0, []interface{}{`[`})
                        return false
                },
-               `flash_room`:func(data interface{})(bool){//房间改变
+               `flash_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 != ``{
+func Save_to_json(Loc int, Context []interface{}) {
+       if path, ok := c.K_v.LoadV(`save_to_json`).(string); ok && path != `` {
                p.File().FileWR(p.Filel{
-                       File:path,
-                       Loc:int64(Loc),
-                       Context:Context,
+                       File:    path,
+                       Loc:     int64(Loc),
+                       Context: Context,
                })
        }
 }
 
 //进入房间发送弹幕
-func Entry_danmu(){
+func Entry_danmu() {
        flog := flog.Base_add(`进房弹幕`)
 
        //检查与切换粉丝牌,只在cookie存在时启用
        F.Get(`CheckSwitch_FansMedal`)
 
-       if v,_ := c.K_v.LoadV(`进房弹幕_有粉丝牌时才发`).(bool);v && c.Wearing_FansMedal == 0{
-               flog.L(`T: `,`无粉丝牌`)
+       if v, _ := c.K_v.LoadV(`进房弹幕_有粉丝牌时才发`).(bool); v && c.Wearing_FansMedal == 0 {
+               flog.L(`T: `, `无粉丝牌`)
                return
        }
-       if v,_ := c.K_v.LoadV(`进房弹幕_仅发首日弹幕`).(bool);v {
+       if v, _ := c.K_v.LoadV(`进房弹幕_仅发首日弹幕`).(bool); v {
                res := F.Get_weared_medal()
                if res.Today_intimacy > 0 {
-                       flog.L(`T: `,`今日已发弹幕`)
+                       flog.L(`T: `, `今日已发弹幕`)
                        return
                }
        }
-       if array,ok := c.K_v.LoadV(`进房弹幕_内容`).([]interface{});ok && len(array) != 0{
-               rand := p.Rand().MixRandom(0,int64(len(array)-1))
+       if array, ok := 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)
        }
 }
 
 //保持所有牌子点亮
 func Keep_medal_light() {
-       if v,_ := c.K_v.LoadV(`保持牌子亮着`).(bool);!v {
+       if v, _ := c.K_v.LoadV(`保持牌子亮着`).(bool); !v {
                return
        }
        flog := flog.Base_add(`保持亮牌`)
 
-       array,ok := c.K_v.LoadV(`进房弹幕_内容`).([]interface{})
-       if !ok || len(array) == 0{
-               flog.L(`I: `,`进房弹幕_内容 为 空,退出`)
+       array, ok := c.K_v.LoadV(`进房弹幕_内容`).([]interface{})
+       if !ok || len(array) == 0 {
+               flog.L(`I: `, `进房弹幕_内容 为 空,退出`)
                return
        }
 
-       flog.L(`T: `,`开始`)
+       flog.L(`T: `, `开始`)
 
        var hasKeep bool
-       for _,v := range F.Get_list_in_room() {
-               if t := int64(v.Last_wear_time) - time.Now().Unix();t > 60*60*24*2 || t < 0{continue}//到期时间在2天以上或已过期
+       for _, v := range F.Get_list_in_room() {
+               if v.IsLighted == 1 {
+                       continue
+               } //点亮状态
 
                hasKeep = true
 
-               info := F.Info(v.Target_id)
+               info := F.Info(v.TargetID)
                //两天内到期,发弹幕续期
-               rand := p.Rand().MixRandom(0,int64(len(array)-1))
+               rand := p.Rand().MixRandom(0, int64(len(array)-1))
                send.Danmu_s(array[rand].(string), info.Data.LiveRoom.Roomid)
                time.Sleep(time.Second)
        }
 
        //重试,使用历史弹幕
-       for _,v := range F.Get_list_in_room() {
-               if t := int64(v.Last_wear_time) - time.Now().Unix();t > 60*60*24*2 || t < 0{continue}//到期时间在2天以上或已过期
+       for _, v := range F.Get_list_in_room() {
+               if v.IsLighted == 1 {
+                       continue
+               }
 
-               info := F.Info(v.Target_id)
+               info := F.Info(v.TargetID)
                //两天内到期,发弹幕续期
                var Str string
-               for _,v := range F.GetHistory(info.Data.LiveRoom.Roomid).Data.Room{
+               for _, v := range F.GetHistory(info.Data.LiveRoom.Roomid).Data.Room {
                        if v.Text != "" {
                                Str = v.Text
                                break
                        }
                }
                if Str == "" {
-                       rand := p.Rand().MixRandom(0,int64(len(array)-1))
+                       rand := p.Rand().MixRandom(0, int64(len(array)-1))
                        Str = array[rand].(string)
                }
-               send.Danmu_s(Str,info.Data.LiveRoom.Roomid)
+               send.Danmu_s(Str, info.Data.LiveRoom.Roomid)
                time.Sleep(time.Second)
        }
 
        if hasKeep {
-               flog.L(`I: `,`完成`)
+               flog.L(`I: `, `完成`)
        } else {
-               flog.L(`T: `,`完成`)
+               flog.L(`T: `, `完成`)
        }
 }
 
 //自动发送即将过期的银瓜子礼物
 func AutoSend_silver_gift() {
-       day,_ := c.K_v.LoadV(`发送还有几天过期的礼物`).(float64)
+       day, _ := c.K_v.LoadV(`发送还有几天过期的礼物`).(float64)
        if day <= 0 {
                return
        }
 
-       flog := flog.Base_add(`自动送礼`).L(`T: `,`开始`)
+       flog := flog.Base_add(`自动送礼`).L(`T: `, `开始`)
 
-       if c.UpUid == 0 {F.Get(`UpUid`)}
+       if c.UpUid == 0 {
+               F.Get(`UpUid`)
+       }
 
        var hasSend bool
 
-       for _,v := range F.Gift_list() {
-               if time.Now().Add(time.Hour * time.Duration(24 * int(day))).Unix() > int64(v.Expire_at) {
+       for _, v := range F.Gift_list() {
+               if time.Now().Add(time.Hour*time.Duration(24*int(day))).Unix() > int64(v.Expire_at) {
                        hasSend = true
                        send.Send_gift(v.Gift_id, v.Bag_id, v.Gift_num)
                }
        }
 
        if hasSend {
-               flog.L(`I: `,`完成`)
+               flog.L(`I: `, `完成`)
        } else {
-               flog.L(`T: `,`完成`)
+               flog.L(`T: `, `完成`)
        }
 }
 
-var m4s_cache sync.Map//使用内存cache避免频繁io
+var m4s_cache sync.Map //使用内存cache避免频繁io
 
-func get_m4s_cache(path string)(buf []byte, cached bool, err error){
-       if b,ok := m4s_cache.Load(path);!ok{
-               f,e := os.OpenFile(path,os.O_RDONLY,0644)
+func get_m4s_cache(path string) (buf []byte, cached bool, err error) {
+       if b, ok := m4s_cache.Load(path); !ok {
+               f, e := os.OpenFile(path, os.O_RDONLY, 0644)
                if e != nil {
                        err = e
                        return
                }
                defer f.Close()
 
-               if b,e := io.ReadAll(f);e != nil {
+               if b, e := io.ReadAll(f); e != nil {
                        err = e
                        return
                } else {
                        buf = b
-                       m4s_cache.Store(path,buf)
-                       go func(){//移除
-                               time.Sleep(time.Second*time.Duration(savestream.m4s_hls+2))
+                       m4s_cache.Store(path, buf)
+                       go func() { //移除
+                               time.Sleep(time.Second * time.Duration(savestream.m4s_hls+2))
                                m4s_cache.Delete(path)
                        }()
                }
        } else {
                cached = true
-               buf,_ = b.([]byte)
+               buf, _ = b.([]byte)
        }
        return
 }
@@ -2025,7 +2179,7 @@ func get_m4s_cache(path string)(buf []byte, cached bool, err error){
 //直播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.K_v.LoadV(`直播Web服务口`).(float64); ok && port_f >= 0 {
                port := int(port_f)
 
                base_dir := savestream.base_path
@@ -2041,7 +2195,7 @@ func init() {
                        Addr: addr,
                })
                var (
-                       root = func(w http.ResponseWriter,r *http.Request){
+                       root = func(w http.ResponseWriter, r *http.Request) {
                                //header
                                w.Header().Set("Access-Control-Allow-Credentials", "true")
                                w.Header().Set("Access-Control-Allow-Headers", "*")
@@ -2050,10 +2204,10 @@ func init() {
                                w.Header().Set("Connection", "keep-alive")
                                w.Header().Set("Content-Transfer-Encoding", "binary")
                                start := time.Now()
-                               
+
                                var path string = r.URL.Path[1:]
 
-                               if !p.Checkfile().IsExist(base_dir+path) {
+                               if !p.Checkfile().IsExist(base_dir + path) {
                                        w.WriteHeader(http.StatusNotFound)
                                        return
                                }
@@ -2061,7 +2215,7 @@ func init() {
                                if savestream.path != "" && strings.Contains(path, filepath.Base(savestream.path)) {
                                        w.Header().Set("Server", "live")
                                        if filepath.Ext(path) == `.dtmp` {
-                                               if strings.Contains(path,".flv") {
+                                               if strings.Contains(path, ".flv") {
                                                        if len(savestream.front) == 0 {
                                                                w.Header().Set("Retry-After", "1")
                                                                w.WriteHeader(http.StatusServiceUnavailable)
@@ -2073,10 +2227,12 @@ func init() {
                                                        w.WriteHeader(http.StatusOK)
 
                                                        flusher, flushSupport := w.(http.Flusher)
-                                                       if flushSupport {flusher.Flush()}
+                                                       if flushSupport {
+                                                               flusher.Flush()
+                                                       }
 
                                                        //写入flv头,首tag
-                                                       if _,err := w.Write(savestream.front);err != nil {
+                                                       if _, err := w.Write(savestream.front); err != nil {
                                                                return
                                                        } else if flushSupport {
                                                                flusher.Flush()
@@ -2085,10 +2241,10 @@ func init() {
                                                        cancel := make(chan struct{})
 
                                                        //flv流关键帧间隔切片
-                                                       savestream.stream.Pull_tag(map[string]func(interface{})(bool){
-                                                               `stream`:func(data interface{})(bool){
-                                                                       if b,ok := data.([]byte);ok{
-                                                                               if _,err := w.Write(b);err != nil {
+                                                       savestream.stream.Pull_tag(map[string]func(interface{}) bool{
+                                                               `stream`: func(data interface{}) bool {
+                                                                       if b, ok := data.([]byte); ok {
+                                                                               if _, err := w.Write(b); err != nil {
                                                                                        close(cancel)
                                                                                        return true
                                                                                } else if flushSupport {
@@ -2097,14 +2253,14 @@ func init() {
                                                                        }
                                                                        return false
                                                                },
-                                                               `close`:func(data interface{})(bool){
+                                                               `close`: func(data interface{}) bool {
                                                                        close(cancel)
                                                                        return true
                                                                },
                                                        })
 
-                                                       <- cancel
-                                               } else if strings.Contains(path,".m3u8") {
+                                                       <-cancel
+                                               } else if strings.Contains(path, ".m3u8") {
                                                        if r.URL.Query().Get("type") == "mp4" {
                                                                if len(savestream.front) == 0 {
                                                                        w.Header().Set("Retry-After", "1")
@@ -2117,10 +2273,12 @@ func init() {
                                                                w.WriteHeader(http.StatusOK)
 
                                                                flusher, flushSupport := w.(http.Flusher)
-                                                               if flushSupport {flusher.Flush()}
+                                                               if flushSupport {
+                                                                       flusher.Flush()
+                                                               }
 
                                                                //写入hls头
-                                                               if _,err := w.Write(savestream.front);err != nil {
+                                                               if _, err := w.Write(savestream.front); err != nil {
                                                                        return
                                                                } else if flushSupport {
                                                                        flusher.Flush()
@@ -2129,10 +2287,10 @@ func init() {
                                                                cancel := make(chan struct{})
 
                                                                //hls切片
-                                                               savestream.stream.Pull_tag(map[string]func(interface{})(bool){
-                                                                       `stream`:func(data interface{})(bool){
-                                                                               if b,ok := data.([]byte);ok{
-                                                                                       if _,err := w.Write(b);err != nil {
+                                                               savestream.stream.Pull_tag(map[string]func(interface{}) bool{
+                                                                       `stream`: func(data interface{}) bool {
+                                                                               if b, ok := data.([]byte); ok {
+                                                                                       if _, err := w.Write(b); err != nil {
                                                                                                close(cancel)
                                                                                                return true
                                                                                        } else if flushSupport {
@@ -2141,36 +2299,36 @@ func init() {
                                                                                }
                                                                                return false
                                                                        },
-                                                                       `close`:func(data interface{})(bool){
+                                                                       `close`: func(data interface{}) bool {
                                                                                close(cancel)
                                                                                return true
                                                                        },
                                                                })
 
-                                                               <- cancel
+                                                               <-cancel
                                                        } else {
                                                                w.Header().Set("Cache-Control", "max-age=1")
                                                                w.Header().Set("Content-Type", "application/vnd.apple.mpegurl")
                                                                w.Header().Set("Last-Modified", savestream.hls_stream.t.Format(http.TimeFormat))
-       
+
                                                                // //经常m4s下载速度赶不上,使用阻塞避免频繁获取列表带来的卡顿
                                                                // if time.Now().Sub(savestream.hls_stream.t).Seconds() > 1 {
                                                                //      time.Sleep(time.Duration(3)*time.Second)
                                                                // }
-       
+
                                                                res := savestream.hls_stream.b
-       
+
                                                                if len(res) == 0 {
                                                                        w.Header().Set("Retry-After", "1")
                                                                        w.WriteHeader(http.StatusServiceUnavailable)
                                                                        return
                                                                }
-       
+
                                                                //Server-Timing
                                                                w.Header().Set("Server-Timing", fmt.Sprintf("dur=%d", time.Since(start).Microseconds()))
-       
-                                                               if _,err := w.Write(res);err != nil {
-                                                                       flog.L(`E: `,err)
+
+                                                               if _, err := w.Write(res); err != nil {
+                                                                       flog.L(`E: `, err)
                                                                        return
                                                                }
                                                        }
@@ -2179,9 +2337,9 @@ func init() {
                                                w.Header().Set("Server", "live")
                                                w.Header().Set("Cache-Control", "Cache-Control:public, max-age=3600")
 
-                                               path = base_dir+path
+                                               path = base_dir + path
 
-                                               buf,cached,e := get_m4s_cache(path)
+                                               buf, cached, e := get_m4s_cache(path)
 
                                                if e != nil {
                                                        w.Header().Set("Retry-After", "1")
@@ -2190,7 +2348,7 @@ func init() {
                                                }
 
                                                if len(buf) == 0 {
-                                                       flog.L(`W: `,`buf size 0`)
+                                                       flog.L(`W: `, `buf size 0`)
                                                        w.Header().Set("Retry-After", "1")
                                                        w.WriteHeader(http.StatusServiceUnavailable)
                                                        return
@@ -2199,37 +2357,39 @@ func init() {
                                                //Server-Timing
                                                w.Header().Add("Server-Timing", fmt.Sprintf("cache=%v;dur=%d", cached, time.Since(start).Microseconds()))
                                                w.WriteHeader(http.StatusOK)
-                                               if _,err := w.Write(buf);err != nil {
-                                                       flog.L(`E: `,err)
+                                               if _, err := w.Write(buf); err != nil {
+                                                       flog.L(`E: `, err)
                                                        return
                                                }
                                        }
                                } else {
                                        w.Header().Set("Server", "file")
-                                       if r.URL.Query().Get("type") == "mp4" {//hls拼合
-                                               dir := base_dir+filepath.Dir(path)+"/"
-                                               if !p.Checkfile().IsExist(dir+`0.m3u8`) {
+                                       if r.URL.Query().Get("type") == "mp4" { //hls拼合
+                                               dir := base_dir + filepath.Dir(path) + "/"
+                                               if !p.Checkfile().IsExist(dir + `0.m3u8`) {
                                                        w.WriteHeader(http.StatusNotFound)
                                                        return
                                                }
                                                var m4slist []string
                                                if e := filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
-                                                       if err != nil {return err}
+                                                       if err != nil {
+                                                               return err
+                                                       }
                                                        if filepath.Ext(info.Name()) == ".m4s" {
                                                                m4slist = append(m4slist, path)
                                                        }
                                                        return nil
-                                               });e != nil {
-                                                       flog.L(`E: `,e);
+                                               }); e != nil {
+                                                       flog.L(`E: `, e)
                                                        w.WriteHeader(http.StatusServiceUnavailable)
                                                        return
                                                }
                                                m4slist = append(m4slist[len(m4slist)-1:], m4slist[:len(m4slist)-1]...)
-                                               for _,v := range m4slist {
-                                                       f,err := os.OpenFile(v,os.O_RDONLY,0644)
+                                               for _, v := range m4slist {
+                                                       f, err := os.OpenFile(v, os.O_RDONLY, 0644)
                                                        if err != nil {
                                                                w.WriteHeader(http.StatusServiceUnavailable)
-                                                               flog.L(`E: `,err)
+                                                               flog.L(`E: `, err)
                                                                return
                                                        }
                                                        io.Copy(w, f)
@@ -2237,10 +2397,10 @@ func init() {
                                                }
                                                return
                                        }
-                                       http.FileServer(http.Dir(base_dir)).ServeHTTP(w,r)
+                                       http.FileServer(http.Dir(base_dir)).ServeHTTP(w, r)
                                }
                        }
-                       now = func(w http.ResponseWriter,r *http.Request){
+                       now = func(w http.ResponseWriter, r *http.Request) {
                                //header
                                w.Header().Set("Access-Control-Allow-Credentials", "true")
                                w.Header().Set("Access-Control-Allow-Headers", "*")
@@ -2250,25 +2410,25 @@ func init() {
 
                                //最新直播流
                                if savestream.path == `` {
-                                       flog.L(`T: `,`还没有下载直播流-直播流为空`)
+                                       flog.L(`T: `, `还没有下载直播流-直播流为空`)
                                        w.WriteHeader(http.StatusNotFound)
                                        return
                                }
 
                                path := filepath.Base(savestream.path)
-                               if strings.Contains(c.Live[0],"flv") {
+                               if strings.Contains(c.Live[0], "flv") {
                                        path += ".flv.dtmp"
                                } else {
                                        path += "/0.m3u8.dtmp"
                                }
 
-                               if !p.Checkfile().IsExist(base_dir+path) {
-                                       flog.L(`T: `,`还没有下载直播流-文件未能找到`)
+                               if !p.Checkfile().IsExist(base_dir + path) {
+                                       flog.L(`T: `, `还没有下载直播流-文件未能找到`)
                                        w.WriteHeader(http.StatusNotFound)
                                } else {
-                                       u, e := url.Parse("../"+path)
+                                       u, e := url.Parse("../" + path)
                                        if e != nil {
-                                               flog.L(`E: `,e)
+                                               flog.L(`E: `, e)
                                                w.Header().Set("Retry-After", "1")
                                                w.WriteHeader(http.StatusServiceUnavailable)
                                                return
@@ -2284,15 +2444,51 @@ func init() {
                                return
                        }
                )
-               s.Handle(map[string]func(http.ResponseWriter,*http.Request){
-                       `/`:root,
-                       `/now`:now,
-                       `/exit`:func(w http.ResponseWriter,r *http.Request){
+               s.Handle(map[string]func(http.ResponseWriter, *http.Request){
+                       `/`:    root,
+                       `/now`: now,
+                       `/exit`: func(w http.ResponseWriter, r *http.Request) {
                                s.Server.Shutdown(context.Background())
                        },
                })
                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.Stream_url = strings.Replace(`http://`+s.Server.Addr, `0.0.0.0`, host, -1)
+               flog.L(`I: `, `启动于`, c.Stream_url)
        }
-}
\ No newline at end of file
+}
+
+//此次直播的交互人数
+var communicate Communicate
+
+type Communicate struct {
+       Buf *psync.Map
+}
+
+func init() {
+       communicate.Buf = new(psync.Map)
+       c.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+               `change_room`: func(data interface{}) bool { //房间改变
+                       communicate.Reset()
+                       return false
+               },
+               `flash_room`: func(data interface{}) bool { //房间改变
+                       communicate.Reset()
+                       return false
+               },
+       })
+}
+
+func (t *Communicate) Reset() {
+       t.Buf.Range(func(key, _ interface{}) bool {
+               t.Buf.Delete(key)
+               return true
+       })
+}
+
+func (t *Communicate) Count() int {
+       return t.Buf.Len()
+}
+
+func (t *Communicate) Store(k interface{}) {
+       t.Buf.Store(k, nil)
+}
index 2e90e6906b1dec90eead012ee425a030d0438dcc..f79897ea97420c8f9282cdc83d9f3281bf4bbabe 100644 (file)
@@ -2,8 +2,9 @@ package reply
 
 import (
        "encoding/json"
+       "io/ioutil"
+
        c "github.com/qydysky/bili_danmu/CV"
-       s "github.com/qydysky/part/buf"
 )
 
 /*
@@ -13,88 +14,93 @@ import (
 var msglog = c.Log.Base(`Msg`)
 
 //Msg类型数据处理方法map
-var Msg_map = map[string]func(replyF, string) {
-       `VOICE_JOIN_ROOM_COUNT_INFO`:replyF.voice_join_room_count_info,//连麦等待
-       `VOICE_JOIN_LIST`:nil,
-       `VOICE_JOIN_STATUS`:replyF.voice_join_status,//连麦人状态
-       `STOP_LIVE_ROOM_LIST`:nil,//停止直播的直播间
-       `PK_LOTTERY_START`:replyF.pk_lottery_start,//大乱斗pk
-       `PK_BATTLE_PRE_NEW`:nil,//pk准备
-       `PK_BATTLE_START_NEW`:nil,//pk开始
-       `PK_BATTLE_PROCESS_NEW`:replyF.pk_battle_process_new,//pk进行中
-       `VTR_GIFT_LOTTERY`:replyF.vtr_gift_lottery,//特别礼物
-       `ENTRY_EFFECT_MUST_RECEIVE`:nil,//高能榜前三进入
-       `GIFT_BAG_DOT`:nil,
-       `LITTLE_MESSAGE_BOX`:replyF.little_message_box,//小消息
-       `MESSAGEBOX_USER_MEDAL_CHANGE`:replyF.messagebox_user_medal_change,//粉丝牌切换
-       `HOT_RANK_SETTLEMENT`:replyF.hot_rank_settlement,//热门榜获得
-       `HOT_RANK_CHANGED`:replyF.hot_rank_changed,//热门榜变动
-       `CARD_MSG`:nil,//提示关注
-       `WIDGET_BANNER`:nil,//每日任务
-       `ROOM_ADMINS`:nil,//房管列表
-       `ONLINE_RANK_TOP3`:nil,
-       `ONLINE_RANK_COUNT`:nil,
-       `ONLINE_RANK_V2`:nil,
-       "TRADING_SCORE":nil,//每日任务
-       "MATCH_ROOM_CONF":nil,//赛事房间配置
-       "HOT_ROOM_NOTIFY":nil,//热点房间
-       "MATCH_TEAM_GIFT_RANK":nil,//赛事人气比拼
-       "ACTIVITY_MATCH_GIFT":nil,//赛事礼物
-       "PK_BATTLE_PRE":nil,//人气pk
-       "PK_BATTLE_START":nil,//人气pk
-       "PK_BATTLE_PROCESS":nil,//人气pk
-       "PK_BATTLE_END":nil,//人气pk
-       "PK_BATTLE_RANK_CHANGE":nil,//人气pk
-       "PK_BATTLE_SETTLE_USER":nil,//人气pk
-       "PK_BATTLE_SETTLE_V2":nil,//人气pk
-       "PK_BATTLE_SETTLE":nil,//人气pk
-       "SYS_MSG":nil,//系统消息
-       "ROOM_SKIN_MSG":nil,
-       "GUARD_ACHIEVEMENT_ROOM":nil,
-       "ANCHOR_LOT_START":replyF.anchor_lot_start,//天选之人开始
-       "ANCHOR_LOT_CHECKSTATUS":nil,
-       "ANCHOR_LOT_END":nil,//天选之人结束
-       "ANCHOR_LOT_AWARD":replyF.anchor_lot_award,//天选之人获奖
-       "COMBO_SEND":nil,
-       "INTERACT_WORD":replyF.interact_word,//进入信息,包含直播间关注提示
-       "ACTIVITY_BANNER_UPDATE_V2":nil,
-       "NOTICE_MSG":nil,
-       "ROOM_BANNER":nil,
-       "ONLINERANK":nil,
-       "WELCOME":nil,
-       "HOUR_RANK_AWARDS":nil,
-       "ROOM_RANK":nil,
-       "ROOM_SHIELD":nil,
-       "USER_TOAST_MSG":replyF.user_toast_msg,//大航海购买信息
-       "WIN_ACTIVITY":replyF.win_activity,//活动
-       "SPECIAL_GIFT":replyF.special_gift,//节奏风暴
-       "GUARD_BUY":nil,//replyF.guard_buy,//大航海购买
-       "WELCOME_GUARD":nil,//replyF.welcome_guard,//大航海进入 ?已废弃?
-       "DANMU_MSG":replyF.danmu,//弹幕
-       "DANMU_MSG:4:0:2:2:2:0":replyF.danmu,//弹幕
-       "ROOM_CHANGE":replyF.room_change,//房间信息分区改变
-       "ROOM_SILENT_OFF":replyF.roomsilent,//禁言结束
-       "ROOM_SILENT_ON":replyF.roomsilent,//禁言开始
-       "SEND_GIFT":replyF.send_gift,//礼物
-       "ROOM_BLOCK_MSG":replyF.room_block_msg,//封禁
-       "PREPARING":replyF.preparing,//下播
-       "LIVE":replyF.live,//开播
-       "SUPER_CHAT_ENTRANCE":nil,//SC入口
-       "SUPER_CHAT_MESSAGE_DELETE":nil,//SC删除
-       "SUPER_CHAT_MESSAGE":nil,//replyF.super_chat_message,//SC
-       "SUPER_CHAT_MESSAGE_JPN":replyF.super_chat_message,//SC
-       "PANEL":nil,//replyF.panel,//排行榜 被HOT_RANK_CHANGED替代
-       "ENTRY_EFFECT":replyF.entry_effect,//进入特效
-       "ROOM_REAL_TIME_MESSAGE_UPDATE":nil,//replyF.roominfo,//粉丝数
+var Msg_map = map[string]func(replyF, string){
+       `VOICE_JOIN_ROOM_COUNT_INFO`:    replyF.voice_join_room_count_info, //连麦等待
+       `VOICE_JOIN_LIST`:               nil,
+       `VOICE_JOIN_STATUS`:             replyF.voice_join_status,     //连麦人状态
+       `STOP_LIVE_ROOM_LIST`:           nil,                          //停止直播的直播间
+       `PK_LOTTERY_START`:              replyF.pk_lottery_start,      //大乱斗pk
+       `PK_BATTLE_PRE_NEW`:             nil,                          //pk准备
+       `PK_BATTLE_START_NEW`:           nil,                          //pk开始
+       `PK_BATTLE_PROCESS_NEW`:         replyF.pk_battle_process_new, //pk进行中
+       `VTR_GIFT_LOTTERY`:              replyF.vtr_gift_lottery,      //特别礼物
+       `ENTRY_EFFECT_MUST_RECEIVE`:     nil,                          //高能榜前三进入
+       `GIFT_BAG_DOT`:                  nil,
+       `LITTLE_MESSAGE_BOX`:            replyF.little_message_box,           //小消息
+       `MESSAGEBOX_USER_MEDAL_CHANGE`:  replyF.messagebox_user_medal_change, //粉丝牌切换
+       `HOT_RANK_SETTLEMENT`:           replyF.hot_rank_settlement,          //热门榜获得
+       `HOT_RANK_CHANGED`:              replyF.hot_rank_changed,             //热门榜变动
+       `CARD_MSG`:                      nil,                                 //提示关注
+       `WIDGET_BANNER`:                 nil,                                 //每日任务
+       `ROOM_ADMINS`:                   nil,                                 //房管列表
+       `ONLINE_RANK_TOP3`:              nil,
+       `ONLINE_RANK_COUNT`:             nil,
+       `ONLINE_RANK_V2`:                nil,
+       "TRADING_SCORE":                 nil, //每日任务
+       "MATCH_ROOM_CONF":               nil, //赛事房间配置
+       "HOT_ROOM_NOTIFY":               nil, //热点房间
+       "MATCH_TEAM_GIFT_RANK":          nil, //赛事人气比拼
+       "ACTIVITY_MATCH_GIFT":           nil, //赛事礼物
+       "PK_BATTLE_PRE":                 nil, //人气pk
+       "PK_BATTLE_START":               nil, //人气pk
+       "PK_BATTLE_PROCESS":             nil, //人气pk
+       "PK_BATTLE_END":                 nil, //人气pk
+       "PK_BATTLE_RANK_CHANGE":         nil, //人气pk
+       "PK_BATTLE_SETTLE_USER":         nil, //人气pk
+       "PK_BATTLE_SETTLE_V2":           nil, //人气pk
+       "PK_BATTLE_SETTLE":              nil, //人气pk
+       "SYS_MSG":                       nil, //系统消息
+       "ROOM_SKIN_MSG":                 nil,
+       "GUARD_ACHIEVEMENT_ROOM":        nil,
+       "ANCHOR_LOT_START":              replyF.anchor_lot_start, //天选之人开始
+       "ANCHOR_LOT_CHECKSTATUS":        nil,
+       "ANCHOR_LOT_END":                nil,                     //天选之人结束
+       "ANCHOR_LOT_AWARD":              replyF.anchor_lot_award, //天选之人获奖
+       "COMBO_SEND":                    nil,
+       "INTERACT_WORD":                 replyF.interact_word, //进入信息,包含直播间关注提示
+       "ACTIVITY_BANNER_UPDATE_V2":     nil,
+       "NOTICE_MSG":                    nil,
+       "ROOM_BANNER":                   nil,
+       "ONLINERANK":                    nil,
+       "WELCOME":                       nil,
+       "HOUR_RANK_AWARDS":              nil,
+       "ROOM_RANK":                     nil,
+       "ROOM_SHIELD":                   nil,
+       "USER_TOAST_MSG":                replyF.user_toast_msg,     //大航海购买信息
+       "WIN_ACTIVITY":                  replyF.win_activity,       //活动
+       "SPECIAL_GIFT":                  replyF.special_gift,       //节奏风暴
+       "GUARD_BUY":                     nil,                       //replyF.guard_buy,//大航海购买
+       "WELCOME_GUARD":                 nil,                       //replyF.welcome_guard,//大航海进入 ?已废弃?
+       "DANMU_MSG":                     replyF.danmu,              //弹幕
+       "DANMU_MSG:4:0:2:2:2:0":         replyF.danmu,              //弹幕
+       "ROOM_CHANGE":                   replyF.room_change,        //房间信息分区改变
+       "ROOM_SILENT_OFF":               replyF.roomsilent,         //禁言结束
+       "ROOM_SILENT_ON":                replyF.roomsilent,         //禁言开始
+       "SEND_GIFT":                     replyF.send_gift,          //礼物
+       "ROOM_BLOCK_MSG":                replyF.room_block_msg,     //封禁
+       "PREPARING":                     replyF.preparing,          //下播
+       "LIVE":                          replyF.live,               //开播
+       "SUPER_CHAT_ENTRANCE":           nil,                       //SC入口
+       "SUPER_CHAT_MESSAGE_DELETE":     nil,                       //SC删除
+       "SUPER_CHAT_MESSAGE":            nil,                       //replyF.super_chat_message,//SC
+       "SUPER_CHAT_MESSAGE_JPN":        replyF.super_chat_message, //SC
+       "PANEL":                         nil,                       //replyF.panel,//排行榜 被HOT_RANK_CHANGED替代
+       "ENTRY_EFFECT":                  replyF.entry_effect,       //进入特效
+       "ROOM_REAL_TIME_MESSAGE_UPDATE": nil,                       //replyF.roominfo,//粉丝数
+       "WATCHED_CHANGE":                replyF.watched_change,     //Msg-观看人数
 }
 
 //屏蔽不需要的消息
-func init(){
-       {//加载不需要的消息
-               buf := s.New()
-               buf.Load("config/config_disable_msg.json")
-               for k,v := range buf.B {
-                       if able,ok := v.(bool);ok {//设置为true时,使用默认显示
+func init() {
+       { //加载不需要的消息
+               bb, err := ioutil.ReadFile("config/config_disable_msg.json")
+               if err != nil {
+                       return
+               }
+               var buf map[string]interface{}
+               json.Unmarshal(bb, &buf)
+               for k, v := range buf {
+                       if able, ok := v.(bool); ok { //设置为true时,使用默认显示
                                if able {
                                        Msg_map[k] = replyF.defaultMsg
                                } else {
@@ -110,18 +116,20 @@ func init(){
 func Msg(b []byte) {
 
        msglog := msglog.Base_add(`select func`)
-       var tmp struct{
+       var tmp struct {
                Cmd string `json:"cmd"`
        }
-       if e := json.Unmarshal(b, &tmp);e != nil {
-               msglog.L(`E: `,e)
+       if e := json.Unmarshal(b, &tmp); e != nil {
+               msglog.L(`E: `, e)
                return
        }
        if F, ok := Msg_map[tmp.Cmd]; ok {
-               if F != nil {F(replyF{}, string(b))}
+               if F != nil {
+                       F(replyF{}, string(b))
+               }
        } else {
                (replyF{}).defaultMsg(string(b))
        }
 
-       return 
+       return
 }
index f0092913b50126046bc6e25abb52d04d827f357d..3a2810c6319f45696341916e7d1d8ebf390051a2 100644 (file)
@@ -1,20 +1,20 @@
 package reply
 
 import (
-       "fmt"
-       "time"
        "bytes"
-       "strings"
-       "strconv"
        "compress/zlib"
        "encoding/json"
+       "fmt"
+       "strconv"
+       "strings"
+       "time"
 
-       p "github.com/qydysky/part"
-       mq "github.com/qydysky/part/msgq"
+       c "github.com/qydysky/bili_danmu/CV"
        F "github.com/qydysky/bili_danmu/F"
        ws_msg "github.com/qydysky/bili_danmu/Reply/ws_msg"
        send "github.com/qydysky/bili_danmu/Send"
-       c "github.com/qydysky/bili_danmu/CV"
+       p "github.com/qydysky/part"
+       mq "github.com/qydysky/part/msgq"
 )
 
 var reply_log = c.Log.Base(`Reply`)
@@ -25,32 +25,50 @@ var reply_log = c.Log.Base(`Reply`)
 func Reply(b []byte) {
        reply_log := reply_log.Base_add(`返回分派`)
 
-       if len(b) <= c.WS_PACKAGE_HEADER_TOTAL_LENGTH {reply_log.L(`W: `,"包缺损");return}
+       if len(b) <= c.WS_PACKAGE_HEADER_TOTAL_LENGTH {
+               reply_log.L(`W: `, "包缺损")
+               return
+       }
 
        head := F.HeadChe(b[:c.WS_PACKAGE_HEADER_TOTAL_LENGTH])
-       if int(head.PackL) > len(b) {reply_log.L(`E: `,"包缺损");return}
+       if int(head.PackL) > len(b) {
+               reply_log.L(`E: `, "首包缺损")
+               return
+       }
 
        if head.BodyV == c.WS_BODY_PROTOCOL_VERSION_DEFLATE {
                readc, err := zlib.NewReader(bytes.NewReader(b[16:]))
-               if err != nil {reply_log.L(`E: `,"解压错误");return}
+               if err != nil {
+                       reply_log.L(`E: `, "解压错误")
+                       return
+               }
                defer readc.Close()
-               
+
                buf := bytes.NewBuffer(nil)
-               if _, err := buf.ReadFrom(readc);err != nil {reply_log.L(`E: `,"解压错误");return}
+               if _, err := buf.ReadFrom(readc); err != nil {
+                       reply_log.L(`E: `, "解压错误")
+                       return
+               }
                b = buf.Bytes()
        }
 
        for len(b) != 0 {
                head := F.HeadChe(b[:c.WS_PACKAGE_HEADER_TOTAL_LENGTH])
-               if int(head.PackL) > len(b) {reply_log.L(`E: `,"包缺损");return}
-               
+               if int(head.PackL) > len(b) {
+                       reply_log.L(`E: `, "包缺损")
+                       return
+               }
+
                contain := b[c.WS_PACKAGE_HEADER_TOTAL_LENGTH:head.PackL]
                switch head.OpeaT {
                case c.WS_OP_MESSAGE:
                        Msg(contain)
-                       Save_to_json(-1, []interface{}{contain,`,`})
-               case c.WS_OP_HEARTBEAT_REPLY:Heart(contain)
-               default :reply_log.L(`W: `,"unknow reply", contain)
+                       Save_to_json(-1, []interface{}{contain, `,`})
+               case c.WS_OP_HEARTBEAT_REPLY: //心跳响应
+                       Heart(contain)
+                       return //忽略剩余内容
+               default:
+                       reply_log.L(`W: `, "unknow reply", contain)
                }
 
                b = b[head.PackL:]
@@ -59,123 +77,127 @@ func Reply(b []byte) {
 
 //所有的json对象处理子函数类
 //包含Msg和HeartBeat两大类
-type replyF struct {}
+type replyF struct{}
 
 //默认未识别Msg
-func (replyF) defaultMsg(s string){
+func (replyF) defaultMsg(s string) {
        msglog.Base_add("Unknow").L(`E: `, s)
 }
 
 //大乱斗pk开始
-func (replyF) pk_lottery_start(s string){
+func (replyF) pk_lottery_start(s string) {
        msglog := msglog.Base_add("大乱斗")
        var j ws_msg.PK_LOTTERY_START
-       if e := json.Unmarshal([]byte(s), &j);e != nil{
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
                return
        }
-       Gui_show(j.Data.Title,`0room`)
+       Gui_show(j.Data.Title, `0room`)
        msglog.L(`I: `, j.Data.Title)
 }
 
 //连麦人状态
-func (replyF) voice_join_status(s string){
+func (replyF) voice_join_status(s string) {
        msglog := msglog.Base_add("连麦")
        var j ws_msg.VOICE_JOIN_STATUS
-       if e := json.Unmarshal([]byte(s), &j);e != nil{
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
                return
        }
-       if j.Data.UserName == `` {return}
+       if j.Data.UserName == `` {
+               return
+       }
 
-       Gui_show(`连麦中:`+j.Data.UserName,`0room`)
+       Gui_show(`连麦中:`+j.Data.UserName, `0room`)
        msglog.L(`I: `, `连麦中:`, j.Data.UserName)
 }
 
 //连麦等待
-func (replyF) voice_join_room_count_info(s string){
+func (replyF) voice_join_room_count_info(s string) {
        msglog := msglog.Base_add("连麦")
        var j ws_msg.VOICE_JOIN_ROOM_COUNT_INFO
-       if e := json.Unmarshal([]byte(s), &j);e != nil{
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
                return
        }
-       Gui_show(`连麦等待:`+strconv.Itoa(j.Data.ApplyCount),`0room`)
+       Gui_show(`连麦等待:`+strconv.Itoa(j.Data.ApplyCount), `0room`)
        msglog.L(`I: `, `连麦等待人数`, j.Data.ApplyCount)
 }
 
 //大乱斗pk状态
-func (replyF) pk_battle_process_new(s string){
+func (replyF) pk_battle_process_new(s string) {
        msglog := msglog.Base_add("大乱斗")
        var j ws_msg.PK_BATTLE_PROCESS_NEW
-       if e := json.Unmarshal([]byte(s), &j);e != nil{
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
                return
        }
-       if diff := j.Data.InitInfo.Votes-j.Data.MatchInfo.Votes;diff<0 {
-               Gui_show(`大乱斗落后`,strconv.Itoa(diff),`0room`)
-               msglog.L(`I: `, `大乱斗落后`,diff)
+       if diff := j.Data.InitInfo.Votes - j.Data.MatchInfo.Votes; diff < 0 {
+               Gui_show(`大乱斗落后`, strconv.Itoa(diff), `0room`)
+               msglog.L(`I: `, `大乱斗落后`, diff)
        }
 }
 
 //msg-特别礼物
-func (replyF) vtr_gift_lottery(s string){
+func (replyF) vtr_gift_lottery(s string) {
        msglog := msglog.Base_add("特别礼物")
        var j ws_msg.VTR_GIFT_LOTTERY
-       if e := json.Unmarshal([]byte(s), &j);e != nil{
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
                return
        }
-       {//语言tts
-               c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{
-                       uid:`0room`,
-                       m:map[string]string{
-                               `{msg}`:j.Data.InteractMsg,
+       { //语言tts
+               c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{
+                       uid: `0room`,
+                       m: map[string]string{
+                               `{msg}`: j.Data.InteractMsg,
                        },
                })
        }
-       Gui_show(j.Data.InteractMsg,`0room`)
+       Gui_show(j.Data.InteractMsg, `0room`)
        msglog.L(`I: `, j.Data.InteractMsg)
 }
 
 //msg-直播间进入信息,此处用来提示关注
-func (replyF) interact_word(s string){
-       msg_type := p.Json().GetValFromS(s, "data.msg_type");
-       if v,ok := msg_type.(float64);!ok || v < 2 {return}//关注时为2,进入时为1
-       uname := p.Json().GetValFromS(s, "data.uname");
-       if v,ok := uname.(string);ok {
-               {//语言tts
-                       c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{
-                               uid:`0follow`,
-                               msg:fmt.Sprint(v + `关注了直播间`),
+func (replyF) interact_word(s string) {
+       msg_type := p.Json().GetValFromS(s, "data.msg_type")
+       if v, ok := msg_type.(float64); !ok || v < 2 {
+               return
+       } //关注时为2,进入时为1
+       uname := p.Json().GetValFromS(s, "data.uname")
+       if v, ok := uname.(string); ok {
+               { //语言tts
+                       c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{
+                               uid: `0follow`,
+                               msg: fmt.Sprint(v + `关注了直播间`),
                        })
                }
-               Gui_show(v + `关注了直播间`,`0follow`)
-               msglog.Base_add("房").Log_show_control(false).L(`I`, v + `关注了直播间`)
+               Gui_show(v+`关注了直播间`, `0follow`)
+               msglog.Base_add("房").Log_show_control(false).L(`I`, v+`关注了直播间`)
        }
 }
 
 //Msg-天选之人开始
-func (replyF) anchor_lot_start(s string){
-       award_name := p.Json().GetValFromS(s, "data.award_name");
+func (replyF) anchor_lot_start(s string) {
+       award_name := p.Json().GetValFromS(s, "data.award_name")
        var sh = []interface{}{">天选"}
        if award_name != nil {
                sh = append(sh, award_name, "开始")
        }
 
-       {//额外 ass
+       { //额外 ass
                Assf(fmt.Sprintln("天选之人", award_name, "开始"))
        }
        fmt.Println(sh...)
-       Gui_show(Itos(sh),`0tianxuan`)
+       Gui_show(Itos(sh), `0tianxuan`)
 
        msglog.Base_add("房").Log_show_control(false).L(`I`, sh...)
 }
 
 //Msg-天选之人结束
-func (replyF) anchor_lot_award(s string){
-       award_name := p.Json().GetValFromS(s, "data.award_name");
-       award_users := p.Json().GetValFromS(s, "data.award_users");
+func (replyF) anchor_lot_award(s string) {
+       award_name := p.Json().GetValFromS(s, "data.award_name")
+       award_users := p.Json().GetValFromS(s, "data.award_users")
 
        var sh = []interface{}{">天选"}
 
@@ -183,11 +205,11 @@ func (replyF) anchor_lot_award(s string){
                sh = append(sh, award_name, "获奖[")
        }
        if award_users != nil {
-               for _,v := range award_users.([]interface{}) {
-                       uname := p.Json().GetValFrom(v, "uname");
-                       uid := p.Json().GetValFrom(v, "uid");
+               for _, v := range award_users.([]interface{}) {
+                       uname := p.Json().GetValFrom(v, "uname")
+                       uid := p.Json().GetValFrom(v, "uid")
                        if uname != nil && uid != nil {
-                               if v,ok := uid.(float64);ok {//uid可能为float型
+                               if v, ok := uid.(float64); ok { //uid可能为float型
                                        sh = append(sh, uname, "(", strconv.Itoa(int(v)), ")")
                                } else {
                                        sh = append(sh, uname, "(", uid, ")")
@@ -196,21 +218,21 @@ func (replyF) anchor_lot_award(s string){
                }
        }
        sh = append(sh, "]")
-       {//额外 ass
+       { //额外 ass
                Assf(fmt.Sprintln("天选之人", award_name, "结束"))
        }
        fmt.Println(sh...)
-       Gui_show(Itos(sh),`0tianxuan`)
+       Gui_show(Itos(sh), `0tianxuan`)
 
        msglog.Base_add("房").Log_show_control(false).L(`I`, sh...)
 }
 
 //msg-通常是大航海购买续费
-func (replyF) user_toast_msg(s string){
+func (replyF) user_toast_msg(s string) {
        msglog := msglog.Base_add("礼")
 
        var j ws_msg.USER_TOAST_MSG
-       if e := json.Unmarshal([]byte(s), &j);e != nil{
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
                return
        }
@@ -255,35 +277,35 @@ func (replyF) user_toast_msg(s string){
                sh = append(sh, role_name)
        }
        if price != 0 {
-               sh_log = append(sh, "¥", price / 1000)//不在界面显示价格
-               c.Danmu_Main_mq.Push_tag(`c.Rev_add`,float64(price) / 1000)
-       }
-       {//语言tts
-               c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-                       uid:`0buyguide`,
-                       m:map[string]string{
-                               `{username}`:username,
-                               `{op_name}`:op_name,
-                               `{role_name}`:role_name,
-                               `{num}`:strconv.Itoa(num),
-                               `{unit}`:unit,
+               sh_log = append(sh, "¥", price/1000) //不在界面显示价格
+               c.Danmu_Main_mq.Push_tag(`c.Rev_add`, float64(price)/1000)
+       }
+       { //语言tts
+               c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+                       uid: `0buyguide`,
+                       m: map[string]string{
+                               `{username}`:  username,
+                               `{op_name}`:   op_name,
+                               `{role_name}`: role_name,
+                               `{num}`:       strconv.Itoa(num),
+                               `{unit}`:      unit,
                        },
                })
        }
-       {//额外 ass 私信
+       { //额外 ass 私信
                Assf(fmt.Sprintln(sh...))
-               c.Danmu_Main_mq.Push_tag(`guard_update`,nil)//使用连续付费的新舰长无法区分,刷新舰长数
+               c.Danmu_Main_mq.Push_tag(`guard_update`, nil) //使用连续付费的新舰长无法区分,刷新舰长数
                if uid != 0 {
-                       c.Danmu_Main_mq.Push_tag(`pm`,send.Pm_item{
-                               Uid:uid,
-                               Msg:c.K_v.LoadV(`上舰私信`).(string),
-                       })//上舰私信
+                       c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+                               Uid: uid,
+                               Msg: 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),
-                       })//上舰私信-对额外
+                       c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+                               Uid: int(c.K_v.LoadV(`额外私信对象`).(float64)),
+                               Msg: c.K_v.LoadV(`上舰私信(额外)`).(string),
+                       }) //上舰私信-对额外
                }
        }
        fmt.Println("\n====")
@@ -294,17 +316,20 @@ func (replyF) user_toast_msg(s string){
        Gui_show(Itos(sh), "0buyguide")
        // Gui_show("====\n")
 
-       msglog.Log_show_control(false).L(`I: `,sh_log...)
+       msglog.Log_show_control(false).L(`I: `, sh_log...)
 }
 
 //HeartBeat-心跳用来传递人气值
 var (
-       renqi_old int
+       renqi_old  int
        continuity int
 )
-func (replyF) heartbeat(s int){
-       c.Danmu_Main_mq.Push_tag(`c.Renqi`,s)//使用连续付费的新舰长无法区分,刷新舰长数
-       if s == 1 {return}//人气为1,不输出
+
+func (replyF) heartbeat(s int) {
+       c.Danmu_Main_mq.Push_tag(`c.Renqi`, s) //使用连续付费的新舰长无法区分,刷新舰长数
+       if s == 1 {
+               return
+       } //人气为1,不输出
        var (
                tmp string
        )
@@ -312,45 +337,53 @@ func (replyF) heartbeat(s int){
                if s > renqi_old {
                        tmp += `+`
                }
-               tmp += fmt.Sprintf("%.1f%%",100*float64(s - renqi_old)/float64(renqi_old))
+               tmp += fmt.Sprintf("%.1f%%", 100*float64(s-renqi_old)/float64(renqi_old))
                if s > renqi_old {
                        continuity += 1
                        if continuity > 2 {
-                               tmp = tmp+` 连续上升`+strconv.Itoa(continuity)
+                               tmp = tmp + ` 连续上升` + strconv.Itoa(continuity)
                        } else if continuity < 0 {
                                continuity = 1
                        }
                } else if s < renqi_old {
                        continuity -= 1
                        if continuity < -2 {
-                               tmp = tmp+` 连续下降`+strconv.Itoa(-continuity)
+                               tmp = tmp + ` 连续下降` + strconv.Itoa(-continuity)
                        } else if continuity > 0 {
                                continuity = -1
                        }
                }
-               tmp = `(`+tmp+`)`
+               tmp = `(` + tmp + `)`
        }
 
        if renqi_old != s {
                fmt.Printf("\t人气:%d %s\n", s, tmp)
        }
-       reply_log.Base_add(`人气`).Log_show_control(false).L(`I: `,"当前人气", s)
+       reply_log.Base_add(`人气`).Log_show_control(false).L(`I: `, "当前人气", s)
        renqi_old = s
 }
 
 //Msg-房间特殊活动
-func (replyF) win_activity(s string){
-       title := p.Json().GetValFromS(s, "data.title");
+func (replyF) win_activity(s string) {
+       title := p.Json().GetValFromS(s, "data.title")
 
        fmt.Println("活动", title, "已开启")
-       msglog.Base_add("房").Log_show_control(false).L(`I: `,"活动", title, "已开启")
+       msglog.Base_add("房").Log_show_control(false).L(`I: `, "活动", title, "已开启")
+}
+
+//Msg-观看人数
+func (replyF) watched_change(s string) {
+       var data ws_msg.WATCHED_CHANGE
+       json.Unmarshal([]byte(s), &data)
+       fmt.Printf("\t观看人数:%d\n", data.Data.Num)
+       msglog.Base_add("房").Log_show_control(false).L(`I: `, "观看人数", data.Data.Num)
 }
 
 //Msg-特殊礼物,当前仅观察到节奏风暴
-func (replyF) special_gift(s string){
-       
-       content := p.Json().GetValFromS(s, "data.39.content");
-       action := p.Json().GetValFromS(s, "data.39.action");
+func (replyF) special_gift(s string) {
+
+       content := p.Json().GetValFromS(s, "data.39.content")
+       action := p.Json().GetValFromS(s, "data.39.action")
 
        var sh []interface{}
 
@@ -360,7 +393,7 @@ func (replyF) special_gift(s string){
        if content != nil {
                sh = append(sh, "节奏风暴", content)
        }
-       {//额外
+       { //额外
                Assf(fmt.Sprintln(sh...))
        }
        fmt.Println("\n====")
@@ -376,10 +409,10 @@ func (replyF) special_gift(s string){
 }
 
 //Msg-大航海购买,由于信息少,用user_toast_msg进行替代
-func (replyF) guard_buy(s string){
-       username := p.Json().GetValFromS(s, "data.username");
-       gift_name := p.Json().GetValFromS(s, "data.gift_name");
-       price := p.Json().GetValFromS(s, "data.price");
+func (replyF) guard_buy(s string) {
+       username := p.Json().GetValFromS(s, "data.username")
+       gift_name := p.Json().GetValFromS(s, "data.gift_name")
+       price := p.Json().GetValFromS(s, "data.price")
 
        var sh []interface{}
        var sh_log []interface{}
@@ -391,9 +424,9 @@ func (replyF) guard_buy(s string){
                sh = append(sh, "购买了", gift_name)
        }
        if price != nil {
-               sh_log = append(sh, "¥", int(price.(float64)) / 1000)//不在界面显示价格
+               sh_log = append(sh, "¥", int(price.(float64))/1000) //不在界面显示价格
        }
-       {//额外 ass
+       { //额外 ass
                Assf(fmt.Sprintln(sh...))
        }
        fmt.Println("\n====")
@@ -404,11 +437,11 @@ func (replyF) guard_buy(s string){
 }
 
 //Msg-房间信息改变,标题等
-func (replyF) room_change(s string){
-       title := p.Json().GetValFromS(s, "data.title");
-       area_name := p.Json().GetValFromS(s, "data.area_name");
+func (replyF) room_change(s string) {
+       title := p.Json().GetValFromS(s, "data.title")
+       area_name := p.Json().GetValFromS(s, "data.area_name")
 
-       var sh  = []interface{}{"房间改变"}
+       var sh = []interface{}{"房间改变"}
 
        if title != nil {
                sh = append(sh, title)
@@ -423,7 +456,7 @@ func (replyF) room_change(s string){
 }
 
 //Msg-大航海欢迎信息 或已废弃
-func (replyF) welcome_guard(s string){
+func (replyF) welcome_guard(s string) {
        // username := p.Json().GetValFromS(s, "data.username");
        // guard_level := p.Json().GetValFromS(s, "data.guard_level");
        // img := "0default"
@@ -455,16 +488,18 @@ func (replyF) welcome_guard(s string){
 }
 
 //Msg-礼物处理
-func (replyF) send_gift(s string){
+func (replyF) send_gift(s string) {
        msglog := msglog.Base_add("礼").Log_show_control(false)
 
        var j ws_msg.SEND_GIFT
-       if e := json.Unmarshal([]byte(s), &j);e != nil {
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
        }
 
        //忽略银瓜子
-       if j.Data.CoinType ==  "silver" {return}
+       if j.Data.CoinType == "silver" {
+               return
+       }
 
        num := j.Data.Num
        uname := j.Data.Uname
@@ -483,34 +518,39 @@ func (replyF) send_gift(s string){
 
        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)
+               sh_log = append(sh, fmt.Sprintf("¥%.1f", allprice)) //不在界面显示价格
+               c.Danmu_Main_mq.Push_tag(`c.Rev_add`, allprice)
        }
 
-       if len(sh) == 0 {return}
+       if len(sh) == 0 {
+               return
+       }
 
        //小于设定
        {
                var tmp = 20.0
-               if v,ok := c.K_v.Load(`弹幕_礼物金额显示阈值`);ok {
+               if v, ok := c.K_v.Load(`弹幕_礼物金额显示阈值`); ok {
                        tmp = v.(float64)
                }
-               if allprice < tmp {msglog.L(`T: `, sh_log...);return}
-               msglog.L(`I: `, sh_log...);
+               if allprice < tmp {
+                       msglog.L(`T: `, sh_log...)
+                       return
+               }
+               msglog.L(`I: `, sh_log...)
        }
 
-       {//语言tts
-               c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-                       uid:`0gift`,
-                       m:map[string]string{
-                               `{num}`:strconv.Itoa(num),
-                               `{uname}`:uname,
-                               `{action}`:action,
-                               `{giftName}`:giftName,
+       { //语言tts
+               c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+                       uid: `0gift`,
+                       m: map[string]string{
+                               `{num}`:      strconv.Itoa(num),
+                               `{uname}`:    uname,
+                               `{action}`:   action,
+                               `{giftName}`: giftName,
                        },
                })
        }
-       {//额外
+       { //额外
                Assf(fmt.Sprintln(sh...))
        }
        fmt.Println("\n====")
@@ -524,7 +564,7 @@ func (replyF) send_gift(s string){
 
 //Msg-房间封禁信息
 func (replyF) room_block_msg(s string) {
-       if uname := p.Json().GetValFromS(s, "uname");uname == nil {
+       if uname := p.Json().GetValFromS(s, "uname"); uname == nil {
                msglog.L(`E: `, "uname", uname)
                return
        } else {
@@ -538,11 +578,11 @@ func (replyF) room_block_msg(s string) {
 func (replyF) preparing(s string) {
        msglog := msglog.Base_add("房")
 
-       if roomid := p.Json().GetValFromS(s, "roomid");roomid == nil {
+       if roomid := p.Json().GetValFromS(s, "roomid"); roomid == nil {
                msglog.L(`E: `, "roomid", roomid)
                return
        } else {
-               {//附加功能 obs结束 `savestream`结束
+               { //附加功能 obs结束 `savestream`结束
                        Obs_R(false)
                        Obsf(false)
                        Savestream_wait()
@@ -563,18 +603,18 @@ func (replyF) preparing(s string) {
 func (replyF) live(s string) {
        msglog := msglog.Base_add("房")
 
-       if roomid := p.Json().GetValFromS(s, "roomid");roomid == nil {
+       if roomid := p.Json().GetValFromS(s, "roomid"); roomid == nil {
                msglog.L(`E: `, "roomid", roomid)
                return
        } else {
-               {//附加功能 obs录播
+               { //附加功能 obs录播
                        Obsf(true)
                        Obs_R(true)
                        go Savestreamf()
                }
                {
-                       c.Rev = 0.0 //营收
-                       c.Liveing = true //直播i标志
+                       c.Rev = 0.0                    //营收
+                       c.Liveing = true               //直播i标志
                        c.Live_Start_Time = time.Now() //开播h时间
                }
                if p.Sys().Type(roomid) == "float64" {
@@ -589,22 +629,30 @@ func (replyF) live(s string) {
 
 //Msg-超级留言处理
 var sc_buf = make(map[string]struct{})
-func (replyF) super_chat_message(s string){
+
+func (replyF) super_chat_message(s string) {
        msglog := msglog.Base_add("礼")
 
        var j ws_msg.SUPER_CHAT_MESSAGE_JPN
-       if e := json.Unmarshal([]byte(s), &j);e != nil {
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
        }
 
        id := j.Data.ID
        if id != "" {
-               if _,ok := sc_buf[id];ok{return}
+               if _, ok := sc_buf[id]; ok {
+                       return
+               }
                if len(sc_buf) >= 10 {
-                       for k,_ := range sc_buf {delete(sc_buf, k);break}
-                       {//copy map
+                       for k, _ := range sc_buf {
+                               delete(sc_buf, k)
+                               break
+                       }
+                       { //copy map
                                tmp := make(map[string]struct{})
-                               for k,v := range sc_buf {tmp[k] = v}
+                               for k, v := range sc_buf {
+                                       tmp[k] = v
+                               }
                                sc_buf = tmp
                        }
                }
@@ -620,9 +668,9 @@ func (replyF) super_chat_message(s string){
        sh = append(sh, uname)
        logg := sh
        if price != 0 {
-               sh = append(sh, "\n")//界面不显示价格
+               sh = append(sh, "\n") //界面不显示价格
                logg = append(logg, "¥", price)
-               c.Danmu_Main_mq.Push_tag(`c.Rev_add`,float64(price))
+               c.Danmu_Main_mq.Push_tag(`c.Rev_add`, float64(price))
        }
        fmt.Println("====")
        fmt.Println(sh...)
@@ -633,14 +681,14 @@ func (replyF) super_chat_message(s string){
                sh = append(sh, message)
                logg = append(logg, message)
        }
-       {//语言tts
-               c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-                       uid:`0superchat`,
-                       m:map[string]string{
-                               `{uname}`:uname,
-                               `{price}`:strconv.Itoa(price),
-                               `{message}`:message,
-                               `{message_jpn}`:message_jpn,
+       { //语言tts
+               c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+                       uid: `0superchat`,
+                       m: map[string]string{
+                               `{uname}`:       uname,
+                               `{price}`:       strconv.Itoa(price),
+                               `{message}`:     message,
+                               `{message_jpn}`: message_jpn,
                        },
                })
        }
@@ -651,8 +699,8 @@ func (replyF) super_chat_message(s string){
                logg = append(logg, message_jpn)
        }
        fmt.Print("====\n\n")
-       
-       {//额外
+
+       { //额外
                Assf(fmt.Sprintln(sh...))
                // Gui_show("====\n")
                Gui_show(Itos(sh), "0superchat")
@@ -661,25 +709,27 @@ func (replyF) super_chat_message(s string){
 }
 
 //Msg-分区排行 使用热门榜替代
-func (replyF) panel(s string){
+func (replyF) panel(s string) {
        msglog := msglog.Base_add("房").Log_show_control(false)
 
-       if note := p.Json().GetValFromS(s, "data.note");note == nil {
+       if note := p.Json().GetValFromS(s, "data.note"); note == nil {
                msglog.L(`E: `, "note", note)
                return
        } else {
-               if v,ok := note.(string);ok{c.Note = v}
+               if v, ok := note.(string); ok {
+                       c.Note = v
+               }
                fmt.Println("排行", note)
                msglog.L(`I: `, "排行", note)
        }
 }
 
 //Msg-热门榜变动
-func (replyF) hot_rank_changed(s string){
+func (replyF) hot_rank_changed(s string) {
        msglog := msglog.Base_add("房").Log_show_control(false)
 
        var type_item ws_msg.HOT_RANK_CHANGED
-       if e := json.Unmarshal([]byte(s), &type_item);e != nil {
+       if e := json.Unmarshal([]byte(s), &type_item); e != nil {
                msglog.L(`E: `, e)
        }
        if type_item.Data.Area_name != `` {
@@ -695,11 +745,11 @@ func (replyF) hot_rank_changed(s string){
 }
 
 //Msg-热门榜获得
-func (replyF) hot_rank_settlement(s string){
+func (replyF) hot_rank_settlement(s string) {
        msglog := msglog.Base_add("房")
 
        var type_item ws_msg.HOT_RANK_SETTLEMENT
-       if e := json.Unmarshal([]byte(s), &type_item);e != nil {
+       if e := json.Unmarshal([]byte(s), &type_item); e != nil {
                msglog.L(`E: `, e)
        }
        var tmp = `获得:`
@@ -710,38 +760,38 @@ func (replyF) hot_rank_settlement(s string){
                tmp += strconv.Itoa(type_item.Data.Rank)
        }
        Gui_show(tmp, "0rank")
-       c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-               uid:"0rank",
-               m:map[string]string{
-                       `{Area_name}`:type_item.Data.Area_name,
-                       `{Rank}`:strconv.Itoa(type_item.Data.Rank),
+       c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+               uid: "0rank",
+               m: map[string]string{
+                       `{Area_name}`: type_item.Data.Area_name,
+                       `{Rank}`:      strconv.Itoa(type_item.Data.Rank),
                },
        })
        msglog.L(`I: `, "热门榜", tmp)
 }
 
 //Msg-小消息
-func (replyF) little_message_box(s string){
+func (replyF) little_message_box(s string) {
        msglog := msglog.Base_add("系统")
 
        var type_item ws_msg.LITTLE_MESSAGE_BOX
-       if e := json.Unmarshal([]byte(s), &type_item);e != nil {
+       if e := json.Unmarshal([]byte(s), &type_item); e != nil {
                msglog.L(`E: `, e)
        }
        if type_item.Data.Msg != `` {
                msglog.L(`I: `, type_item.Data.Msg)
-               if strings.Contains(type_item.Data.Msg,`小心心`) && strings.Contains(type_item.Data.Msg,`上限`) {
-                               F.F_x25Kn_cancel()
+               if strings.Contains(type_item.Data.Msg, `小心心`) && strings.Contains(type_item.Data.Msg, `上限`) {
+                       F.F_x25Kn_cancel()
                }
        }
 }
 
 //Msg-粉丝牌切换
-func (replyF) messagebox_user_medal_change(s string){
+func (replyF) messagebox_user_medal_change(s string) {
        msglog := msglog.Base_add("房")
 
        var type_item ws_msg.MESSAGEBOX_USER_MEDAL_CHANGE
-       if e := json.Unmarshal([]byte(s), &type_item);e != nil {
+       if e := json.Unmarshal([]byte(s), &type_item); e != nil {
                msglog.L(`E: `, e)
        }
        if type_item.Data.Medal_name != `` {
@@ -750,22 +800,22 @@ func (replyF) messagebox_user_medal_change(s string){
 }
 
 //Msg-进入特效
-func (replyF) entry_effect(s string){
+func (replyF) entry_effect(s string) {
 
-       var res struct{
-               Data struct{
+       var res struct {
+               Data struct {
                        Copy_writing string `json:"copy_writing"`
                } `json:"data"`
        }
-       if e := json.Unmarshal([]byte(s), &res);e != nil {
+       if e := json.Unmarshal([]byte(s), &res); e != nil {
                msglog.L(`E: `, e)
        }
-       
+
        var username string
        op := strings.Index(res.Data.Copy_writing, ` <%`)
        ed := strings.Index(res.Data.Copy_writing, `%> `)
        if op != -1 && ed != -1 {
-               username = res.Data.Copy_writing[op+3:ed]
+               username = res.Data.Copy_writing[op+3 : ed]
        }
        //处理特殊字符
        copy_writing := strings.ReplaceAll(res.Data.Copy_writing, `<%`, ``)
@@ -784,13 +834,13 @@ func (replyF) entry_effect(s string){
                img = "0level3"
        }
 
-       {//语言tts
-               c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-                       uid:img,
-                       m:map[string]string{
-                               `{guard_name}`:guard_name,
-                               `{username}`:username,
-                               `{msg}`:copy_writing,
+       { //语言tts
+               c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+                       uid: img,
+                       m: map[string]string{
+                               `{guard_name}`: guard_name,
+                               `{username}`:   username,
+                               `{msg}`:        copy_writing,
                        },
                })
        }
@@ -802,22 +852,24 @@ func (replyF) entry_effect(s string){
 }
 
 //Msg-房间禁言
-func (replyF) roomsilent(s string){
+func (replyF) roomsilent(s string) {
        msglog := msglog.Base_add("房")
 
-       if level := p.Json().GetValFromS(s, "data.level");level == nil {
+       if level := p.Json().GetValFromS(s, "data.level"); level == nil {
                msglog.L(`E: `, "level", level)
                return
        } else {
-               if level.(float64) == 0 {msglog.L(`I: `, "主播关闭了禁言")}
+               if level.(float64) == 0 {
+                       msglog.L(`I: `, "主播关闭了禁言")
+               }
                msglog.L(`I: `, "主播开启了等级禁言:", level)
        }
 }
 
 //Msg-粉丝信息,常刷屏,不显示
-func (replyF) roominfo(s string){
-       fans := p.Json().GetValFromS(s, "data.fans");
-       fans_club := p.Json().GetValFromS(s, "data.fans_club");
+func (replyF) roominfo(s string) {
+       fans := p.Json().GetValFromS(s, "data.fans")
+       fans_club := p.Json().GetValFromS(s, "data.fans_club")
 
        var sh []interface{}
 
@@ -828,35 +880,38 @@ func (replyF) roominfo(s string){
                sh = append(sh, "粉丝团人数:", fans_club)
        }
 
-       if len(sh) != 0 {msglog.Base_add("粉").L(`I: `, sh...)}
+       if len(sh) != 0 {
+               msglog.Base_add("粉").L(`I: `, sh...)
+       }
 }
 
 //Msg-弹幕处理
 type Danmu_item struct {
-       msg string
-       auth interface{}
-       uid string
-       roomid int//to avoid danmu show when room has changed
+       msg    string
+       auth   interface{}
+       uid    string
+       roomid int //to avoid danmu show when room has changed
 }
+
 func (replyF) danmu(s string) {
        var j struct {
                Cmd  string        `json:"cmd"`
                Info []interface{} `json:"info"`
        }
 
-       if e := json.Unmarshal([]byte(s), &j);e != nil {
+       if e := json.Unmarshal([]byte(s), &j); e != nil {
                msglog.L(`E: `, e)
        }
-       
+
        infob := j.Info
        item := Danmu_item{}
        {
                //解析
                if len(infob) > 0 {
-                       item.msg,_ = infob[1].(string)
+                       item.msg, _ = infob[1].(string)
                }
                if len(infob) > 1 {
-                       i,_ := infob[2].([]interface{})
+                       i, _ := infob[2].([]interface{})
                        if len(i) > 0 {
                                item.uid = strconv.Itoa(int(i[0].(float64)))
                        }
@@ -869,7 +924,7 @@ func (replyF) danmu(s string) {
 
        msglog := msglog.Log_show_control(false)
 
-       {//附加功能 弹幕机 封禁 弹幕合并
+       { //附加功能 弹幕机 封禁 弹幕合并
                go Danmujif(item.msg)
                if Autobanf(item.msg) {
                        Gui_show(Itos([]interface{}{"风险", item.auth, ":", item.msg}))
@@ -889,7 +944,9 @@ func (replyF) danmu(s string) {
                if _msg := Shortdanmuf(item.msg); _msg == "" {
                        msglog.L(`I: `, item.auth, ":", item.msg)
                        return
-               } else {item.msg = _msg}
+               } else {
+                       item.msg = _msg
+               }
        }
        Msg_showdanmu(item)
 }
@@ -897,13 +954,13 @@ func (replyF) danmu(s string) {
 //弹幕发送
 //传入字符串即可发送
 //需要cookie
-func Msg_senddanmu(msg string){
+func Msg_senddanmu(msg string) {
        if missKey := F.CookieCheck([]string{
                `bili_jct`,
                `DedeUserID`,
                `LIVE_BUVID`,
-       });len(missKey) != 0 || c.Roomid == 0 {
-               msglog.L(`E: `,`c.Roomid == 0 || Cookie无Key:`,missKey)
+       }); len(missKey) != 0 || c.Roomid == 0 {
+               msglog.L(`E: `, `c.Roomid == 0 || Cookie无Key:`, missKey)
                return
        }
        send.Danmu_s(msg, c.Roomid)
@@ -914,77 +971,89 @@ func Msg_senddanmu(msg string){
 func Msg_showdanmu(item Danmu_item) {
        msg := item.msg
        msglog := msglog.Log_show_control(false)
-       
+
        //room change
-       if item.roomid != 0 && item.roomid != c.Roomid {return}
-       
+       if item.roomid != 0 && item.roomid != c.Roomid {
+               return
+       }
+
        //展示
        {
-               Assf(msg)//ass
+               Assf(msg) //ass
                if item.auth != nil {
-                       Gui_show(fmt.Sprint(item.auth) +`: `+ msg, item.uid)
+                       Gui_show(fmt.Sprint(item.auth)+`: `+msg, item.uid)
                } else {
                        Gui_show(msg, item.uid)
                }
        }
-       {//语言tts 私信
+       { //语言tts 私信
                if item.uid != "" {
                        if item.auth != nil {
-                               c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
-                                       uid:item.uid,
-                                       m:map[string]string{
-                                               `{auth}`:fmt.Sprint(item.auth),
-                                               `{msg}`:msg,
+                               c.Danmu_Main_mq.Push_tag(`tts`, Danmu_mq_t{ //传入消息队列
+                                       uid: item.uid,
+                                       m: map[string]string{
+                                               `{auth}`: fmt.Sprint(item.auth),
+                                               `{msg}`:  msg,
                                        },
                                })
                        }
-                       if i,e := strconv.Atoi(item.uid);e == nil {
-                               c.Danmu_Main_mq.Push_tag(`pm`,send.Pm_item{
-                                       Uid:i,
-                                       Msg:c.K_v.LoadV(`弹幕私信`).(string),
-                               })//上舰私信
+                       if i, e := strconv.Atoi(item.uid); e == nil {
+                               c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+                                       Uid: i,
+                                       Msg: 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),
-                               })//上舰私信-对额外
+                               c.Danmu_Main_mq.Push_tag(`pm`, send.Pm_item{
+                                       Uid: int(c.K_v.LoadV(`额外私信对象`).(float64)),
+                                       Msg: c.K_v.LoadV(`弹幕私信(额外)`).(string),
+                               }) //上舰私信-对额外
                        }
                }
        }
        fmt.Println(msg)
-       if item.auth != nil {msglog.L(`I: `, item.auth, ":", msg)}
+       if item.auth != nil {
+               msglog.L(`I: `, item.auth, ":", msg)
+       }
 }
 
 type Danmu_mq_t struct {
        uid string
        msg string
-       m map[string]string//tts参数替换列表
+       m   map[string]string //tts参数替换列表
 }
+
 var Danmu_mq = mq.New(10)
 
-func Gui_show(m ...string){
+func Gui_show(m ...string) {
        //m[0]:msg m[1]:uid
        uid := ""
-       if len(m) > 1 {uid = m[1]}
+       if len(m) > 1 {
+               uid = m[1]
+       }
 
-       Danmu_mq.Push_tag(`danmu`,Danmu_mq_t{
-               uid:uid,
-               msg:m[0],
+       Danmu_mq.Push_tag(`danmu`, Danmu_mq_t{
+               uid: uid,
+               msg: m[0],
        })
 }
 
 func Itos(i []interface{}) string {
        r := ""
-       for _,v := range i {
+       for _, v := range i {
                switch v.(type) {
-               case string:r += v.(string)
-               case int:r += strconv.Itoa(v.(int))
-               case int64: r += strconv.Itoa(int(v.(int64)))
-               case float64: r+= strconv.Itoa(int(v.(float64)))
-               default:fmt.Println("unkonw type", v)
+               case string:
+                       r += v.(string)
+               case int:
+                       r += strconv.Itoa(v.(int))
+               case int64:
+                       r += strconv.Itoa(int(v.(int64)))
+               case float64:
+                       r += strconv.Itoa(int(v.(float64)))
+               default:
+                       fmt.Println("unkonw type", v)
                }
                r += " "
        }
        return r
-}
\ No newline at end of file
+}
index 60415a82495a7c913bbffb3b60c6b924ec2651a7..92b15825abc771b83bdaa05ab9184b17894aada5 100644 (file)
@@ -1,84 +1,87 @@
-//+build gtk
+//go:build gtk
+// +build gtk
 
 package reply
 
 import (
        "container/list"
        "errors"
+       "fmt"
+       "log"
+       "runtime"
        "strconv"
-       "time"
        "strings"
-       "log"
-       "fmt"
        "sync"
-       "runtime"
+       "time"
 
-       F "github.com/qydysky/bili_danmu/F"
        c "github.com/qydysky/bili_danmu/CV"
+       F "github.com/qydysky/bili_danmu/F"
 
        p "github.com/qydysky/part"
-       msgq "github.com/qydysky/part/msgq"
        s "github.com/qydysky/part/buf"
+       msgq "github.com/qydysky/part/msgq"
        reqf "github.com/qydysky/part/reqf"
 
+       "github.com/gotk3/gotk3/gdk"
        "github.com/gotk3/gotk3/glib"
        "github.com/gotk3/gotk3/gtk"
-       "github.com/gotk3/gotk3/gdk"
 )
 
 type danmu_item struct {
-       text *gtk.TextView
-       img *gtk.Image
+       text   *gtk.TextView
+       img    *gtk.Image
        handle glib.SignalHandle
 }
 type gtk_item_source struct {
        text string
-       img string
+       img  string
        time time.Time
 }
 
-var gtkGetList = make(chan string,100)
-var danmu_item_chan = make(chan danmu_item,100)
+var gtkGetList = make(chan string, 100)
+var danmu_item_chan = make(chan danmu_item, 100)
 
 var keep_key = map[string]int{
-       "face/0default":0,
-       "face/0room":0,
-       "face/0buyguide":9,
-       "face/0gift":8,
-       "face/0jiezou":8,
-       "face/0level1":5,
-       "face/0level2":3,
-       "face/0level3":1,
-       "face/0superchat":13,
-       "face/0tianxuan":5,
+       "face/0default":   0,
+       "face/0room":      0,
+       "face/0buyguide":  9,
+       "face/0gift":      8,
+       "face/0jiezou":    8,
+       "face/0level1":    5,
+       "face/0level2":    3,
+       "face/0level3":    1,
+       "face/0superchat": 13,
+       "face/0tianxuan":  5,
 }
 var (
-       Gtk_on bool
-       Gtk_img_path string = "face"
-       Gtk_danmu_chan = make(chan Danmu_mq_t,100)
+       Gtk_on         bool
+       Gtk_img_path   string = "face"
+       Gtk_danmu_chan        = make(chan Danmu_mq_t, 100)
 
-       imgbuf = struct{
+       imgbuf = struct {
                b map[string](*gdk.Pixbuf)
                sync.Mutex
        }{
-               b:make(map[string](*gdk.Pixbuf)),
+               b: make(map[string](*gdk.Pixbuf)),
        }
 
-       danmu_win_running bool//弹幕窗体是否正在运行
-       contrl_win_running bool//控制窗体是否正在运行
-       in_smooth_roll bool
-       grid0 *gtk.Grid
-       grid1 *gtk.Grid
-       keep_list = list.New()
+       danmu_win_running  bool //弹幕窗体是否正在运行
+       contrl_win_running bool //控制窗体是否正在运行
+       in_smooth_roll     bool
+       grid0              *gtk.Grid
+       grid1              *gtk.Grid
+       keep_list          = list.New()
 )
 
-func init(){
-       if!IsOn("Gtk弹幕窗") {return}
+func init() {
+       if !IsOn("Gtk弹幕窗") {
+               return
+       }
        go Gtk_danmu()
        //使用带tag的消息队列在功能间传递消息
        Danmu_mq.Pull_tag(msgq.FuncMap{
-               `danmu`:func(data interface{})(bool){//弹幕
-                       select{
+               `danmu`: func(data interface{}) bool { //弹幕
+                       select {
                        case Gtk_danmu_chan <- data.(Danmu_mq_t):
                        default:
                        }
@@ -86,12 +89,14 @@ func init(){
                },
        })
        //
-       go func(){//copy map
+       go func() { //copy map
                for {
-                       time.Sleep(time.Duration(60)*time.Second)
+                       time.Sleep(time.Duration(60) * time.Second)
                        {
                                tmp := make(map[string](*gdk.Pixbuf))
-                               for k,v := range imgbuf.b {tmp[k] = v}
+                               for k, v := range imgbuf.b {
+                                       tmp[k] = v
+                               }
                                imgbuf.Lock()
                                imgbuf.b = tmp
                                imgbuf.Unlock()
@@ -101,34 +106,44 @@ func init(){
 }
 
 func Gtk_danmu() {
-       if Gtk_on {return}
+       if Gtk_on {
+               return
+       }
        gtk.Init(nil)
 
        var (
-               scrolledwindow0 *gtk.ScrolledWindow
-               viewport0 *gtk.Viewport
-               w2_textView0 *gtk.TextView
-               w2_textView1 *gtk.TextView
-               w2_textView2 *gtk.TextView
-               w2_textView3 *gtk.TextView
-               w2_textView4 *gtk.TextView
-               w2_Entry0 *gtk.Entry
-               w2_Entry0_editting = make(chan bool,10)
+               scrolledwindow0    *gtk.ScrolledWindow
+               viewport0          *gtk.Viewport
+               w2_textView0       *gtk.TextView
+               w2_textView1       *gtk.TextView
+               w2_textView2       *gtk.TextView
+               w2_textView3       *gtk.TextView
+               w2_textView4       *gtk.TextView
+               w2_Entry0          *gtk.Entry
+               w2_Entry0_editting = make(chan bool, 10)
        )
 
-
        application, err := gtk.ApplicationNew(
-       "com.github.qydysky.bili_danmu.reply"+p.Sys().GetTime(),//时间戳允许多开
-       glib.APPLICATION_FLAGS_NONE)
+               "com.github.qydysky.bili_danmu.reply"+p.Sys().GetTime(), //时间戳允许多开
+               glib.APPLICATION_FLAGS_NONE)
 
-       if err != nil {log.Println(err);return}
+       if err != nil {
+               log.Println(err)
+               return
+       }
 
        application.Connect("startup", func() {
 
                builder, err := gtk.BuilderNewFromFile("ui/1.glade")
-               if err != nil {log.Println(err);return}
+               if err != nil {
+                       log.Println(err)
+                       return
+               }
                builder2, err := gtk.BuilderNewFromFile("ui/2.glade")
-               if err != nil {log.Println(err);return}
+               if err != nil {
+                       log.Println(err)
+                       return
+               }
 
                {
                        signals := map[string]interface{}{
@@ -138,177 +153,275 @@ func Gtk_danmu() {
                        builder2.ConnectSignals(signals)
                }
                var (
-                       win *gtk.Window
+                       win  *gtk.Window
                        win2 *gtk.Window
                )
                {
                        obj, err := builder.GetObject("main_window")
-                       if err != nil {log.Println(err);return}
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
                        win, err = isWindow(obj)
-                       if err != nil {log.Println(err);return}
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
                        danmu_win_running = true
                        win.Connect("delete-event", func() {
                                log.Println(`弹幕窗已关闭`)
-                               danmu_win_running = false//关闭后置空
+                               danmu_win_running = false //关闭后置空
                        })
                        application.AddWindow(win)
                }
                {
                        obj, err := builder2.GetObject("main_window")
-                       if err != nil {log.Println(err);return}
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
                        win2, err = isWindow(obj)
-                       if err != nil {log.Println(err);return}
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
                        contrl_win_running = true
                        win2.Connect("delete-event", func() {
                                log.Println(`弹幕信息窗已关闭`)
-                               contrl_win_running = false//关闭后置空
+                               contrl_win_running = false //关闭后置空
                        })
                        application.AddWindow(win2)
                }
-               {//营收
+               { //营收
                        obj, err := builder2.GetObject("t0")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.TextView); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.TextView); ok {
                                w2_textView0 = tmp
-                       }else{log.Println("cant find #t0 in .glade");return}
+                       } else {
+                               log.Println("cant find #t0 in .glade")
+                               return
+                       }
                }
-               {//直播时长
+               { //直播时长
                        obj, err := builder2.GetObject("t1")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.TextView); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.TextView); ok {
                                w2_textView1 = tmp
-                       }else{log.Println("cant find #t1 in .glade");return}
+                       } else {
+                               log.Println("cant find #t1 in .glade")
+                               return
+                       }
                }
-               {//人气值
+               { //人气值
                        obj, err := builder2.GetObject("t2")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.TextView); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.TextView); ok {
                                w2_textView2 = tmp
-                       }else{log.Println("cant find #t2 in .glade");return}
+                       } else {
+                               log.Println("cant find #t2 in .glade")
+                               return
+                       }
                }
-               {//舰长数
+               { //舰长数
                        obj, err := builder2.GetObject("t3")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.TextView); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.TextView); ok {
                                w2_textView3 = tmp
-                       }else{log.Println("cant find #t3 in .glade");return}
+                       } else {
+                               log.Println("cant find #t3 in .glade")
+                               return
+                       }
                }
-               {//排名
+               { //排名
                        obj, err := builder2.GetObject("t4")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.TextView); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.TextView); ok {
                                w2_textView4 = tmp
-                       }else{log.Println("cant find #t4 in .glade");return}
+                       } else {
+                               log.Println("cant find #t4 in .glade")
+                               return
+                       }
                }
-               {//发送弹幕
+               { //发送弹幕
                        var danmu_send_form string
-                       {//发送弹幕格式
+                       { //发送弹幕格式
                                obj, err := builder2.GetObject("send_danmu_form")
-                               if err != nil {log.Println(err);return}
-                               if tmp,ok := obj.(*gtk.Entry); ok {
+                               if err != nil {
+                                       log.Println(err)
+                                       return
+                               }
+                               if tmp, ok := obj.(*gtk.Entry); ok {
                                        tmp.Connect("focus-out-event", func() {
-                                               if t,e := tmp.GetText();e == nil {//可设置为空
+                                               if t, e := tmp.GetText(); e == nil { //可设置为空
                                                        danmu_send_form = t
-                                                       log.Println("弹幕格式已设置为",danmu_send_form)
+                                                       log.Println("弹幕格式已设置为", danmu_send_form)
                                                }
                                        })
-                               }else{log.Println("cant find #send_danmu in .glade");return}
+                               } else {
+                                       log.Println("cant find #send_danmu in .glade")
+                                       return
+                               }
                        }
                        obj, err := builder2.GetObject("send_danmu")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.Entry); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.Entry); ok {
                                tmp.Connect("key-release-event", func(entry *gtk.Entry, event *gdk.Event) {
                                        eventKey := gdk.EventKeyNewFromEvent(event)
                                        if eventKey.KeyVal() == gdk.KEY_Return {
-                                               if t,e := entry.GetText();e == nil && t != ``{
+                                               if t, e := entry.GetText(); e == nil && t != `` {
                                                        danmu_want_send := t
-                                                       if danmu_send_form != `` {danmu_want_send = strings.ReplaceAll(danmu_send_form, "{D}", t)}
+                                                       if danmu_send_form != `` {
+                                                               danmu_want_send = strings.ReplaceAll(danmu_send_form, "{D}", t)
+                                                       }
                                                        if len([]rune(danmu_want_send)) > 20 {
                                                                log.Println(`弹幕长度大于20,不做格式处理`)
                                                                danmu_want_send = t
-                                                       } 
+                                                       }
                                                        Msg_senddanmu(danmu_want_send)
                                                        entry.SetText(``)
                                                }
                                        }
                                })
-                       }else{log.Println("cant find #send_danmu in .glade");return}
+                       } else {
+                               log.Println("cant find #send_danmu in .glade")
+                               return
+                       }
                }
-               {//房间id
+               { //房间id
                        obj, err := builder2.GetObject("want_room_id")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.Entry); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.Entry); ok {
                                w2_Entry0 = tmp
                                tmp.Connect("focus-out-event", func() {
-                                       glib.TimeoutAdd(uint(3000), func()bool{//3s后才解除,避免刚想切换又变回去
-                                               for len(w2_Entry0_editting) != 0 {<-w2_Entry0_editting}
+                                       glib.TimeoutAdd(uint(3000), func() bool { //3s后才解除,避免刚想切换又变回去
+                                               for len(w2_Entry0_editting) != 0 {
+                                                       <-w2_Entry0_editting
+                                               }
                                                w2_Entry0_editting <- false
                                                return false
                                        })
                                })
-                       }else{log.Println("cant find #want_room_id in .glade");return}
+                       } else {
+                               log.Println("cant find #want_room_id in .glade")
+                               return
+                       }
                }
-               {//房间id click
+               { //房间id click
                        obj, err := builder2.GetObject("want_click")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.Button); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.Button); ok {
                                tmp.Connect("clicked", func() {
-                                       if t,e := w2_Entry0.GetText();e != nil {
-                                               show("读取错误",load_face("0room"))
+                                       if t, e := w2_Entry0.GetText(); e != nil {
+                                               show("读取错误", load_face("0room"))
                                        } else if t != `` {
-                                               if i,e := strconv.Atoi(t);e != nil {
-                                                       show(`输入错误`,load_face("0room"))
+                                               if i, e := strconv.Atoi(t); e != nil {
+                                                       show(`输入错误`, load_face("0room"))
                                                } else {
-                                                       c.Roomid =  i
-                                                       c.Danmu_Main_mq.Push_tag(`change_room`,nil)
+                                                       c.Roomid = i
+                                                       c.Danmu_Main_mq.Push_tag(`change_room`, nil)
                                                }
                                        } else {
-                                               show(`房间号输入为空`,load_face("0room"))
+                                               show(`房间号输入为空`, load_face("0room"))
                                        }
                                })
-                       }else{log.Println("cant find #want_click in .glade");return}
+                       } else {
+                               log.Println("cant find #want_click in .glade")
+                               return
+                       }
                }
                {
                        obj, err := builder.GetObject("scrolledwindow0")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.ScrolledWindow); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.ScrolledWindow); ok {
                                scrolledwindow0 = tmp
-                       }else{log.Println("cant find #scrolledwindow0 in .glade");return}
+                       } else {
+                               log.Println("cant find #scrolledwindow0 in .glade")
+                               return
+                       }
                }
 
                {
                        obj, err := builder.GetObject("viewport0")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.Viewport); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.Viewport); ok {
                                viewport0 = tmp
-                       }else{log.Println("cant find #viewport0 in .glade");return}
+                       } else {
+                               log.Println("cant find #viewport0 in .glade")
+                               return
+                       }
                }
                {
                        obj, err := builder.GetObject("grid0")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.Grid); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.Grid); ok {
                                grid0 = tmp
-                       }else{log.Println("cant find #grid0 in .glade");return}
+                       } else {
+                               log.Println("cant find #grid0 in .glade")
+                               return
+                       }
                }
                {
                        obj, err := builder.GetObject("grid1")
-                       if err != nil {log.Println(err);return}
-                       if tmp,ok := obj.(*gtk.Grid); ok {
+                       if err != nil {
+                               log.Println(err)
+                               return
+                       }
+                       if tmp, ok := obj.(*gtk.Grid); ok {
                                grid1 = tmp
-                       }else{log.Println("cant find #grid1 in .glade");return}
+                       } else {
+                               log.Println("cant find #grid1 in .glade")
+                               return
+                       }
                }
                imgbuf.Lock()
-               imgbuf.b["face/0default"],_ = gdk.PixbufNewFromFileAtSize("face/0default", 40, 40);
+               imgbuf.b["face/0default"], _ = gdk.PixbufNewFromFileAtSize("face/0default", 40, 40)
                imgbuf.Unlock()
 
                {
-                       if pro_style,e := gtk.CssProviderNew();e == nil{
-                               if e = pro_style.LoadFromPath(`ui/1.css`);e == nil{
-                                       if scr := win.GetScreen();scr != nil {
-                                               gtk.AddProviderForScreen(scr,pro_style,gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
+                       if pro_style, e := gtk.CssProviderNew(); e == nil {
+                               if e = pro_style.LoadFromPath(`ui/1.css`); e == nil {
+                                       if scr := win.GetScreen(); scr != nil {
+                                               gtk.AddProviderForScreen(scr, pro_style, gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
                                        }
-                               }else{log.Println(e)}
-                       }else{log.Println(e)}
+                               } else {
+                                       log.Println(e)
+                               }
+                       } else {
+                               log.Println(e)
+                       }
                }
 
                //先展示弹幕窗
@@ -320,57 +433,65 @@ func Gtk_danmu() {
 
        application.Connect("activate", func() {
 
-               go func(){
-                       glib.TimeoutAdd(uint(1000),func()(bool){
-                               if !danmu_win_running {return false}
+               go func() {
+                       glib.TimeoutAdd(uint(1000), func() bool {
+                               if !danmu_win_running {
+                                       return false
+                               }
                                el := keep_list.Front()
                                for el != nil && time.Now().After(el.Value.(gtk_item_source).time) {
                                        if grid1.Container.GetChildren().Length() > 0 {
                                                grid1.RemoveRow(0)
                                        }
-                                       show(el.Value.(gtk_item_source).text,el.Value.(gtk_item_source).img, 0)
+                                       show(el.Value.(gtk_item_source).text, el.Value.(gtk_item_source).img, 0)
                                        keep_list.Remove(el)
                                        el = el.Next()
                                }
                                return true
                        })
                        for danmu_win_running {
-                               select{
-                               case item := <- Gtk_danmu_chan:
-                                       show(item.msg,load_face(item.uid))
+                               select {
+                               case item := <-Gtk_danmu_chan:
+                                       show(item.msg, load_face(item.uid))
                                default:
                                }
-                               time.Sleep(time.Second/time.Duration(len(Gtk_danmu_chan)+1))
+                               time.Sleep(time.Second / time.Duration(len(Gtk_danmu_chan)+1))
                        }
                }()
                var old_cu float64
-               {//平滑滚动效果
-                       glib.TimeoutAdd(uint(30),func()(bool){
-                               if !danmu_win_running {return false}
-                               if !in_smooth_roll {return true}
+               { //平滑滚动效果
+                       glib.TimeoutAdd(uint(30), func() bool {
+                               if !danmu_win_running {
+                                       return false
+                               }
+                               if !in_smooth_roll {
+                                       return true
+                               }
                                h := viewport0.GetViewWindow().WindowGetHeight()
                                tmp := scrolledwindow0.GetVAdjustment()
                                max := tmp.GetUpper() - float64(h)
                                cu := tmp.GetValue()
-                               
+
                                //用户在回看
-                               if old_cu != 0 &&//非初始
-                               max - cu > 100 &&//当前位置低于100
-                               old_cu != cu {//上一次滚动有移动
+                               if old_cu != 0 && //非初始
+                                       max-cu > 100 && //当前位置低于100
+                                       old_cu != cu { //上一次滚动有移动
                                        return true
                                }
-                               
-                               loc := int(grid0.Container.GetChildren().Length())/2
+
+                               loc := int(grid0.Container.GetChildren().Length()) / 2
                                step := (max - cu) / 30
-                               if loc > 0 && step > 20 || max > 5 * float64(h){//太长或太快
+                               if loc > 0 && step > 20 || max > 5*float64(h) { //太长或太快
                                        grid0.RemoveRow(0)
                                } else if step > 0.5 {
-                                       if step > 5{step = 5}
+                                       if step > 5 {
+                                               step = 5
+                                       }
                                        tmp.SetValue(cu + step)
                                } else {
                                        in_smooth_roll = false
                                        tmp.SetValue(max)
-                                       if v,ok := c.K_v.LoadV(`gtk_保留弹幕数量`).(float64);ok {
+                                       if v, ok := c.K_v.LoadV(`gtk_保留弹幕数量`).(float64); ok {
                                                loc -= int(v)
                                        } else {
                                                loc -= 25
@@ -385,37 +506,51 @@ func Gtk_danmu() {
                        })
                }
                var renqi_old = 1
-               glib.TimeoutAdd(uint(3000), func()(o bool){
+               glib.TimeoutAdd(uint(3000), func() (o bool) {
                        o = contrl_win_running
                        //y("sssss",load_face(""))
-                       {//加载特定信息驻留时长
+                       { //加载特定信息驻留时长
                                buf := s.New()
                                buf.Load("config/config_gtk_keep_key.json")
-                               for k,_ := range keep_key {delete(keep_key,k)}
-                               for k,v := range buf.B {
+                               for k, _ := range keep_key {
+                                       delete(keep_key, k)
+                               }
+                               for k, v := range buf.B {
                                        keep_key[k] = int(v.(float64))
                                }
                        }
-                       {//营收
+                       { //营收
                                if IsOn("统计营收") {
-                                       b,e := w2_textView0.GetBuffer()
-                                       if e != nil {log.Println(e);return}
-                                       b.SetText(fmt.Sprintf("¥%.2f",c.Rev))                                 
+                                       b, e := w2_textView0.GetBuffer()
+                                       if e != nil {
+                                               log.Println(e)
+                                               return
+                                       }
+                                       b.SetText(fmt.Sprintf("¥%.2f", c.Rev))
                                }
                        }
-                       {//舰长
-                               b,e := w2_textView3.GetBuffer()
-                               if e != nil {log.Println(e);return}
-                               b.SetText(fmt.Sprintf("%d",c.GuardNum))
+                       { //舰长
+                               b, e := w2_textView3.GetBuffer()
+                               if e != nil {
+                                       log.Println(e)
+                                       return
+                               }
+                               b.SetText(fmt.Sprintf("%d", c.GuardNum))
                        }
-                       {//分区排行
-                               b,e := w2_textView4.GetBuffer()
-                               if e != nil {log.Println(e);return}
+                       { //分区排行
+                               b, e := w2_textView4.GetBuffer()
+                               if e != nil {
+                                       log.Println(e)
+                                       return
+                               }
                                b.SetText(c.Note)
                        }
-                       {//时长
-                               b,e := w2_textView1.GetBuffer()
-                               if e != nil {log.Println(e);return}
+                       { //时长
+                               b, e := w2_textView1.GetBuffer()
+                               if e != nil {
+                                       log.Println(e)
+                                       return
+                               }
                                if c.Liveing {
                                        d := time.Since(c.Live_Start_Time).Round(time.Second)
                                        h := d / time.Hour
@@ -428,24 +563,31 @@ func Gtk_danmu() {
                                        b.SetText("00:00:00")
                                }
                        }
-                       {//人气
-                               b,e := w2_textView2.GetBuffer()
-                               if e != nil {log.Println(e);return}
+                       { //人气
+                               b, e := w2_textView2.GetBuffer()
+                               if e != nil {
+                                       log.Println(e)
+                                       return
+                               }
                                if c.Liveing {
                                        if c.Renqi != renqi_old {
                                                var Renqi string = strconv.Itoa(c.Renqi)
-                                               L:=len([]rune(Renqi))
+                                               L := len([]rune(Renqi))
 
                                                var tmp string
                                                if renqi_old != 1 {
-                                                       if c.Renqi > renqi_old {tmp += `+`}
-                                                       tmp += fmt.Sprintf("%.1f",100*float64(c.Renqi - renqi_old)/float64(renqi_old)) + `% | `
+                                                       if c.Renqi > renqi_old {
+                                                               tmp += `+`
+                                                       }
+                                                       tmp += fmt.Sprintf("%.1f", 100*float64(c.Renqi-renqi_old)/float64(renqi_old)) + `% | `
+                                               }
+                                               if c.Renqi != 0 {
+                                                       renqi_old = c.Renqi
                                                }
-                                               if c.Renqi != 0 {renqi_old = c.Renqi}
 
-                                               for k,v := range []rune(Renqi) {
+                                               for k, v := range []rune(Renqi) {
                                                        tmp += string(v)
-                                                       if (L - k)%3 == 1 && L - k != 1{
+                                                       if (L-k)%3 == 1 && L-k != 1 {
                                                                tmp += `,`
                                                        }
                                                }
@@ -455,10 +597,12 @@ func Gtk_danmu() {
                                        b.SetText(`0`)
                                }
                        }
-                       {//房间id
-                               for len(w2_Entry0_editting) > 1 {<-w2_Entry0_editting}
-                               select{
-                               case tmp:=<-w2_Entry0_editting:
+                       { //房间id
+                               for len(w2_Entry0_editting) > 1 {
+                                       <-w2_Entry0_editting
+                               }
+                               select {
+                               case tmp := <-w2_Entry0_editting:
                                        if !tmp {
                                                w2_Entry0.SetText(strconv.Itoa(c.Roomid))
                                        }
@@ -466,18 +610,24 @@ func Gtk_danmu() {
                                }
                        }
                        select {
-                       case uid:=<-gtkGetList:
-                               go func(){
-                                       if p.Checkfile().IsExist(Gtk_img_path + `/` + uid) {return}
+                       case uid := <-gtkGetList:
+                               go func() {
+                                       if p.Checkfile().IsExist(Gtk_img_path + `/` + uid) {
+                                               return
+                                       }
                                        src := F.Get_face_src(uid)
-                                       if src == "" {return}
+                                       if src == "" {
+                                               return
+                                       }
                                        req := reqf.New()
                                        if e := req.Reqf(reqf.Rval{
-                                               Url:src,
-                                               SaveToPath:Gtk_img_path + `/` + uid,
-                                               Timeout:3*1000,
-                                               Proxy:c.Proxy,
-                                       }); e != nil{log.Println(e);}
+                                               Url:        src,
+                                               SaveToPath: Gtk_img_path + `/` + uid,
+                                               Timeout:    3 * 1000,
+                                               Proxy:      c.Proxy,
+                                       }); e != nil {
+                                               log.Println(e)
+                                       }
                                }()
                        default:
                        }
@@ -486,9 +636,9 @@ func Gtk_danmu() {
        })
 
        application.Connect("shutdown", func() {
-               log.Println("application shutdown")     
+               log.Println("application shutdown")
                Gtk_on = false
-               c.Danmu_Main_mq.Push_tag(`gtk_close`,nil)
+               c.Danmu_Main_mq.Push_tag(`gtk_close`, nil)
        })
 
        application.Run(nil)
@@ -507,141 +657,158 @@ func onMainWindowDestroy() {
 
 func load_face(uid string) (loc string) {
        loc = Gtk_img_path + `/` + "0default"
-       if uid == "" {return}
-       if _,ok := keep_key[Gtk_img_path + `/` + uid];ok{
+       if uid == "" {
+               return
+       }
+       if _, ok := keep_key[Gtk_img_path+`/`+uid]; ok {
                loc = Gtk_img_path + `/` + uid
                return
        }
-       if p.Checkfile().IsExist(Gtk_img_path + `/` + uid) && p.Rand().MixRandom(1,100) > 1 {
+       if p.Checkfile().IsExist(Gtk_img_path+`/`+uid) && p.Rand().MixRandom(1, 100) > 1 {
                loc = Gtk_img_path + `/` + uid
                return
        }
-       if v,ok := c.K_v.LoadV(`gtk_头像获取等待最大数量`).(float64);ok && len(gtkGetList) > int(v) {return}
-       select{
-               case gtkGetList <- uid:
-               default:
+       if v, ok := c.K_v.LoadV(`gtk_头像获取等待最大数量`).(float64); ok && len(gtkGetList) > int(v) {
+               return
+       }
+       select {
+       case gtkGetList <- uid:
+       default:
        }
        return
 }
 
-func show(s,img_src string,to_grid ...int){
-       if s == `` || img_src == `` {return}
-       glib.TimeoutAdd(uint(1),func()(r bool){
-       r = false
+func show(s, img_src string, to_grid ...int) {
+       if s == `` || img_src == `` {
+               return
+       }
+       glib.TimeoutAdd(uint(1), func() (r bool) {
+               r = false
 
-       sec := 0
+               sec := 0
 
-       var item danmu_item
-       // runtime.SetFinalizer(&item,func(p *danmu_item){p = nil;fmt.Print(`i `)})
+               var item danmu_item
+               // runtime.SetFinalizer(&item,func(p *danmu_item){p = nil;fmt.Print(`i `)})
 
-       item.text,_ = gtk.TextViewNew()
-       // runtime.SetFinalizer(item.text,func(p *gtk.TextView){p = nil;fmt.Print(`t `)})
-       {
-               item.text.SetMarginStart(5)
-               item.text.SetEditable(false)
-               item.text.SetHExpand(true)
-               item.text.SetWrapMode(gtk.WRAP_WORD_CHAR)
-               if tsec,ok := keep_key[img_src];ok && tsec != 0 {
-                       sec = tsec
-                       if sty,e := item.text.GetStyleContext();e == nil{
-                               sty.AddClass("highlight")
+               item.text, _ = gtk.TextViewNew()
+               // runtime.SetFinalizer(item.text,func(p *gtk.TextView){p = nil;fmt.Print(`t `)})
+               {
+                       item.text.SetMarginStart(5)
+                       item.text.SetEditable(false)
+                       item.text.SetHExpand(true)
+                       item.text.SetWrapMode(gtk.WRAP_WORD_CHAR)
+                       if tsec, ok := keep_key[img_src]; ok && tsec != 0 {
+                               sec = tsec
+                               if sty, e := item.text.GetStyleContext(); e == nil {
+                                       sty.AddClass("highlight")
+                               }
                        }
+                       item.handle = item.text.Connect("size-allocate", func(text *gtk.TextView) {
+                               if text == nil {
+                                       return
+                               }
+                               b, e := text.GetBuffer()
+                               if e != nil {
+                                       log.Println(e)
+                                       return
+                               }
+                               b.SetText(s)
+                               in_smooth_roll = true
+                       })
                }
-               item.handle = item.text.Connect("size-allocate", func(text *gtk.TextView){
-                       if text == nil {return}
-                       b,e := text.GetBuffer()
-                       if e != nil {log.Println(e);return}
-                       b.SetText(s)
-                       in_smooth_roll = true
-               })
-       }
 
-       item.img,_ = gtk.ImageNew();
-       // runtime.SetFinalizer(item.img,func(p *gtk.Image){p = nil;fmt.Print(`I `)})
-       {
-               var (
-                       pixbuf *gdk.Pixbuf
-                       e error
-               )
-               if v,ok := imgbuf.b[img_src];ok{
-                       pixbuf,e = gdk.PixbufCopy(v)
-               } else {
-                       pixbuf,e = gdk.PixbufNewFromFileAtSize(img_src, 40, 40);
-                       if e == nil {
-                               imgbuf.Lock()
-                               if v,ok := c.K_v.LoadV(`gtk_内存头像数量`).(float64);ok && len(imgbuf.b) > int(v) + 10 {
-                                       for k,_ := range imgbuf.b {
-                                               delete(imgbuf.b,k)
-                                               if len(imgbuf.b) <= int(v) {break}
+               item.img, _ = gtk.ImageNew()
+               // runtime.SetFinalizer(item.img,func(p *gtk.Image){p = nil;fmt.Print(`I `)})
+               {
+                       var (
+                               pixbuf *gdk.Pixbuf
+                               e      error
+                       )
+                       if v, ok := imgbuf.b[img_src]; ok {
+                               pixbuf, e = gdk.PixbufCopy(v)
+                       } else {
+                               pixbuf, e = gdk.PixbufNewFromFileAtSize(img_src, 40, 40)
+                               if e == nil {
+                                       imgbuf.Lock()
+                                       if v, ok := c.K_v.LoadV(`gtk_内存头像数量`).(float64); ok && len(imgbuf.b) > int(v)+10 {
+                                               for k, _ := range imgbuf.b {
+                                                       delete(imgbuf.b, k)
+                                                       if len(imgbuf.b) <= int(v) {
+                                                               break
+                                                       }
+                                               }
                                        }
+                                       imgbuf.b[img_src], e = gdk.PixbufCopy(pixbuf)
+                                       imgbuf.Unlock()
                                }
-                               imgbuf.b[img_src],e = gdk.PixbufCopy(pixbuf)
-                               imgbuf.Unlock()
+                       }
+                       if e == nil {
+                               item.img.SetFromPixbuf(pixbuf)
                        }
                }
-               if e == nil {item.img.SetFromPixbuf(pixbuf)}
-       }
 
-       select {
-       case danmu_item_chan <- item:
-       default:
-               old :=<- danmu_item_chan
-               old.text.Destroy()
-               old.img.Destroy()
-               runtime.GC()
-               danmu_item_chan <- item
-       }
-       
-
-       {
-               if len(to_grid) != 0 && to_grid[0] == 0 {//突出显示结束后,显示在普通弹幕区
-                       loc := int(grid0.Container.GetChildren().Length())/2;
-                       grid0.InsertRow(loc);
-                       grid0.Attach(item.img, 0, loc, 1, 1)
-                       grid0.Attach(item.text, 1, loc, 1, 1)
-                       grid0.ShowAll()
-                       return
+               select {
+               case danmu_item_chan <- item:
+               default:
+                       old := <-danmu_item_chan
+                       old.text.Destroy()
+                       old.img.Destroy()
+                       runtime.GC()
+                       danmu_item_chan <- item
                }
-               /*
-                       front
-                       |
-                       back index:0
-               */
-               var InsertIndex int = keep_list.Len()
-               if sec > InsertIndex / 5 {//5不是指最大值,而是当list太大时,sec小的将直接跳过
-                       var cu_To = time.Now().Add(time.Second * time.Duration(sec))
-                       var hasInsert bool
-                       for el := keep_list.Front(); el != nil; el = el.Next(){
-                               if cu_To.After(el.Value.(gtk_item_source).time) {InsertIndex -= 1;continue}
-                               keep_list.InsertBefore(gtk_item_source{
-                                       text:s,
-                                       img:img_src,
-                                       time:cu_To,
-                               },el)
-                               hasInsert = true
-                               break
-                       }
-                       if !hasInsert {
-                               keep_list.PushBack(gtk_item_source{
-                                       text:s,
-                                       img:img_src,
-                                       time:cu_To,
-                               })
+
+               {
+                       if len(to_grid) != 0 && to_grid[0] == 0 { //突出显示结束后,显示在普通弹幕区
+                               loc := int(grid0.Container.GetChildren().Length()) / 2
+                               grid0.InsertRow(loc)
+                               grid0.Attach(item.img, 0, loc, 1, 1)
+                               grid0.Attach(item.text, 1, loc, 1, 1)
+                               grid0.ShowAll()
+                               return
                        }
-                       loc := int(grid1.Container.GetChildren().Length())/2;
-                       grid1.InsertRow(loc - InsertIndex);
-                       grid1.Attach(item.img, 0, loc - InsertIndex, 1, 1)
-                       grid1.Attach(item.text, 1, loc - InsertIndex, 1, 1)
-                       grid1.ShowAll()
-               } else {
-                       loc := int(grid0.Container.GetChildren().Length())/2;
-                       grid0.InsertRow(loc);
-                       grid0.Attach(item.img, 0, loc, 1, 1)
-                       grid0.Attach(item.text, 1, loc, 1, 1)
-                       grid0.ShowAll()
+                       /*
+                               front
+                               |
+                               back index:0
+                       */
+                       var InsertIndex int = keep_list.Len()
+                       if sec > InsertIndex/5 { //5不是指最大值,而是当list太大时,sec小的将直接跳过
+                               var cu_To = time.Now().Add(time.Second * time.Duration(sec))
+                               var hasInsert bool
+                               for el := keep_list.Front(); el != nil; el = el.Next() {
+                                       if cu_To.After(el.Value.(gtk_item_source).time) {
+                                               InsertIndex -= 1
+                                               continue
+                                       }
+                                       keep_list.InsertBefore(gtk_item_source{
+                                               text: s,
+                                               img:  img_src,
+                                               time: cu_To,
+                                       }, el)
+                                       hasInsert = true
+                                       break
+                               }
+                               if !hasInsert {
+                                       keep_list.PushBack(gtk_item_source{
+                                               text: s,
+                                               img:  img_src,
+                                               time: cu_To,
+                                       })
+                               }
+                               loc := int(grid1.Container.GetChildren().Length()) / 2
+                               grid1.InsertRow(loc - InsertIndex)
+                               grid1.Attach(item.img, 0, loc-InsertIndex, 1, 1)
+                               grid1.Attach(item.text, 1, loc-InsertIndex, 1, 1)
+                               grid1.ShowAll()
+                       } else {
+                               loc := int(grid0.Container.GetChildren().Length()) / 2
+                               grid0.InsertRow(loc)
+                               grid0.Attach(item.img, 0, loc, 1, 1)
+                               grid0.Attach(item.text, 1, loc, 1, 1)
+                               grid0.ShowAll()
+                       }
+                       return
                }
-               return
-       }
        })
 }
 
@@ -668,8 +835,8 @@ item.handle,_ = item.text.Connect("size-allocate", func(){
 })
 */
 /*
-    同时太多ToWidget().Destroy()将会卡死gtk
+   同时太多ToWidget().Destroy()将会卡死gtk
 */
 /*
        gotk3存在内存泄漏,发生在C
-*/
\ No newline at end of file
+*/
index 4498bb21c8765507a7caffc468f420f229b9b83e..18331d487eee100c876df7672e6725a095e538dc 100644 (file)
@@ -1,88 +1,93 @@
 package reply
 
 import (
-       "fmt"
-       "time"
-       "errors"
+       "crypto/hmac"
        "crypto/sha256"
-       "os/exec"
-       "net/url"
-       "strings"
        "encoding/base64"
        "encoding/json"
-       "crypto/hmac"
+       "errors"
+       "fmt"
+       "io/ioutil"
+       "net/url"
+       "os/exec"
+       "strings"
+       "time"
+
        c "github.com/qydysky/bili_danmu/CV"
 
        p "github.com/qydysky/part"
+       funcCtrl "github.com/qydysky/part/funcCtrl"
+       limit "github.com/qydysky/part/limit"
        msgq "github.com/qydysky/part/msgq"
-       ws "github.com/qydysky/part/websocket"
-       s "github.com/qydysky/part/buf"
        reqf "github.com/qydysky/part/reqf"
-       limit "github.com/qydysky/part/limit"
-       funcCtrl "github.com/qydysky/part/funcCtrl"
+       ws "github.com/qydysky/part/websocket"
 )
 
 var (
        tts_setting_string = map[string]string{
-               "0buyguide":"感谢{D}",
-               "0gift":"感谢{D}",
-               "0superchat":"感谢{D}",
+               "0buyguide":  "感谢{D}",
+               "0gift":      "感谢{D}",
+               "0superchat": "感谢{D}",
        }
        tts_setting_replace = map[string]string{
-               "\n":" ",
+               "\n": " ",
        }
 )
-var tts_List = make(chan string,20)
+var tts_List = make(chan string, 20)
 
-var tts_limit = limit.New(1,5000,15000)//频率限制1次/5s,最大等待时间15s
+var tts_limit = limit.New(1, 5000, 15000) //频率限制1次/5s,最大等待时间15s
 
 var tts_log = c.Log.Base_add(`TTS`)
 
 var (
-       tts_ser = "baidu"
-       tts_ser_map = map[string]func(string)error{
-               `baidu`:baidu,
-               `youdao`:youdao,
-               `xf`:xf,
+       tts_ser     = "baidu"
+       tts_ser_map = map[string]func(string) error{
+               `baidu`:  baidu,
+               `youdao`: youdao,
+               `xf`:     xf,
        }
-       tts_prog = "ffplay"
+       tts_prog     = "ffplay"
        tts_prog_set = "-autoexit -nodisp"
 )
 
-func init(){
-       {//tts配置
+func init() {
+       { //tts配置
 
-               if v, ok := c.K_v.LoadV(`TTS_总开关`).(bool);ok && !v {
+               if v, ok := c.K_v.LoadV(`TTS_总开关`).(bool); ok && !v {
                        return
                }
-               if v, ok := c.K_v.LoadV(`TTS_使用程序路径`).(string);ok && v != ``{
+               if v, ok := c.K_v.LoadV(`TTS_使用程序路径`).(string); ok && v != `` {
                        tts_prog = v
                } else {
-                       tts_log.L(`E: `,`TTS_使用程序路径不是字符串或为空`)
+                       tts_log.L(`E: `, `TTS_使用程序路径不是字符串或为空`)
                }
-               if v, ok := c.K_v.LoadV(`TTS_使用程序参数`).(string);ok && v != ``{
+               if v, ok := c.K_v.LoadV(`TTS_使用程序参数`).(string); ok && v != `` {
                        tts_prog_set = v
                } else {
-                       tts_log.L(`E: `,`TTS_使用程序参数不是字符串`)
+                       tts_log.L(`E: `, `TTS_使用程序参数不是字符串`)
                }
-               if v, ok := c.K_v.LoadV(`TTS_服务器`).(string);ok && v != "" {
-                       if _,ok := tts_ser_map[v];ok{
+               if v, ok := c.K_v.LoadV(`TTS_服务器`).(string); ok && v != "" {
+                       if _, ok := tts_ser_map[v]; ok {
                                tts_ser = v
                        } else {
-                               tts_log.L(`I: `,`未支持设定服务提供商,使用baidu`)
+                               tts_log.L(`I: `, `未支持设定服务提供商,使用baidu`)
                                tts_ser = `baidu`
                        }
                }
-               
-               buf := s.New()
-               buf.Load("config/config_tts.json")
-               if onoff,ok := buf.Get(`onoff`);ok {
-                       for k,v := range onoff.(map[string]interface{}) {
+
+               bb, err := ioutil.ReadFile("config/config_tts.json")
+               if err != nil {
+                       return
+               }
+               var buf map[string]interface{}
+               json.Unmarshal(bb, &buf)
+               if onoff, ok := buf[`onoff`]; ok {
+                       for k, v := range onoff.(map[string]interface{}) {
                                tts_setting_string[k] = v.(string)
                        }
                }
-               if replace,ok := buf.Get(`replace`);ok {
-                       for k,v := range replace.(map[string]interface{}) {
+               if replace, ok := buf[`replace`]; ok {
+                       for k, v := range replace.(map[string]interface{}) {
                                tts_setting_replace[k] = v.(string)
                        }
                }
@@ -90,38 +95,45 @@ func init(){
        //启动程序
        p.Exec().Start(exec.Command(tts_prog))
 
-       go func(){
-               for{
-                       s := <- tts_List
+       go func() {
+               for {
+                       s := <-tts_List
                        for len(tts_List) > 0 && len(s) < 100 {
-                               s += " " + <- tts_List
+                               s += " " + <-tts_List
                        }
                        TTS(s)
                }
        }()
-       
+
        //消息队列接收tts类消息,并传送到TTS朗读
        //使用带tag的消息队列在功能间传递消息
        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 != "" {
-                               
-                               for k,v := range d.m {
+               `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 != "" {
+
+                               for k, v := range d.m {
                                        s = strings.ReplaceAll(s, k, v)
                                }
-                               for k,v := range tts_setting_replace {
+                               for k, v := range tts_setting_replace {
                                        s = strings.ReplaceAll(s, k, v)
                                }
                                var (
-                                       skip bool
+                                       skip  bool
                                        runel []rune
                                )
-                               for _,v := range s {
-                                       if v == []rune("{")[0] {skip = true}
-                                       if v == []rune("}")[0] {skip = false;continue}
-                                       if skip {continue}
-                                       runel = append(runel,v)
+                               for _, v := range s {
+                                       if v == []rune("{")[0] {
+                                               skip = true
+                                       }
+                                       if v == []rune("}")[0] {
+                                               skip = false
+                                               continue
+                                       }
+                                       if skip {
+                                               continue
+                                       }
+                                       runel = append(runel, v)
                                }
 
                                tts_log.L(`I: `, d.uid, string(runel))
@@ -129,11 +141,12 @@ func init(){
                        }
                        return false
                },
-               `change_room`:func(data interface{})(bool){
+               `change_room`: func(data interface{}) bool {
                        for {
                                select {
-                               case <- tts_List:;
-                               default:return false;
+                               case <-tts_List:
+                               default:
+                                       return false
                                }
                        }
                        return false
@@ -141,29 +154,30 @@ func init(){
        })
 }
 
-
 func TTS(msg string) {
-       if tts_limit.TO() {return}
+       if tts_limit.TO() {
+               return
+       }
 
        var err error
-       if f,ok := tts_ser_map[tts_ser];ok{
+       if f, ok := tts_ser_map[tts_ser]; ok {
                err = f(msg)
        } else {
                err = baidu(msg)
        }
-       
+
        if err != nil {
                tts_log.L(`E: `, err)
                return
        }
-       
+
        return
 }
 
-func play(){
+func play() {
        var prog = []string{}
        prog = append(prog, p.Sys().Cdir()+"/tts.mp3")
-       prog = append(prog, strings.Split(tts_prog_set," ")...)
+       prog = append(prog, strings.Split(tts_prog_set, " ")...)
        p.Exec().Run(false, tts_prog, prog...)
 
 }
@@ -171,13 +185,13 @@ func play(){
 func baidu(msg string) error {
        req := reqf.New()
        if err := req.Reqf(reqf.Rval{
-               Url:`https://fanyi.baidu.com/gettts?lan=zh&text=`+ url.PathEscape(msg) +`&spd=5&source=web`,
-               SaveToPath:p.Sys().Cdir()+`/tts.mp3`,
-               Timeout:3*1000,
-               Retry:1,
-               SleepTime:5000,
-               Proxy:c.Proxy,
-       });err != nil {
+               Url:        `https://fanyi.baidu.com/gettts?lan=zh&text=` + url.PathEscape(msg) + `&spd=5&source=web`,
+               SaveToPath: p.Sys().Cdir() + `/tts.mp3`,
+               Timeout:    3 * 1000,
+               Retry:      1,
+               SleepTime:  5000,
+               Proxy:      c.Proxy,
+       }); err != nil {
                return err
        }
        play()
@@ -185,14 +199,15 @@ func baidu(msg string) error {
 }
 
 var (
-       youdaoId string
+       youdaoId     string
        youdaoappKey string
 )
-func init(){
-       if v, ok := c.K_v.LoadV(`TTS_服务器_youdaoId`).(string);ok && v != ``{
+
+func init() {
+       if v, ok := 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.K_v.LoadV(`TTS_服务器_youdaoKey`).(string); ok && v != `` {
                youdaoappKey = v
        }
        if tts_ser == `youdao` && (youdaoId == `` || youdaoappKey == ``) {
@@ -208,29 +223,31 @@ func youdao(msg string) error {
        //https://ai.youdao.com/gw.s#/
        var (
                api = map[string]string{
-                       `q`:msg,
-                       `langType`:"zh-CHS",
-                       `youdaoappKey`:youdaoId,
-                       `salt`:p.Stringf().Rand(1, 8),
+                       `q`:            msg,
+                       `langType`:     "zh-CHS",
+                       `youdaoappKey`: youdaoId,
+                       `salt`:         p.Stringf().Rand(1, 8),
                }
                postS string
        )
-       api[`sign`] = strings.ToUpper(p.Md5().Md5String(api[`youdaoappKey`]+api[`q`]+api[`salt`]+youdaoappKey))
-       for k,v := range api {
-               if postS != "" {postS += "&"}
-               postS += k+`=`+v
+       api[`sign`] = strings.ToUpper(p.Md5().Md5String(api[`youdaoappKey`] + api[`q`] + api[`salt`] + youdaoappKey))
+       for k, v := range api {
+               if postS != "" {
+                       postS += "&"
+               }
+               postS += k + `=` + v
        }
 
        req := reqf.New()
        if err := req.Reqf(reqf.Rval{
-               Url:`https://openapi.youdao.com/ttsapi`,
-               PostStr:url.PathEscape(postS),
-               SaveToPath:p.Sys().Cdir()+`/tts.mp3`,
-               Timeout:3*1000,
-               Retry:1,
-               SleepTime:5000,
-               Proxy:c.Proxy,
-       });err != nil {
+               Url:        `https://openapi.youdao.com/ttsapi`,
+               PostStr:    url.PathEscape(postS),
+               SaveToPath: p.Sys().Cdir() + `/tts.mp3`,
+               Timeout:    3 * 1000,
+               Retry:      1,
+               SleepTime:  5000,
+               Proxy:      c.Proxy,
+       }); err != nil {
                return err
        }
        if req.Response.Header.Get(`Content-type`) == `application/json` {
@@ -241,41 +258,44 @@ func youdao(msg string) error {
 }
 
 var (
-       xfId string
-       xfKey string
+       xfId     string
+       xfKey    string
        xfSecret string
-       xfVoice = "random"
-       xfVmap = map[string]bool{
-               `xiaoyan`:true,
-               `aisjiuxu`:true,
-               `aisxping`:true,
-               `aisjinger`:true,
-               `aisbabyxu`:true,
+       xfVoice  = "random"
+       xfVmap   = map[string]bool{
+               `xiaoyan`:   true,
+               `aisjiuxu`:  true,
+               `aisxping`:  true,
+               `aisjinger`: true,
+               `aisbabyxu`: true,
        }
-       xfwsClient *ws.Client
-       xf_req func()
+       xfwsClient   *ws.Client
+       xf_req       func()
        xf_req_block funcCtrl.BlockFunc
 )
-func init(){
-       if v, ok := c.K_v.LoadV(`TTS_服务器_xfId`).(string);ok && v != ``{
+
+func init() {
+       if v, ok := 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.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.K_v.LoadV(`TTS_服务器_xfSecret`).(string); ok && v != `` {
                xfSecret = v
        }
-       if v, ok := c.K_v.LoadV(`TTS_服务器_xfVoice`).(string);ok && v != ``{
-               if _,ok := xfVmap[v];ok || v == `random` {
+       if v, ok := c.K_v.LoadV(`TTS_服务器_xfVoice`).(string); ok && v != `` {
+               if _, ok := xfVmap[v]; ok || v == `random` {
                        xfVoice = v
                } else {
-                       tts_log.L(`I: `,`未支持设定发音,使用随机`)
+                       tts_log.L(`I: `, `未支持设定发音,使用随机`)
                }
        }
 
        //      设置了非讯飞tts
-       if tts_ser != `xf` {return}
+       if tts_ser != `xf` {
+               return
+       }
 
        if xfId == `` || xfKey == `` || xfSecret == `` {
                tts_log.L(`W: `, `未提供讯飞Id、Key、Secret,使用baidu`)
@@ -284,37 +304,37 @@ func init(){
        }
 
        //@hosturl :  like  wss://tts-api.xfyun.cn/v2/tts
-    //@apikey : apiKey
-    //@apiSecret : apiSecret
-       assembleAuthUrl := func (hosturl string, apiKey, apiSecret string) (string,error) {
-        ul, err := url.Parse(hosturl)
-        if err != nil {
-            return "",err
-        }
-        //签名时间
-        date := time.Now().UTC().Format(time.RFC1123)
-        //参与签名的字段 host ,date, request-line
-        signString := []string{"host: " + ul.Host, "date: " + date, "GET " + ul.Path + " HTTP/1.1"}
-        //拼接签名字符串
-        sgin := strings.Join(signString, "\n")
-        //签名
+       //@apikey : apiKey
+       //@apiSecret : apiSecret
+       assembleAuthUrl := func(hosturl string, apiKey, apiSecret string) (string, error) {
+               ul, err := url.Parse(hosturl)
+               if err != nil {
+                       return "", err
+               }
+               //签名时间
+               date := time.Now().UTC().Format(time.RFC1123)
+               //参与签名的字段 host ,date, request-line
+               signString := []string{"host: " + ul.Host, "date: " + date, "GET " + ul.Path + " HTTP/1.1"}
+               //拼接签名字符串
+               sgin := strings.Join(signString, "\n")
+               //签名
                mac := hmac.New(sha256.New, []byte(apiSecret))
                mac.Write([]byte(sgin))
-        sha := base64.StdEncoding.EncodeToString(mac.Sum(nil))
-        //构建请求参数 此时不需要urlencoding
-        authUrl := fmt.Sprintf("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha)
-        //将请求参数使用base64编码
-        authorization:= base64.StdEncoding.EncodeToString([]byte(authUrl))
-        v := url.Values{}
-        v.Add("host", ul.Host)
-        v.Add("date", date)
-        v.Add("authorization", authorization)
-        //将编码后的字符串url encode后添加到url后面
-        callurl := hosturl + "?" + v.Encode()
-        return callurl,nil
-    }
-
-       wsUrl,err := assembleAuthUrl("wss://tts-api.xfyun.cn/v2/tts", xfKey, xfSecret)
+               sha := base64.StdEncoding.EncodeToString(mac.Sum(nil))
+               //构建请求参数 此时不需要urlencoding
+               authUrl := fmt.Sprintf("api_key=\"%s\",algorithm=\"%s\",headers=\"%s\",signature=\"%s\"", apiKey, "hmac-sha256", "host date request-line", sha)
+               //将请求参数使用base64编码
+               authorization := base64.StdEncoding.EncodeToString([]byte(authUrl))
+               v := url.Values{}
+               v.Add("host", ul.Host)
+               v.Add("date", date)
+               v.Add("authorization", authorization)
+               //将编码后的字符串url encode后添加到url后面
+               callurl := hosturl + "?" + v.Encode()
+               return callurl, nil
+       }
+
+       wsUrl, err := assembleAuthUrl("wss://tts-api.xfyun.cn/v2/tts", xfKey, xfSecret)
 
        if err != nil {
                tts_log.L(`E: `, `错误,使用百度`, err)
@@ -322,30 +342,32 @@ func init(){
                return
        }
 
-       xf_req = func(){
-               xf_req_block.Block()//cant call in same time
+       xf_req = func() {
+               xf_req_block.Block() //cant call in same time
                defer xf_req_block.UnBlock()
 
                xfwsClient = ws.New_client(ws.Client{
-                       Url:wsUrl,
-                       Proxy:c.Proxy,
+                       Url:   wsUrl,
+                       Proxy: c.Proxy,
                        Header: map[string]string{
-                               `User-Agent`: `Mozilla/5.0 (X11; Linux x86_64; rv:84.0) Gecko/20100101 Firefox/84.0`,
-                               `Accept`: `*/*`,
+                               `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`,
-                               `Pragma`: `no-cache`,
-                               `Cache-Control`: `no-cache`,
+                               `Pragma`:          `no-cache`,
+                               `Cache-Control`:   `no-cache`,
                        },
                }).Handle()
                if xfwsClient.Isclose() {
-                       tts_log.L(`E: `,"连接错误,使用百度", xfwsClient.Error())
+                       tts_log.L(`E: `, "连接错误,使用百度", xfwsClient.Error())
                        tts_ser = `baidu`
                } else {
-                       go func(){
+                       go func() {
                                var buf []byte
                                for !xfwsClient.Isclose() {
-                                       data := <- xfwsClient.RecvChan
-                                       if len(data) == 0 {break}
+                                       data := <-xfwsClient.RecvChan
+                                       if len(data) == 0 {
+                                               break
+                                       }
 
                                        var partS struct {
                                                Code    int    `json:"code"`
@@ -357,18 +379,18 @@ func init(){
                                                        Status int    `json:"status"`
                                                } `json:"data"`
                                        }
-                                       if e := json.Unmarshal(data, &partS);e != nil {
-                                               tts_log.L(`E: `,"错误", e, data)
+                                       if e := json.Unmarshal(data, &partS); e != nil {
+                                               tts_log.L(`E: `, "错误", e, data)
                                                xfwsClient.Close()
                                                return
                                        } else {
                                                if partS.Code != 0 {
-                                                       tts_log.L(`W: `,fmt.Sprintf("code:%d msg:%s", partS.Code, partS.Message))
+                                                       tts_log.L(`W: `, fmt.Sprintf("code:%d msg:%s", partS.Code, partS.Message))
                                                        break
                                                }
                                                if partS.Data.Audio != "" {
-                                                       if part,e := base64.StdEncoding.DecodeString(partS.Data.Audio);e != nil {
-                                                               tts_log.L(`E: `,"错误", e)
+                                                       if part, e := base64.StdEncoding.DecodeString(partS.Data.Audio); e != nil {
+                                                               tts_log.L(`E: `, "错误", e)
                                                                break
                                                        } else {
                                                                buf = append(buf, part...)
@@ -381,27 +403,27 @@ func init(){
                                }
                                if len(buf) != 0 {
                                        p.File().FileWR(p.Filel{
-                                               File:p.Sys().Cdir()+`/tts.mp3`,
-                                               Context:[]interface{}{buf},
+                                               File:    p.Sys().Cdir() + `/tts.mp3`,
+                                               Context: []interface{}{buf},
                                        })
                                        play()
                                }
                                xfwsClient.Close()
                        }()
                }
-               
+
        }
        xf_req()
 }
 func xf(msg string) error {
        if xfId == `` || xfKey == `` || xfSecret == `` {
-               tts_log.L(`T: `,"参数不足,使用百度")
+               tts_log.L(`T: `, "参数不足,使用百度")
                return baidu(msg)
        }
 
        voice := xfVoice
        if voice == `random` {
-               for k,_ := range xfVmap {
+               for k, _ := range xfVmap {
                        voice = k
                        break
                }
@@ -412,10 +434,10 @@ func xf(msg string) error {
                        AppID string `json:"app_id"`
                } `json:"common"`
                Business struct {
-                       Aue   string `json:"aue"`
-                       Vcn   string `json:"vcn"`
-                       Tte   string `json:"tte"`
-                       Sfl   int `json:"sfl"`
+                       Aue string `json:"aue"`
+                       Vcn string `json:"vcn"`
+                       Tte string `json:"tte"`
+                       Sfl int    `json:"sfl"`
                } `json:"business"`
                Data struct {
                        Status int    `json:"status"`
@@ -423,7 +445,7 @@ func xf(msg string) error {
                } `json:"data"`
        }
 
-       {//msg
+       { //msg
                var postS = rec{}
                postS.Common.AppID = xfId
                postS.Business.Aue = "lame"
@@ -432,8 +454,8 @@ func xf(msg string) error {
                postS.Business.Vcn = voice
                postS.Data.Status = 2
                postS.Data.Text = base64.StdEncoding.EncodeToString([]byte(msg))
-       
-               if b,e := json.Marshal(postS);e != nil {
+
+               if b, e := json.Marshal(postS); e != nil {
                        return e
                } else {
                        if xfwsClient.Isclose() {
@@ -443,4 +465,4 @@ func xf(msg string) error {
                }
        }
        return nil
-}
\ No newline at end of file
+}
diff --git a/Reply/ws_msg/WATCHED_CHANGE.go b/Reply/ws_msg/WATCHED_CHANGE.go
new file mode 100644 (file)
index 0000000..5d5efe8
--- /dev/null
@@ -0,0 +1,11 @@
+package part
+
+type WATCHED_CHANGE struct {
+       Cmd  string              `json:"cmd"`
+       Data WATCHED_CHANGE_Data `json:"data"`
+}
+type WATCHED_CHANGE_Data struct {
+       Num       int    `json:"num"`
+       TextSmall string `json:"text_small"`
+       TextLarge string `json:"text_large"`
+}
index 2c16db5fbe6a7448bf76aeb34679dfb74e1af74a..5eed855b0dc6acb62b521429186ddd5de6496faa 100644 (file)
@@ -14,7 +14,7 @@ require (
        github.com/miekg/dns v1.1.42 // indirect
        github.com/mitchellh/mapstructure v1.4.1 // indirect
        github.com/qydysky/bili_danmu v0.5.9
-       github.com/qydysky/part v0.5.26 // indirect
+       github.com/qydysky/part v0.6.0 // indirect
        github.com/shirou/gopsutil v3.21.5+incompatible // indirect
        github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
        github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
index 3e22fe35f1c39e2d4098f925a1182801cacc4442..439d9d47790d4696af7109cd2fc2163440b3462c 100644 (file)
@@ -316,6 +316,8 @@ github.com/qydysky/part v0.5.25 h1:jDxxwml175gc9pcyuMGdlAX1ErLk5CWKv58Jr1UWdy4=
 github.com/qydysky/part v0.5.25/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
 github.com/qydysky/part v0.5.26 h1:h2rwwgE4o0CgkPKNHxWVFqFIzDcv+tj4vp3o97YmjLs=
 github.com/qydysky/part v0.5.26/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
+github.com/qydysky/part v0.6.0 h1:4Akc4E7+rAbbcGwtpKTGZrnKn/hayIWj/AgTR8FhFjA=
+github.com/qydysky/part v0.6.0/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
 github.com/qydysky/part/msgq v0.0.0-20201213031129-ca3253dc72ad h1:Jtzf509lQrkUMGTV0Sc6IDCAiR1VrBcHrIban7hpye4=
 github.com/qydysky/part/msgq v0.0.0-20201213031129-ca3253dc72ad/go.mod h1:w32TkJNVtTJd4LOS09cq+4uYG6itcN2vsqw+slp44Rg=
 github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba h1:1ew9dRpc0Rux0WkWeT/4AE15ynYWmL2D7onJEJIFOB8=
diff --git a/go.mod b/go.mod
index f218f48993ea6df336218b958fd03bcb1b6ed765..fc9234eb61e68cb2a7f4ea7fe762ce7e1315087b 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -12,7 +12,7 @@ require (
        github.com/mdp/qrterminal/v3 v3.0.0
        github.com/miekg/dns v1.1.42 // indirect
        github.com/mitchellh/mapstructure v1.4.1 // indirect
-       github.com/qydysky/part v0.5.26
+       github.com/qydysky/part v0.6.0
        github.com/shirou/gopsutil v3.21.5+incompatible // indirect
        github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
        github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
diff --git a/go.sum b/go.sum
index 8a9602c4a06615a35d8591a7ea38a991b6fbd2fd..74e1bf11e81c9f7755afafaa2e52b1aed9604805 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -90,6 +90,8 @@ github.com/qydysky/part v0.5.25 h1:jDxxwml175gc9pcyuMGdlAX1ErLk5CWKv58Jr1UWdy4=
 github.com/qydysky/part v0.5.25/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
 github.com/qydysky/part v0.5.26 h1:h2rwwgE4o0CgkPKNHxWVFqFIzDcv+tj4vp3o97YmjLs=
 github.com/qydysky/part v0.5.26/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
+github.com/qydysky/part v0.6.0 h1:4Akc4E7+rAbbcGwtpKTGZrnKn/hayIWj/AgTR8FhFjA=
+github.com/qydysky/part v0.6.0/go.mod h1:43opuciW71sZvOR67kye50jgMDSDrn/t6+LefNdlXPg=
 github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba h1:1ew9dRpc0Rux0WkWeT/4AE15ynYWmL2D7onJEJIFOB8=
 github.com/qydysky/part/msgq v0.0.0-20201213120821-f36e49c32bba/go.mod h1:w32TkJNVtTJd4LOS09cq+4uYG6itcN2vsqw+slp44Rg=
 github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=