]> 127.0.0.1 Git - bili_danmu/.git/commitdiff
Add 配置项 服务器时区
authorqydysky <qydysky@foxmail.com>
Sun, 7 Jul 2024 08:55:45 +0000 (08:55 +0000)
committerqydysky <qydysky@foxmail.com>
Sun, 7 Jul 2024 08:55:45 +0000 (08:55 +0000)
CV/Var.go
F/CookieCrypo.go
F/api.go
F/biliApiInterface.go
Reply/gtk.go
bili_danmu.go
cmd/cmd.go
demo/config/config_K_v.json
go.mod
go.sum

index 438abd41bbd31d6d218990c49f8b41f45327466e..9ac13f0a1f16c1b84f942fa401f8c08e4ebb0a3d 100644 (file)
--- a/CV/Var.go
+++ b/CV/Var.go
@@ -71,6 +71,7 @@ type Common struct {
        LiveBuvidUpdated  time.Time      `json:"-"`             //LIVE_BUVID更新时间
        Stream_url        *url.URL       `json:"-"`             //直播Web服务
        Proxy             string         `json:"-"`             //全局代理
+       SerLocation       int            `json:"-"`             //服务器时区
        AcceptQn          map[int]string `json:"-"`             //允许的直播流质量
        Qn                map[int]string `json:"-"`             //全部直播流质量
        // StreamType        StreamType            `json:"streamType"`    //当前直播流类型
@@ -183,6 +184,7 @@ func (t *Common) Copy() *Common {
                LiveBuvidUpdated:  t.LiveBuvidUpdated,
                Stream_url:        t.Stream_url,
                Proxy:             t.Proxy,
+               SerLocation:       t.SerLocation,
                AcceptQn:          syncmap.Copy(t.AcceptQn),
                Qn:                syncmap.Copy(t.Qn),
                // StreamType:        t.StreamType,
@@ -485,6 +487,10 @@ func (t *Common) Init() *Common {
                t.Proxy = val.(string)
        }
 
+       if val, exist := t.K_v.LoadV("服务器时区").(float64); exist && val != 0 {
+               t.SerLocation = int(val)
+       }
+
        // 配置直播流类型
        if val, exist := t.K_v.Load("直播流类型"); exist {
                if _, ok := t.AllStreamType[val.(string)]; !ok {
index 2179c037c5b2a32c3a62af367964a63a94797958..7a154b04d152aef8d2208f766420cf4e36dea3d1 100644 (file)
@@ -2,6 +2,7 @@ package F
 
 import (
        "fmt"
+       "sync"
 
        c "github.com/qydysky/bili_danmu/CV"
        crypto "github.com/qydysky/part/crypto"
@@ -10,13 +11,18 @@ import (
 
 // 公私钥加密
 var (
-       clog = c.C.Log.Base(`cookie加密`)
-       pub  []byte
-       pri  []byte
+       clog       = c.C.Log.Base(`cookie加密`)
+       pub        []byte
+       pri        []byte
+       cookieLock sync.RWMutex
 )
 
 func CookieGet() []byte {
        clog := clog.Base_add(`获取`)
+
+       cookieLock.RLock()
+       defer cookieLock.RUnlock()
+
        if len(pri) == 0 {
                if priS, ok := c.C.K_v.LoadV(`cookie解密私钥`).(string); ok && priS != `` {
                        if d, e := crypto.FileLoad(priS); e != nil {
@@ -78,6 +84,10 @@ func CookieGet() []byte {
 
 func CookieSet(source []byte) {
        clog := clog.Base_add(`设置`)
+
+       cookieLock.Lock()
+       defer cookieLock.Unlock()
+
        if len(pub) == 0 {
                if pubS, ok := c.C.K_v.LoadV(`cookie加密公钥`).(string); ok && pubS != `` {
                        if d, e := crypto.FileLoad(pubS); e != nil {
index 800bfad14e8baab6537c383965b41746c4590665..aa284e3843f4358682f1680bea9e5636acb11822 100644 (file)
--- a/F/api.go
+++ b/F/api.go
@@ -38,6 +38,7 @@ var apilog = c.C.Log.Base(`api`)
 var api_limit = limit.New(2, "1s", "30s") //频率限制2次/s,最大等待时间30s
 
 var biliApi = cmp.Get(id, func(ba biliApiInter) biliApiInter {
+       ba.SetLocation(c.C.SerLocation)
        ba.SetProxy(c.C.Proxy)
        ba.SetReqPool(c.C.ReqPool)
        return ba
@@ -58,11 +59,11 @@ func Get(c *c.Common) *GetFunc {
        return &GetFunc{Common: c}
 }
 
-func (c *GetFunc) Get(key string) {
+func (t *GetFunc) Get(key string) {
        apilog := apilog.Base_add(`Get`)
 
-       current := c.count.Add(1)
-       defer c.count.Add(-1)
+       current := t.count.Add(1)
+       defer t.count.Add(-1)
 
        if current > 10 {
                apilog.L(`E: `, `max loop`)
@@ -76,158 +77,158 @@ func (c *GetFunc) Get(key string) {
        var (
                api_can_get = map[string][]func() (missKey []string){
                        `Cookie`: { //Cookie
-                               c.Get_cookie,
+                               t.Get_cookie,
                        },
                        `Uid`: { //用戶uid
-                               c.GetUid,
+                               t.GetUid,
                        },
                        `UpUid`: { //主播uid
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `Live_Start_Time`: { //直播开始时间
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `Liveing`: { //是否在直播
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `Title`: { //直播间标题
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.Html,
                        },
                        `Uname`: { //主播名
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.Html,
                        },
                        `ParentAreaID`: { //分区
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.Html,
                        },
                        `AreaID`: { //子分区
-                               c.getRoomBaseInfo,
-                               c.getInfoByRoom,
-                               c.Html,
+                               t.getRoomBaseInfo,
+                               t.getInfoByRoom,
+                               t.Html,
                        },
                        `Roomid`: { //房间id
-                               c.missRoomId,
+                               t.missRoomId,
                        },
                        `GuardNum`: { //舰长数
-                               c.Get_guardNum,
-                               c.getInfoByRoom,
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.Get_guardNum,
+                               t.getInfoByRoom,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `Note`: { //分区排行
-                               c.getPopularAnchorRank,
-                               // c.Get_HotRank,
-                               c.getInfoByRoom,
-                               c.Html,
+                               t.getPopularAnchorRank,
+                               // t.Get_HotRank,
+                               t.getInfoByRoom,
+                               t.Html,
                        },
                        `Locked`: { //直播间是否被封禁
-                               c.getInfoByRoom,
-                               c.Html,
+                               t.getInfoByRoom,
+                               t.Html,
                        },
                        `Live_qn`: { //当前直播流质量
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `AcceptQn`: { //允许的清晰度
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `Live`: { //直播流链接
-                               c.getRoomPlayInfoByQn,
-                               c.getRoomPlayInfo,
-                               c.Html,
+                               t.getRoomPlayInfoByQn,
+                               t.getRoomPlayInfo,
+                               t.Html,
                        },
                        `Token`: { //弹幕钥
-                               c.getDanmuInfo,
+                               t.getDanmuInfo,
                        },
                        `WSURL`: { //弹幕链接
-                               c.getDanmuInfo,
+                               t.getDanmuInfo,
                        },
                        // `VERSION`:[]func()([]string){//客户版本  不再需要
                        //      Get_Version,
                        // },
                        `LIVE_BUVID`: { //LIVE_BUVID
-                               c.Get_LIVE_BUVID,
+                               t.Get_LIVE_BUVID,
                        },
                        `CheckSwitch_FansMedal`: { //切换粉丝牌
-                               c.CheckSwitch_FansMedal,
+                               t.CheckSwitch_FansMedal,
                        },
                        `getOnlineGoldRank`: { //切换粉丝牌
-                               c.getOnlineGoldRank,
+                               t.getOnlineGoldRank,
                        },
                }
                // 验证是否有效
                check = map[string]func() (valid bool){
                        `Uid`: func() bool { //用戶uid
-                               return c.Uid != 0
+                               return t.Uid != 0
                        },
                        `UpUid`: func() bool { //主播uid
-                               return c.UpUid != 0
+                               return t.UpUid != 0
                        },
                        `Live_Start_Time`: func() bool { //直播开始时间
-                               return c.Live_Start_Time != time.Time{}
+                               return t.Live_Start_Time != time.Time{}
                        },
                        `Liveing`: func() bool { //是否在直播
                                return true
                        },
                        `Title`: func() bool { //直播间标题
-                               return c.Title != ``
+                               return t.Title != ``
                        },
                        `Uname`: func() bool { //主播名
-                               return c.Uname != ``
+                               return t.Uname != ``
                        },
                        `ParentAreaID`: func() bool { //分区
-                               return c.ParentAreaID != 0
+                               return t.ParentAreaID != 0
                        },
                        `AreaID`: func() bool { //子分区
-                               return c.AreaID != 0
+                               return t.AreaID != 0
                        },
                        `Roomid`: func() bool { //房间id
-                               return c.Roomid != 0
+                               return t.Roomid != 0
                        },
                        `GuardNum`: func() bool { //舰长数
-                               return c.GuardNum != 0
+                               return t.GuardNum != 0
                        },
                        `Note`: func() bool { //分区排行
-                               return c.Note != ``
+                               return t.Note != ``
                        },
                        `Locked`: func() bool { //直播间是否被封禁
                                return true
                        },
                        `Live_qn`: func() bool { //当前直播流质量
-                               return c.Live_qn != 0
+                               return t.Live_qn != 0
                        },
                        `AcceptQn`: func() bool { //允许的清晰度
-                               return len(c.AcceptQn) != 0
+                               return len(t.AcceptQn) != 0
                        },
                        `Live`: func() bool { //直播流链接
-                               return len(c.Live) != 0
+                               return len(t.Live) != 0
                        },
                        `Token`: func() bool { //弹幕钥
-                               return c.Token != ``
+                               return t.Token != ``
                        },
                        `WSURL`: func() bool { //弹幕链接
-                               return len(c.WSURL) != 0
+                               return len(t.WSURL) != 0
                        },
                        // `VERSION`:func()(bool){//客户版本  不再需要
-                       //      return c.VERSION != `2.0.11`
+                       //      return t.VERSION != `2.0.11`
                        // },
                        `LIVE_BUVID`: func() bool { //LIVE_BUVID
-                               return c.LiveBuvidUpdated.After(time.Now().Add(-time.Hour))
+                               return t.LiveBuvidUpdated.After(time.Now().Add(-time.Hour))
                        },
                        `CheckSwitch_FansMedal`: func() bool { //切换粉丝牌
                                return true
@@ -244,31 +245,31 @@ func (c *GetFunc) Get(key string) {
                for i := 0; i < len(fList); i++ {
                        apilog.Log_show_control(false).L(`T: `, `Get`, key)
 
-                       c.l.Lock()
+                       t.l.Lock()
                        missKey := fList[i]()
-                       c.l.Unlock()
+                       t.l.Unlock()
 
                        if len(missKey) > 0 {
                                apilog.L(`T: `, `missKey when get`, key, missKey)
                                for _, misskeyitem := range missKey {
                                        if checkf, ok := check[misskeyitem]; ok {
-                                               c.l.RLock()
+                                               t.l.RLock()
                                                if checkf() {
-                                                       c.l.RUnlock()
+                                                       t.l.RUnlock()
                                                        continue
                                                }
-                                               c.l.RUnlock()
+                                               t.l.RUnlock()
                                        }
                                        if misskeyitem == key {
                                                apilog.L(`W: `, `missKey equrt key`, key, missKey)
                                                continue
                                        }
-                                       c.Get(misskeyitem)
+                                       t.Get(misskeyitem)
                                }
 
-                               c.l.Lock()
+                               t.l.Lock()
                                missKey := fList[i]()
-                               c.l.Unlock()
+                               t.l.Unlock()
 
                                if len(missKey) > 0 {
                                        apilog.L(`W: `, `missKey when get`, key, missKey)
@@ -277,27 +278,27 @@ func (c *GetFunc) Get(key string) {
                        }
 
                        if checkf, ok := check[key]; ok {
-                               c.l.RLock()
+                               t.l.RLock()
                                if checkf() {
-                                       c.l.RUnlock()
+                                       t.l.RUnlock()
                                        break
                                } else {
-                                       c.l.RUnlock()
+                                       t.l.RUnlock()
                                        apilog.L(`W: `, `check fail`, key)
-                                       // c.Get(key)
+                                       // t.Get(key)
                                }
                        }
                }
        }
 }
 
-func (c *GetFunc) GetUid() (missKey []string) {
-       if uid, ok := c.Cookie.LoadV(`DedeUserID`).(string); !ok { //cookie中无DedeUserID
+func (t *GetFunc) GetUid() (missKey []string) {
+       if uid, ok := t.Cookie.LoadV(`DedeUserID`).(string); !ok { //cookie中无DedeUserID
                missKey = append(missKey, `Cookie`)
        } else if uid, e := strconv.Atoi(uid); e != nil {
                missKey = append(missKey, `Cookie`)
        } else {
-               c.Uid = uid
+               t.Uid = uid
        }
        return
 }
@@ -486,78 +487,78 @@ func (t *GetFunc) configStreamType(sts []struct {
        }
 }
 
-func (c *GetFunc) missRoomId() (missKey []string) {
+func (t *GetFunc) missRoomId() (missKey []string) {
        apilog.Base_add(`missRoomId`).L(`E: `, `missRoomId`)
        return
 }
 
-func (c *GetFunc) getRoomBaseInfo() (missKey []string) {
+func (t *GetFunc) getRoomBaseInfo() (missKey []string) {
        fkey := `getRoomBaseInfo`
 
-       if _, ok := c.Cache.Load(fkey); ok {
+       if _, ok := t.Cache.Load(fkey); ok {
                return
        }
 
        apilog := apilog.Base_add(`getRoomBaseInfo`)
 
-       if c.Roomid == 0 {
+       if t.Roomid == 0 {
                missKey = append(missKey, `Roomid`)
                return
        }
 
        //使用其他api
-       if err, res := biliApi.GetRoomBaseInfo(c.Roomid); err != nil {
+       if err, res := biliApi.GetRoomBaseInfo(t.Roomid); err != nil {
                apilog.L(`E: `, err)
                return
        } else {
-               c.UpUid = res.UpUid
-               c.Uname = res.Uname
-               c.ParentAreaID = res.ParentAreaID
-               c.AreaID = res.AreaID
-               c.Title = res.Title
-               c.Live_Start_Time = res.LiveStartTime
-               c.Liveing = res.Liveing
-               c.Roomid = res.RoomID
+               t.UpUid = res.UpUid
+               t.Uname = res.Uname
+               t.ParentAreaID = res.ParentAreaID
+               t.AreaID = res.AreaID
+               t.Title = res.Title
+               t.Live_Start_Time = res.LiveStartTime
+               t.Liveing = res.Liveing
+               t.Roomid = res.RoomID
        }
 
-       c.Cache.Store(fkey, nil, time.Second*2)
+       t.Cache.Store(fkey, nil, time.Second*2)
        return
 }
 
-func (c *GetFunc) getInfoByRoom() (missKey []string) {
+func (t *GetFunc) getInfoByRoom() (missKey []string) {
 
        fkey := `getInfoByRoom`
 
-       if _, ok := c.Cache.Load(fkey); ok {
+       if _, ok := t.Cache.Load(fkey); ok {
                return
        }
 
        apilog := apilog.Base_add(`getInfoByRoom`)
 
-       if c.Roomid == 0 {
+       if t.Roomid == 0 {
                missKey = append(missKey, `Roomid`)
                return
        }
 
        //使用其他api
-       if err, res := biliApi.GetInfoByRoom(c.Roomid); err != nil {
+       if err, res := biliApi.GetInfoByRoom(t.Roomid); err != nil {
                apilog.L(`E: `, err)
                return
        } else {
-               c.UpUid = res.UpUid
-               c.Uname = res.Uname
-               c.ParentAreaID = res.ParentAreaID
-               c.AreaID = res.AreaID
-               c.Title = res.Title
-               c.Live_Start_Time = res.LiveStartTime
-               c.Liveing = res.Liveing
-               c.Roomid = res.RoomID
-               c.GuardNum = res.GuardNum
-               c.Note = res.Note
-               c.Locked = res.Locked
+               t.UpUid = res.UpUid
+               t.Uname = res.Uname
+               t.ParentAreaID = res.ParentAreaID
+               t.AreaID = res.AreaID
+               t.Title = res.Title
+               t.Live_Start_Time = res.LiveStartTime
+               t.Liveing = res.Liveing
+               t.Roomid = res.RoomID
+               t.GuardNum = res.GuardNum
+               t.Note = res.Note
+               t.Locked = res.Locked
        }
 
-       c.Cache.Store(fkey, nil, time.Second*2)
+       t.Cache.Store(fkey, nil, time.Second*2)
 
        return
 }
@@ -749,11 +750,11 @@ func (t *GetFunc) getRoomPlayInfoByQn() (missKey []string) {
        return
 }
 
-func (c *GetFunc) getDanmuInfo() (missKey []string) {
-       if c.Roomid == 0 {
+func (t *GetFunc) getDanmuInfo() (missKey []string) {
+       if t.Roomid == 0 {
                missKey = append(missKey, `Roomid`)
        }
-       if c.LiveBuvidUpdated.Before(time.Now().Add(-time.Hour)) {
+       if t.LiveBuvidUpdated.Before(time.Now().Add(-time.Hour)) {
                missKey = append(missKey, `LIVE_BUVID`)
        }
        if len(missKey) > 0 {
@@ -761,12 +762,12 @@ func (c *GetFunc) getDanmuInfo() (missKey []string) {
        }
 
        //GetDanmuInfo
-       if err, res := biliApi.GetDanmuInfo(c.Roomid); err != nil {
+       if err, res := biliApi.GetDanmuInfo(t.Roomid); err != nil {
                apilog.L(`E: `, err)
                return
        } else {
-               c.Token = res.Token
-               c.WSURL = res.WSURL
+               t.Token = res.Token
+               t.WSURL = res.WSURL
        }
        return
 }
@@ -1045,7 +1046,7 @@ func (t *GetFunc) Get_cookie() (missKey []string) {
 }
 
 // 获取其他Cookie
-// func (c *GetFunc) Get_other_cookie() {
+// func (t *GetFunc) Get_other_cookie() {
 //     apilog := apilog.Base_add(`获取其他Cookie`)
 
 //     r := c.ReqPool.Get()
@@ -1133,12 +1134,12 @@ func Get_weared_medal(uid, upUid int) (item J.GetWearedMedal_Data) {
        return
 }
 
-func (c *GetFunc) CheckSwitch_FansMedal() (missKey []string) {
+func (t *GetFunc) CheckSwitch_FansMedal() (missKey []string) {
 
-       if c.LiveBuvidUpdated.Before(time.Now().Add(-time.Hour)) {
+       if t.LiveBuvidUpdated.Before(time.Now().Add(-time.Hour)) {
                missKey = append(missKey, `LIVE_BUVID`)
        }
-       if c.UpUid == 0 {
+       if t.UpUid == 0 {
                missKey = append(missKey, `UpUid`)
        }
        if len(missKey) > 0 {
@@ -1157,15 +1158,15 @@ func (c *GetFunc) CheckSwitch_FansMedal() (missKey []string) {
        }
 
        Cookie := make(map[string]string)
-       c.Cookie.Range(func(k, v interface{}) bool {
+       t.Cookie.Range(func(k, v interface{}) bool {
                Cookie[k.(string)] = v.(string)
                return true
        })
        { //获取当前牌子,验证是否本直播间牌子
-               res := Get_weared_medal(c.Uid, c.UpUid)
+               res := Get_weared_medal(t.Uid, t.UpUid)
 
-               c.Wearing_FansMedal = res.Roominfo.RoomID //更新佩戴信息
-               if res.TargetID == c.UpUid {
+               t.Wearing_FansMedal = res.Roominfo.RoomID //更新佩戴信息
+               if res.TargetID == t.UpUid {
                        return
                }
        }
@@ -1173,16 +1174,16 @@ func (c *GetFunc) CheckSwitch_FansMedal() (missKey []string) {
        var medal_id int //将要使用的牌子id
        //检查是否有此直播间的牌子
        {
-               medal_list := Get_list_in_room(c.Roomid, c.UpUid)
+               medal_list := Get_list_in_room(t.Roomid, t.UpUid)
                for _, v := range medal_list {
-                       if v.TargetID != c.UpUid {
+                       if v.TargetID != t.UpUid {
                                continue
                        }
                        medal_id = v.MedalID
                }
                if medal_id == 0 { //无牌
                        apilog.L(`I: `, `无主播粉丝牌`)
-                       if c.Wearing_FansMedal == 0 { //当前没牌
+                       if t.Wearing_FansMedal == 0 { //当前没牌
                                return
                        }
                }
@@ -1196,7 +1197,7 @@ func (c *GetFunc) CheckSwitch_FansMedal() (missKey []string) {
                        } else {
                                apilog.L(`I: `, `自动切换粉丝牌 id:`, medal_id)
                        }
-                       c.Wearing_FansMedal = medal_id //更新佩戴信息
+                       t.Wearing_FansMedal = medal_id //更新佩戴信息
                        return
                }
        }
@@ -1539,7 +1540,7 @@ func GetHistory(Roomid_int int) (j []string) {
        }
 }
 
-func (c *GetFunc) SearchUP(s string) (list []struct {
+func (t *GetFunc) SearchUP(s string) (list []struct {
        Roomid  int
        Uname   string
        Is_live bool
@@ -1582,7 +1583,7 @@ func IsConnected() bool {
 }
 
 // bilibili wrid wts 计算
-func (c *GetFunc) getWridWts(query string, imgURL, subURL string, customWts ...string) (w_rid, wts string) {
+func (t *GetFunc) getWridWts(query string, imgURL, subURL string, customWts ...string) (w_rid, wts string) {
        wbi := imgURL[strings.LastIndex(imgURL, "/")+1:strings.LastIndex(imgURL, ".")] +
                subURL[strings.LastIndex(subURL, "/")+1:strings.LastIndex(subURL, ".")]
 
index ef51c6b09c54c6ff0319043e9eb8dae6230db5de..070e4fb0f72bce0b7a42e3a6734bdd6a0f332c6d 100644 (file)
@@ -11,6 +11,7 @@ import (
 type biliApiInter interface {
        SetReqPool(pool *pool.Buf[reqf.Req])
        SetProxy(proxy string)
+       SetLocation(secOfTimeZone int) // east positive
        SetCookies(cookies []*http.Cookie)
        GetCookies() (cookies []*http.Cookie)
        GetCookie(name string) (error, string)
index a167b9f5692b65f0abf585e325f46c80b6036f8e..0ef64c9de12ce343346abdd720f192fccb6080e7 100644 (file)
@@ -344,7 +344,7 @@ func Gtk_danmu() {
                                                        show(`输入错误`, load_face("0room"))
                                                } else {
                                                        c.C.Roomid = i
-                                                       c.C.Danmu_Main_mq.Push_tag(`change_room`, nil)
+                                                       c.C.Danmu_Main_mq.Push_tag(`change_room`, i)
                                                }
                                        } else {
                                                show(`房间号输入为空`, load_face("0room"))
index dd1a7e5ceb5332616a13fbf9a030bd1487c0c214..2026f821a69d3671b88ab73af8a8c45e45048b90 100644 (file)
@@ -167,19 +167,22 @@ func Start() {
                }
 
                for exitSign := false; !exitSign; {
-                       if c.C.Roomid == 0 {
+                       common := c.C.Copy()
+
+                       if common.Roomid == 0 {
                                fmt.Println("回车查看指令")
                                ctx, cancel := context.WithCancel(mainCtx)
-                               cancel1, c := c.C.Danmu_Main_mq.Pull_tag_chan(`change_room`, 1, ctx)
+                               cancel1, c := common.Danmu_Main_mq.Pull_tag_chan(`change_room`, 1, ctx)
                                select {
-                               case <-c:
+                               case roomid := <-c:
+                                       common.Roomid = roomid.(int)
                                case <-interrupt_chan:
                                        exitSign = true
                                }
                                cancel1()
                                cancel()
                        } else {
-                               fmt.Print("房间号: ", strconv.Itoa(c.C.Roomid), "\n")
+                               fmt.Print("房间号: ", strconv.Itoa(common.Roomid), "\n")
                        }
 
                        if exitSign {
@@ -194,39 +197,31 @@ func Start() {
                        //附加功能 自动发送即将过期礼物
                        go reply.AutoSend_silver_gift()
                        //获取热门榜
-                       F.Get(c.C).Get(`Note`)
+                       F.Get(common).Get(`Note`)
 
-                       danmulog.L(`I: `, "连接到房间", c.C.Roomid)
+                       danmulog.L(`I: `, "连接到房间", common.Roomid)
 
                        Cookie := make(map[string]string)
-                       c.C.Cookie.Range(func(k, v any) bool {
+                       common.Cookie.Range(func(k, v any) bool {
                                Cookie[k.(string)] = v.(string)
                                return true
                        })
 
-                       F.Get(c.C).Get(`Liveing`)
                        // 检查与切换粉丝牌,只在cookie存在时启用
-                       F.Get(c.C).Get(`CheckSwitch_FansMedal`)
-
-                       // 直播状态
-                       if c.C.Liveing {
-                               danmulog.L(`I: `, "直播中")
-                       } else {
-                               danmulog.L(`I: `, "未直播")
-                       }
+                       F.Get(common).Get(`CheckSwitch_FansMedal`)
 
                        // 对每个弹幕服务器尝试
-                       F.Get(c.C).Get(`WSURL`)
+                       F.Get(common).Get(`WSURL`)
                        aliveT := time.Now().Add(3 * time.Hour)
-                       for i, exitloop := 0, false; !exitloop && i < len(c.C.WSURL) && time.Now().Before(aliveT); {
-                               v := c.C.WSURL[i]
+                       for i, exitloop := 0, false; !exitloop && i < len(common.WSURL) && time.Now().Before(aliveT); {
+                               v := common.WSURL[i]
                                //ws启动
                                danmulog.L(`T: `, "连接 "+v)
                                u, _ := url.Parse(v)
                                ws_c, err := ws.New_client(&ws.Client{
                                        Url:               v,
                                        TO:                35 * 1000,
-                                       Proxy:             c.C.Proxy,
+                                       Proxy:             common.Proxy,
                                        Func_abort_close:  func() { danmulog.L(`I: `, `服务器连接中断`) },
                                        Func_normal_close: func() { danmulog.L(`I: `, `服务器连接关闭`) },
                                        Header: map[string]string{
@@ -260,7 +255,7 @@ func Start() {
                                // auth
                                {
                                        wsmsg.PushLock_tag(`send`, &ws.WsMsg{
-                                               Msg: F.HelloGen(c.C.Roomid, c.C.Token),
+                                               Msg: F.HelloGen(common.Roomid, common.Token),
                                        })
                                        waitCheckAuth, cancel := context.WithTimeout(mainCtx, 5*time.Second)
                                        doneAuth := wsmsg.Pull_tag_only(`rec`, func(wm *ws.WsMsg) (disable bool) {
@@ -278,17 +273,24 @@ func Start() {
                                        }
                                }
 
-                               danmulog.L(`I: `, "已连接到房间", c.C.Uname, `(`, c.C.Roomid, `)`)
-                               reply.Gui_show(`进入直播间: `+c.C.Uname+` (`+strconv.Itoa(c.C.Roomid)+`)`, `0room`)
-                               if c.C.Title != `` {
-                                       danmulog.L(`I: `, `房间标题: `+c.C.Title)
-                                       reply.Gui_show(`房间标题: `+c.C.Title, `0room`)
+                               danmulog.L(`I: `, "已连接到房间", common.Uname, `(`, common.Roomid, `)`)
+                               reply.Gui_show(`进入直播间: `+common.Uname+` (`+strconv.Itoa(common.Roomid)+`)`, `0room`)
+                               if common.Title != `` {
+                                       danmulog.L(`I: `, `房间标题: `+common.Title)
+                                       reply.Gui_show(`房间标题: `+common.Title, `0room`)
+                               }
+
+                               // 直播状态
+                               if F.Get(common).Get(`Liveing`); common.Liveing {
+                                       danmulog.L(`I: `, "直播中")
+                               } else {
+                                       danmulog.L(`I: `, "未直播")
                                }
 
                                // 处理ws消息
                                var cancelDeal = wsmsg.Pull_tag(map[string]func(*ws.WsMsg) (disable bool){
                                        `rec`: func(wm *ws.WsMsg) (disable bool) {
-                                               go reply.Reply(c.C, wm.Msg)
+                                               go reply.Reply(common, wm.Msg)
                                                return false
                                        },
                                        `close`: func(_ *ws.WsMsg) (disable bool) {
@@ -309,9 +311,9 @@ func Start() {
                                }()
 
                                // 刷新舰长数
-                               F.Get(c.C).Get(`GuardNum`)
+                               F.Get(common).Get(`GuardNum`)
                                // 在线人数
-                               F.Get(c.C).Get(`getOnlineGoldRank`)
+                               F.Get(common).Get(`getOnlineGoldRank`)
                                //验证cookie
                                if missKey := F.CookieCheck([]string{
                                        `bili_jct`,
@@ -324,18 +326,18 @@ func Start() {
                                { //附加功能 进房间发送弹幕 直播流保存 每日签到
                                        go F.Dosign()
                                        go reply.Entry_danmu()
-                                       if _, e := recStartEnd.RecStartCheck.Run(mainCtx, c.C); e == nil {
-                                               go reply.StreamOStart(c.C.Copy(), c.C.Roomid)
+                                       if _, e := recStartEnd.RecStartCheck.Run(mainCtx, common); e == nil {
+                                               go reply.StreamOStart(common, common.Roomid)
                                        } else {
-                                               danmulog.Base("功能", "指定房间录制区间").L(`I: `, c.C.Roomid, e)
+                                               danmulog.Base("功能", "指定房间录制区间").L(`I: `, common.Roomid, e)
                                        }
-                                       go F.RoomEntryAction(c.C.Roomid)
+                                       go F.RoomEntryAction(common.Roomid)
                                }
 
                                //当前ws
                                {
                                        // 处理各种指令
-                                       var cancelfunc = c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
+                                       var cancelfunc = common.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
                                                `interrupt`: func(_ any) (disable bool) {
                                                        exitloop = true
                                                        exitSign = true
@@ -346,39 +348,40 @@ func Start() {
                                                },
                                                `exit_room`: func(_ any) bool { //退出当前房间
                                                        exitloop = true
-                                                       reply.StreamOStop(c.C.Roomid)
-                                                       danmulog.L(`I: `, "退出房间", c.C.Roomid)
-                                                       c.C.Roomid = 0
+                                                       reply.StreamOStop(common.Roomid)
+                                                       danmulog.L(`I: `, "退出房间", common.Roomid)
+                                                       common.Roomid = 0
                                                        ws_c.Close()
                                                        return true
                                                },
-                                               `change_room`: func(_ any) bool { //换房时退出当前房间
+                                               `change_room`: func(roomid any) bool { //换房时退出当前房间
+                                                       common.Roomid = roomid.(int)
                                                        exitloop = true
                                                        ws_c.Close()
-                                                       if v, ok := c.C.K_v.LoadV(`仅保存当前直播间流`).(bool); ok && v {
-                                                               reply.StreamOStopOther(c.C.Roomid) //停止其他房间录制
+                                                       if v, ok := common.K_v.LoadV(`仅保存当前直播间流`).(bool); ok && v {
+                                                               reply.StreamOStopOther(common.Roomid) //停止其他房间录制
                                                        }
                                                        return true
                                                },
                                                `flash_room`: func(_ any) bool { //重进房时退出当前房间
-                                                       go F.Get(c.C).Get(`WSURL`)
+                                                       go F.Get(common).Get(`WSURL`)
                                                        ws_c.Close()
                                                        return true
                                                },
                                                `guard_update`: func(_ any) bool { //舰长更新
-                                                       go F.Get(c.C).Get(`GuardNum`)
+                                                       go F.Get(common).Get(`GuardNum`)
                                                        return false
                                                },
                                                `every100s`: func(_ any) bool { //每100s
                                                        if time.Now().After(aliveT) {
-                                                               c.C.Danmu_Main_mq.Push_tag(`flash_room`, nil)
+                                                               common.Danmu_Main_mq.Push_tag(`flash_room`, nil)
                                                                return false
                                                        }
-                                                       if v, ok := c.C.K_v.LoadV("下播后不记录人气观看人数").(bool); ok && v && !c.C.Liveing {
+                                                       if v, ok := common.K_v.LoadV("下播后不记录人气观看人数").(bool); ok && v && !common.Liveing {
                                                                return false
                                                        }
                                                        // 在线人数
-                                                       go F.Get(c.C).Get(`getOnlineGoldRank`)
+                                                       go F.Get(common).Get(`getOnlineGoldRank`)
                                                        return false
                                                },
                                                `new day`: func(_ any) bool { //日期更换
@@ -386,7 +389,7 @@ func Start() {
                                                                //每日签到
                                                                F.Dosign()
                                                                //每日兑换硬币
-                                                               F.Get(c.C).Silver_2_coin()
+                                                               F.Get(common).Silver_2_coin()
                                                                //附加功能 每日发送弹幕
                                                                reply.Entry_danmu()
                                                                //附加功能 保持牌子点亮
index aae26ae9d644df921cb6cd73a74a2574be9bdab1..7c2e55717964f326329af0a7ab8c5b43d32deb3c 100644 (file)
@@ -102,7 +102,7 @@ func Cmd() {
                                fmt.Print("\n")
                                if room, ok := liveList[inputs]; ok {
                                        c.C.Roomid = room
-                                       c.C.Danmu_Main_mq.Push_tag(`change_room`, nil)
+                                       c.C.Danmu_Main_mq.Push_tag(`change_room`, room)
                                        continue
                                } else {
                                        cmdlog.L(`W: `, "输入错误", inputs)
@@ -191,16 +191,8 @@ func Cmd() {
                                        }
                                        fmt.Println(c.C.Uname, c.C.Title, living)
                                }
-                               {
-                                       if c.C.Liveing {
-                                               d := time.Since(c.C.Live_Start_Time).Round(time.Second)
-                                               h := d / time.Hour
-                                               d -= h * time.Hour
-                                               m := d / time.Minute
-                                               d -= m * time.Minute
-                                               s := d / time.Second
-                                               fmt.Println(`已直播时长:`, fmt.Sprintf("%02d:%02d:%02d", h, m, s))
-                                       }
+                               if c.C.Liveing {
+                                       fmt.Println(`已直播时长:`, (time.Time{}).Add(time.Since(c.C.Live_Start_Time)).Format(time.TimeOnly))
                                }
                                {
                                        fmt.Println(`营收:`, fmt.Sprintf("¥%.2f", c.C.Rev))
@@ -227,7 +219,7 @@ func Cmd() {
                        if room, err := strconv.Atoi(inputs[1:]); err == nil {
                                c.C.Roomid = room
                                cmdlog.L(`I: `, "进入房间", room)
-                               c.C.Danmu_Main_mq.Push_tag(`change_room`, nil)
+                               c.C.Danmu_Main_mq.Push_tag(`change_room`, room)
                                continue
                        }
                        cmdlog.L(`W: `, "无效指令("+inputs+")")
index bad780d74f3487f57579aac49b1f908a95404529..ac5b2a56203fbad0dc6dc37650dc0a10ddb1d6b7 100644 (file)
     "生成pgo-help":"将在退出后生成pgo文件在指定路径,default.pgo将有助于下次构建的优化,但会导致gc频繁,构建缓慢,为空时不生成",
     "生成pgo":"",
     "登陆二维码-白":"OO",
-    "登陆二维码-黑":"  "
+    "登陆二维码-黑":"  ",
+    "服务器时区-help":"用于正确解析服务器响应中的时间,整数,单位秒,整数是UTC以东,默认0",
+    "服务器时区":0
 }
\ No newline at end of file
diff --git a/go.mod b/go.mod
index b0bd66f7d9833268f2744d9453f962cd18efab32..463ac6457d0d4e83f72f1e2b09bcc2f3e2335219 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/qydysky/bili_danmu
 go 1.22.2
 
 require (
-       github.com/gotk3/gotk3 v0.6.3
+       github.com/gotk3/gotk3 v0.6.4
        github.com/mdp/qrterminal/v3 v3.2.0
        github.com/qydysky/part v0.28.20240617114802
        github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
@@ -13,8 +13,8 @@ require (
 
 require (
        github.com/google/uuid v1.6.0
-       github.com/qydysky/biliApi v0.0.0-20240621154030-402fd30c5a23
-       golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
+       github.com/qydysky/biliApi v0.0.0-20240707084224-dd146610f462
+       golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
 )
 
 require (
@@ -26,11 +26,11 @@ require (
        github.com/mattn/go-isatty v0.0.20 // indirect
        github.com/ncruces/go-strftime v0.1.9 // indirect
        github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
-       golang.org/x/crypto v0.24.0 // indirect
+       golang.org/x/crypto v0.25.0 // indirect
        golang.org/x/sync v0.7.0 // indirect
-       golang.org/x/term v0.21.0 // indirect
+       golang.org/x/term v0.22.0 // indirect
        modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
-       modernc.org/libc v1.53.3 // indirect
+       modernc.org/libc v1.54.2 // indirect
        modernc.org/mathutil v1.6.0 // indirect
        modernc.org/memory v1.8.0 // indirect
        modernc.org/strutil v1.2.0 // indirect
@@ -52,9 +52,9 @@ require (
        github.com/tklauser/go-sysconf v0.3.14 // indirect
        github.com/tklauser/numcpus v0.8.0 // indirect
        github.com/yusufpapurcu/wmi v1.2.4 // indirect
-       golang.org/x/mod v0.18.0 // indirect
-       golang.org/x/net v0.26.0 // indirect
-       golang.org/x/sys v0.21.0 // indirect
+       golang.org/x/mod v0.19.0 // indirect
+       golang.org/x/net v0.27.0 // indirect
+       golang.org/x/sys v0.22.0 // indirect
        golang.org/x/tools v0.22.0 // indirect
        modernc.org/sqlite v1.30.1
        rsc.io/qr v0.2.0 // indirect
diff --git a/go.sum b/go.sum
index cba6b007bcc9ba253a652d882b7f6ea9f21fded7..af13ec3717312d30b707f3adf2f5a476460c7e29 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -18,8 +18,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
 github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gotk3/gotk3 v0.6.3 h1:+Ke4WkM1TQUNOlM2TZH6szqknqo+zNbX3BZWVXjSHYw=
-github.com/gotk3/gotk3 v0.6.3/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
+github.com/gotk3/gotk3 v0.6.4 h1:5ur/PRr86PwCG8eSj98D1eXvhrNNK6GILS2zq779dCg=
+github.com/gotk3/gotk3 v0.6.4/go.mod h1:/hqFpkNa9T3JgNAE2fLvCdov7c5bw//FHNZrZ3Uv9/Q=
 github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
 github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
 github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@@ -44,8 +44,8 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh
 github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/qydysky/biliApi v0.0.0-20240621154030-402fd30c5a23 h1:xMqDxMA6K4CAFqwenaSlSJjJ7xSAtFmpojpkO7latMM=
-github.com/qydysky/biliApi v0.0.0-20240621154030-402fd30c5a23/go.mod h1:om024vfxALQ5vxsbaGoMm8IS0esLYBnEOpJI8FsGoDg=
+github.com/qydysky/biliApi v0.0.0-20240707084224-dd146610f462 h1:SblV/m+0mx6QgH2YYvdjE5QxhyfE/EOQglJ1PGd3x3E=
+github.com/qydysky/biliApi v0.0.0-20240707084224-dd146610f462/go.mod h1:om024vfxALQ5vxsbaGoMm8IS0esLYBnEOpJI8FsGoDg=
 github.com/qydysky/part v0.28.20240617114802 h1:cmDWin7303nKFQ7HAL2+Ur87vkh8d67xVqudvpXp96E=
 github.com/qydysky/part v0.28.20240617114802/go.mod h1:dgagZnPYRFZDbt7XJf7nADOJLoYwlebD9B8Z8g5aHhI=
 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
@@ -69,23 +69,23 @@ github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYg
 github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE=
 github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
 github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
-golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
-golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
-golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
-golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
-golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
-golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
-golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
-golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
+golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
+golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
+golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
+golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
+golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
+golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
+golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
+golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
 golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
 golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
-golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
-golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
+golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
+golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
 golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
 golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
 golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
@@ -94,18 +94,18 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-modernc.org/cc/v4 v4.21.3 h1:2mhBdWKtivdFlLR1ecKXTljPG1mfvbByX7QKztAIJl8=
-modernc.org/cc/v4 v4.21.3/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
-modernc.org/ccgo/v4 v4.18.1 h1:1zF5kPBFq/ZVTulBOKgQPQITdOzzyBUfC51gVYP62E4=
-modernc.org/ccgo/v4 v4.18.1/go.mod h1:ao1fAxf9a2KEOL15WY8+yP3wnpaOpP/QuyFOZ9HJolM=
+modernc.org/cc/v4 v4.21.4 h1:3Be/Rdo1fpr8GrQ7IVw9OHtplU4gWbb+wNgeoBMmGLQ=
+modernc.org/cc/v4 v4.21.4/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
+modernc.org/ccgo/v4 v4.19.0 h1:f9K5VdC0nVhHKTFMvhjtZ8TbRgFQbASvE5yO1zs8eC0=
+modernc.org/ccgo/v4 v4.19.0/go.mod h1:CfpAl+673iXNwMG/aqcQn+vDcu4Es/YLya7+9RHjTa4=
 modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
 modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
 modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
 modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
 modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
 modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
-modernc.org/libc v1.53.3 h1:9O0aSLZuHPgp49we24NoFFteRgXNLGBAQ3TODrW3XLg=
-modernc.org/libc v1.53.3/go.mod h1:kb+Erju4FfHNE59xd2fNpv5CBeAeej6fHbx8p8xaiyI=
+modernc.org/libc v1.54.2 h1:9ymAodb+3v85YfBIZqn62BGgO4L9zF2Hx4LNb6dSU/Q=
+modernc.org/libc v1.54.2/go.mod h1:B0D6klDmSmnq26T1iocn9kzyX6NtbzjuI3+oX/xfvng=
 modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
 modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
 modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=