demo/main.exe
*.m4s
*.m3u8
-*.flv
\ No newline at end of file
+*.flv
+demo/build.bat
import (
"encoding/json"
- "io/ioutil"
+ "errors"
+ "io"
"time"
+ file "github.com/qydysky/part/file"
idpool "github.com/qydysky/part/idpool"
log "github.com/qydysky/part/log"
mq "github.com/qydysky/part/msgq"
t.Danmu_Main_mq = mq.New(200)
- if bb, err := ioutil.ReadFile("config/config_K_v.json"); err == nil {
- var data map[string]interface{}
- json.Unmarshal(bb, &data)
- for k, v := range data {
- t.K_v.Store(k, v)
+ if bb, err := file.New("config/config_K_v.json", 0, true).ReadAll(100, 1<<16); err != nil {
+ if errors.Is(err, io.EOF) {
+ var data map[string]interface{}
+ json.Unmarshal(bb, &data)
+ for k, v := range data {
+ t.K_v.Store(k, v)
+ }
+ } else {
+ panic(err)
}
}
+ go func() {
+ for {
+ v, ok := t.K_v.LoadV("几秒后重载").(float64)
+ if !ok || v < 0 {
+ break
+ } else if v < 60 {
+ v = 60
+ }
+ time.Sleep(time.Duration(int(v)) * time.Second)
+
+ // 64k
+ if bb, e := file.New("config/config_K_v.json", 0, true).ReadAll(100, 1<<16); e != nil {
+ if !errors.Is(e, io.EOF) {
+ panic(e)
+ } else {
+ var data map[string]interface{}
+ json.Unmarshal(bb, &data)
+ for k, v := range data {
+ t.K_v.Store(k, v)
+ }
+ }
+ }
+ }
+ }()
+
if val, exist := t.K_v.Load("http代理地址"); exist {
t.Proxy = val.(string)
}
{
AcceptQn := []int{}
- for k, _ := range c.AcceptQn {
+ for k := range c.AcceptQn {
if k <= c.Live_want_qn {
AcceptQn = append(AcceptQn, k)
}
}
http.ServeFile(w, r, path)
},
- `/exit`: func(w http.ResponseWriter, r *http.Request) {
+ `/exit`: func(_ http.ResponseWriter, _ *http.Request) {
s.Server.Shutdown(context.Background())
},
})
## bilibili 直播弹幕机
-golang go version go1.16 linux/amd64
+
+[](https://goreportcard.com/report/github.com/qydysky/bili_danmu)
---
### 目录释义
"errors"
"fmt"
"io"
- "io/ioutil"
"math"
"net/http"
"net/url"
return []c.Common{v.(*M4SStream).Common()}
}
} else { //返回所有
- streamO.Range(func(k, v interface{}) bool {
+ streamO.Range(func(_, v interface{}) bool {
array = append(array, v.(*M4SStream).Common())
return true
})
StartRecDanmu(ms.Current_save_path + "0.csv")
Ass_f(ms.Current_save_path, ms.Current_save_path+"0", time.Now()) //开始ass
}
- tmp.Callback_stopRec = func(ms *M4SStream) {
+ tmp.Callback_stopRec = func(_ *M4SStream) {
StopRecDanmu()
Ass_f("", "", time.Now()) //停止ass
}
return true
})
case -1: // 所有房间
- streamO.Range(func(_roomid, v interface{}) bool {
+ streamO.Range(func(_, v interface{}) bool {
if v.(*M4SStream).Status.Islive() {
v.(*M4SStream).Stop()
}
}
func init() { //初始化反射型弹幕机
- bb, err := ioutil.ReadFile("config/config_auto_reply.json")
+ bb, err := file.New("config/config_auto_reply.json", 0, true).ReadAll(100, 1<<16)
if err != nil {
return
}
func init() {
Save_to_json(0, []byte{'['})
c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `change_room`: func(data interface{}) bool { //房间改变
+ `change_room`: func(_ interface{}) bool { //房间改变
Save_to_json(0, []byte{'['})
return false
},
- `flash_room`: func(data interface{}) bool { //房间改变
+ `flash_room`: func(_ interface{}) bool { //房间改变
Save_to_json(0, []byte{'['})
return false
},
return
}
for _, v := range medals {
- if v.IsLighted == 1 {
+ if v.IsLighted == 1 || cacheInfo[v.TargetID].Data.LiveRoom.Roomid == 0 {
continue
}
return
}
for _, v := range medals {
- if v.IsLighted == 1 {
+ if v.IsLighted == 1 || cacheInfo[v.TargetID].Data.LiveRoom.Roomid == 0 {
continue
}
//等待会话结束,通道释放
<-conn
},
- `/exit`: func(w http.ResponseWriter, r *http.Request) {
+ `/exit`: func(_ http.ResponseWriter, _ *http.Request) {
s.Server.Shutdown(context.Background())
},
})
func init() {
communicate.Buf = new(psync.Map)
c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `change_room`: func(data interface{}) bool { //房间改变
+ `change_room`: func(_ interface{}) bool { //房间改变
communicate.Reset()
return false
},
- `flash_room`: func(data interface{}) bool { //房间改变
+ `flash_room`: func(_ interface{}) bool { //房间改变
communicate.Reset()
return false
},
import (
"encoding/json"
- "io/ioutil"
c "github.com/qydysky/bili_danmu/CV"
+ file "github.com/qydysky/part/file"
)
/*
"USER_TASK_PROGRESS": nil,
"LITTLE_TIPS": replyF.little_tips, //小提示窗口
"LIKE_INFO_V3_NOTICE": nil,
+ "LIVE_INTERACTIVE_GAME": nil,
}
// 屏蔽不需要的消息
func init() {
{ //加载不需要的消息
- bb, err := ioutil.ReadFile("config/config_disable_msg.json")
+ bb, err := file.New("config/config_disable_msg.json", 0, true).ReadAll(100, 1<<16)
if err != nil {
return
}
}
-// 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")
-
- // var sh []interface{}
- // var sh_log []interface{}
-
- // if username != nil {
- // sh = append(sh, username)
- // }
- // if gift_name != nil {
- // sh = append(sh, "购买了", gift_name)
- // }
- // if price != nil {
- // sh_log = append(sh, "¥", int(price.(float64))/1000) //不在界面显示价格
- // }
- // { //额外 ass
- // Assf(fmt.Sprintln(sh...))
- // }
- // fmt.Println("\n====")
- // fmt.Println(sh...)
- // fmt.Print("====\n\n")
- // msglog.Base_add("礼").Log_show_control(false).L(`I: `, sh_log...)
-
-}
-
// Msg-房间信息改变,标题等
func (replyF) room_change(s string) {
title := p.Json().GetValFromS(s, "data.title")
msglog.Base_add("房").L(`I: `, tmp)
}
-// Msg-大航海欢迎信息 或已废弃
-func (replyF) welcome_guard(s string) {
- // username := p.Json().GetValFromS(s, "data.username");
- // guard_level := p.Json().GetValFromS(s, "data.guard_level");
- // img := "0default"
-
- // var sh = []interface{}{"欢迎"}
-
- // if guard_level != nil {
- // switch guard_level.(float64) {
- // case 1:sh = append(sh, "总督");img="0level1"
- // case 2:sh = append(sh, "提督");img="0level2"
- // case 3:sh = append(sh, "舰长");img="0level3"
- // default:sh = append(sh, "等级", guard_level)
- // }
- // }
- // if username != nil {
- // sh = append(sh, username, "进入直播间")
- // }
- // {//语言tts
- // c.Danmu_Main_mq.Push_tag(`tts`,Danmu_mq_t{//传入消息队列
- // uid:img,
- // msg:fmt.Sprintln(sh...),
- // })
- // }
- // fmt.Print(">>> ")
- // fmt.Println(sh...)
- // Gui_show(Itos(append([]interface{}{">>> "}, sh...)), img)
-
- // msglog.Base_add("房").Log_show_control(false).L(`I: `, sh...)
-}
-
// Msg-礼物处理
func (replyF) send_gift(s string) {
msglog := msglog.Base_add("礼").Log_show_control(false)
return
}
if len(sc_buf) >= 10 {
- for k, _ := range sc_buf {
+ for k := range sc_buf {
delete(sc_buf, k)
break
}
msglog.Log_show_control(false).L(`I: `, logg...)
}
-// Msg-分区排行 使用热门榜替代
-func (replyF) panel(s string) {
- msglog := msglog.Base_add("房").Log_show_control(false)
-
- if note := p.Json().GetValFromS(s, "data.note"); note == nil {
- msglog.L(`E: `, "note", note)
- return
- } else {
- if v, ok := note.(string); ok {
- c.C.Note = v
- }
- fmt.Println("排行", note)
- msglog.L(`I: `, "排行", note)
- }
-}
-
-// Msg-热门榜变动
-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 {
- msglog.L(`E: `, e)
- }
- if type_item.Data.Area_name != `` {
- c.C.Note = type_item.Data.Area_name + " "
- if type_item.Data.Rank == 0 {
- c.C.Note += "50+"
- } else {
- c.C.Note += strconv.Itoa(type_item.Data.Rank)
- }
- fmt.Printf("%s\t%s\n", "热门榜", c.C.Note)
- msglog.L(`I: `, "热门榜", c.C.Note)
- }
-}
-
-// Msg-热门榜变动V2
-func (replyF) hot_rank_changed_v2(s string) {
- msglog := msglog.Base_add("房").Log_show_control(false)
-
- var type_item ws_msg.HOT_RANK_CHANGED_V2
- if e := json.Unmarshal([]byte(s), &type_item); e != nil {
- msglog.L(`E: `, e)
- }
- if type_item.Data.AreaName != `` {
- c.C.Note = type_item.Data.AreaName + " "
- if type_item.Data.Rank == 0 {
- c.C.Note += "50+"
- } else {
- c.C.Note += strconv.Itoa(type_item.Data.Rank)
- }
- fmt.Printf("%s\t%s\n", "热门榜", c.C.Note)
- msglog.L(`I: `, "热门榜", c.C.Note)
- }
-}
-
-// Msg-热门榜获得
-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 {
- msglog.L(`E: `, e)
- }
- var tmp = `获得:`
- if type_item.Data.Area_name != `` {
- tmp += type_item.Data.Area_name + " 第"
- }
- if type_item.Data.Rank != 0 {
- tmp += strconv.Itoa(type_item.Data.Rank)
- }
- Gui_show(tmp, "0rank")
- c.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-热门榜获得v2
func (replyF) hot_rank_settlement_v2(s string) {
msglog := msglog.Base_add("房")
}
}
-// Msg-粉丝信息,常刷屏,不显示
-func (replyF) roominfo(s string) {
- fans := p.Json().GetValFromS(s, "data.fans")
- fans_club := p.Json().GetValFromS(s, "data.fans_club")
-
- var sh []interface{}
-
- if fans != nil {
- sh = append(sh, "粉丝总人数:", fans)
- }
- if fans_club != nil {
- sh = append(sh, "粉丝团人数:", fans_club)
- }
-
- if len(sh) != 0 {
- msglog.Base_add("粉").L(`I: `, sh...)
- }
-}
-
// Msg-弹幕处理
type Danmu_item struct {
msg string
func Itos(i []interface{}) string {
r := ""
for _, v := range i {
- switch v.(type) {
+ switch v := v.(type) {
case string:
- r += v.(string)
+ r += v
case int:
- r += strconv.Itoa(v.(int))
+ r += strconv.Itoa(v)
case int64:
- r += strconv.Itoa(int(v.(int64)))
+ r += strconv.Itoa(int(v))
case float64:
- r += strconv.Itoa(int(v.(float64)))
+ r += strconv.Itoa(int(v))
default:
fmt.Println("unkonw type", v)
}
return true
})
- req := t.reqPool.Get()
- defer t.reqPool.Put(req)
- r := req.Item.(*reqf.Req)
- if e := r.Reqf(reqf.Rval{
- Url: t.common.Live[0],
- Retry: 10,
- SleepTime: 1000,
- Proxy: t.common.Proxy,
- Header: map[string]string{
- `User-Agent`: `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.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`,
- `Pragma`: `no-cache`,
- `Cache-Control`: `no-cache`,
- `Referer`: "https://live.bilibili.com/",
- `Cookie`: reqf.Map_2_Cookies_String(CookieM),
- `Connection`: `close`,
- },
- Timeout: 5 * 1000,
- JustResponseCode: true,
- }); e != nil {
- t.log.L(`W: `, e)
- }
+ for _, v := range t.common.Live {
+ req := t.reqPool.Get()
+ r := req.Item.(*reqf.Req)
+ if e := r.Reqf(reqf.Rval{
+ Url: v,
+ Retry: 10,
+ SleepTime: 1000,
+ Proxy: t.common.Proxy,
+ Header: map[string]string{
+ `User-Agent`: `Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:103.0) Gecko/20100101 Firefox/103.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`,
+ `Pragma`: `no-cache`,
+ `Cache-Control`: `no-cache`,
+ `Referer`: "https://live.bilibili.com/",
+ `Cookie`: reqf.Map_2_Cookies_String(CookieM),
+ `Connection`: `close`,
+ },
+ Timeout: 5 * 1000,
+ JustResponseCode: true,
+ }); e != nil {
+ t.log.L(`W: `, e)
+ }
- if r.Response == nil {
- t.log.L(`W: `, `live响应错误`)
- return false
- } else if r.Response.StatusCode != 200 {
- t.log.L(`W: `, `live响应错误`, r.Response.Status, string(r.Respon))
- return false
+ if r.Response == nil {
+ t.log.L(`W: `, `live响应错误`)
+ t.common.Live = t.common.Live[1:]
+ } else if r.Response.StatusCode != 200 {
+ t.log.L(`W: `, `live响应错误`, r.Response.Status, string(r.Respon))
+ t.common.Live = t.common.Live[1:]
+ }
+ t.reqPool.Put(req)
}
- return true
+
+ return len(t.common.Live) != 0
}
func (t *M4SStream) fetchParseM3U8() (m4s_links []*m4s_link_item, m3u8_addon []byte, e error) {
func (t *M4SStream) saveStreamFlv() (e error) {
//对每个直播流进行尝试
for _, v := range t.common.Live {
- //结束退出
- if !t.Status.Islive() {
- return
- }
-
surl, err := url.Parse(v)
if err != nil {
t.log.L(`E: `, err)
e = err
- break
+ continue
}
+ //结束退出
+ if !t.Status.Islive() {
+ return
+ }
+
+ // 如果被主动关闭,则退出saveStreamFlv,否则继续尝试其他live
+ s := signal.Init()
+
//开始获取
req := t.reqPool.Get()
{
- s := signal.Init()
r := req.Item.(*reqf.Req)
go func() {
}
}()
- out, err := os.Create(t.Current_save_path + `0.flv`)
- if err != nil {
- out.Close()
- }
+ out := file.New(t.Current_save_path+`0.flv`, -1, true).File()
rc, rw := io.Pipe()
var leastReadUnix = time.Now().Unix()
r.Cancel()
return
}
+ if v, ok := c.C.K_v.LoadV(`直播流清晰度`).(float64); ok {
+ if t.config.want_qn != int(v) {
+ t.log.L(`I: `, "直播流清晰度改变:", t.common.Qn[t.config.want_qn], "=>", t.common.Qn[int(v)])
+ t.config.want_qn = int(v)
+ s.Done()
+ r.Cancel()
+ return
+ }
+ }
}
}
}()
return true
})
+ t.log.L(`I: `, `flv下载开始`)
+
if err := r.Reqf(reqf.Rval{
Url: surl.String(),
SaveToPipeWriter: rw,
t.log.L(`E: `, `flv下载失败:`, err)
}
}
- s.Done()
}
t.reqPool.Put(req)
+
+ if s.Islive() {
+ s.Done()
+ } else {
+ return
+ }
}
e = errors.New("未能找到可用流服务器")
// 均衡负载
if link_url, e := url.Parse(link.Url); e == nil {
if t.stream_hosts.Len() != 1 {
- t.stream_hosts.Range(func(key, value interface{}) bool {
+ t.stream_hosts.Range(func(key, _ interface{}) bool {
// 故障转移
if link.status == 3 && link_url.Host == key.(string) {
return true
break
}
+ if v, ok := c.C.K_v.LoadV(`直播流清晰度`).(float64); ok {
+ if t.config.want_qn != int(v) {
+ t.log.L(`I: `, "直播流清晰度改变:", t.common.Qn[t.config.want_qn], "=>", t.common.Qn[int(v)])
+ t.config.want_qn = int(v)
+ return
+ }
+ }
+
// 刷新流地址
// 偶尔刷新后的切片编号与原来不连续,故不再提前检查,直到流获取失败再刷新
// if time.Now().Unix()+60 > t.stream_expires {
}
return false
},
- `close`: func(data interface{}) bool {
+ `close`: func(_ interface{}) bool {
close(cancel)
return true
},
}
return false
},
- `close`: func(data interface{}) bool {
+ `close`: func(_ interface{}) bool {
close(cancel)
return true
},
"encoding/json"
"errors"
"fmt"
- "io/ioutil"
"net/url"
"os/exec"
"strings"
}
}
- bb, err := ioutil.ReadFile("config/config_tts.json")
+ bb, err := file.New("config/config_tts.json", 0, true).ReadAll(100, 1<<16)
if err != nil {
return
}
}
return false
},
- `change_room`: func(data interface{}) bool {
+ `change_room`: func(_ interface{}) bool {
for {
select {
case <-tts_List:
return false
}
}
- return false
},
})
}
tts_log.L(`E: `, err)
return
}
-
- return
}
func play() {
voice := xfVoice
if voice == `random` {
- for k, _ := range xfVmap {
+ for k := range xfVmap {
voice = k
break
}
--- /dev/null
+package part
+
+type LIVE_INTERACTIVE_GAME struct {
+ Cmd string `json:"cmd"`
+ Data struct {
+ Type int `json:"type"`
+ UID int `json:"uid"`
+ Uname string `json:"uname"`
+ Uface string `json:"uface"`
+ GiftID int `json:"gift_id"`
+ GiftName string `json:"gift_name"`
+ GiftNum int `json:"gift_num"`
+ Price int `json:"price"`
+ Paid bool `json:"paid"`
+ Msg string `json:"msg"`
+ FansMedalLevel int `json:"fans_medal_level"`
+ GuardLevel int `json:"guard_level"`
+ Timestamp int `json:"timestamp"`
+ AnchorLottery interface{} `json:"anchor_lottery"`
+ PkInfo interface{} `json:"pk_info"`
+ AnchorInfo interface{} `json:"anchor_info"`
+ } `json:"data"`
+}
//使用带tag的消息队列在功能间传递消息
c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `flash_room`: func(data interface{}) bool { //房间重进
+ `flash_room`: func(_ interface{}) bool { //房间重进
select {
case flash_room_chan <- struct{}{}:
default:
}
return false
},
- `change_room`: func(data interface{}) bool { //房间改变
+ `change_room`: func(_ interface{}) bool { //房间改变
c.C.Rev = 0.0 // 营收
c.C.Renqi = 1 // 人气置1
c.C.Watched = 0 // 观看人数
}
return false
},
- `gtk_close`: func(data interface{}) bool { //gtk关闭信号
+ `gtk_close`: func(_ interface{}) bool { //gtk关闭信号
interrupt <- os.Interrupt
return false
},
F.Get(&c.C).Get(`GuardNum`)
//使用带tag的消息队列在功能间传递消息
c.C.Danmu_Main_mq.Pull_tag(msgq.FuncMap{
- `guard_update`: func(data interface{}) bool { //舰长更新
+ `guard_update`: func(_ interface{}) bool { //舰长更新
go F.Get(&c.C).Get(`GuardNum`)
return false
},
`change_room`: func(data interface{}) bool { //换房时退出当前房间
return true
},
- `new day`: func(data interface{}) bool { //日期更换
+ `new day`: func(_ interface{}) bool { //日期更换
//每日签到
F.Dosign()
// //获取用户版本 不再需要
"网络中断不退出": true,
"http代理地址-help":"例http://127.0.0.1:38223 为空时不使用",
"http代理地址":"",
- "启动时显示ip":true
+ "启动时显示ip":true,
+ "几秒后重载-help":"最少间隔60s,-1时不重载",
+ "几秒后重载":60
}
\ No newline at end of file
github.com/mdp/qrterminal/v3 v3.0.0 // indirect
github.com/miekg/dns v1.1.50 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
- github.com/qydysky/part v0.10.14 // indirect
+ github.com/qydysky/part v0.10.17 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e // indirect
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
github.com/qydysky/part v0.10.12/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
github.com/qydysky/part v0.10.14 h1:Pf13/0mbl7Gc0qRnJXUDnzALqJKRDL88ZbQm5JI2nS0=
github.com/qydysky/part v0.10.14/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
+github.com/qydysky/part v0.10.15 h1:vKGhzhY5HGJGOzygkbBbEgs0Nmc6ddNNhqLf/a4fxQk=
+github.com/qydysky/part v0.10.15/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
+github.com/qydysky/part v0.10.16 h1:mzrCQEPkQOH4MK+vdPAvJboYhQYBdiKbw2QdvDKinX0=
+github.com/qydysky/part v0.10.16/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
+github.com/qydysky/part v0.10.17 h1:xcMgJaEvPlOPAEfOniTZZM/pDiafWW3FA5ZQXNPthpI=
+github.com/qydysky/part v0.10.17/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.5+incompatible h1:OloQyEerMi7JUrXiNzy8wQ5XN+baemxSl12QgIzt0jc=
github.com/shirou/gopsutil v3.21.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/gofrs/uuid v4.3.0+incompatible
github.com/gotk3/gotk3 v0.6.1
github.com/mdp/qrterminal/v3 v3.0.0
- github.com/qydysky/part v0.10.14
+ github.com/qydysky/part v0.10.17
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966
golang.org/x/text v0.3.8
github.com/qydysky/part v0.10.13/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
github.com/qydysky/part v0.10.14 h1:Pf13/0mbl7Gc0qRnJXUDnzALqJKRDL88ZbQm5JI2nS0=
github.com/qydysky/part v0.10.14/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
+github.com/qydysky/part v0.10.15 h1:vKGhzhY5HGJGOzygkbBbEgs0Nmc6ddNNhqLf/a4fxQk=
+github.com/qydysky/part v0.10.15/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
+github.com/qydysky/part v0.10.16 h1:mzrCQEPkQOH4MK+vdPAvJboYhQYBdiKbw2QdvDKinX0=
+github.com/qydysky/part v0.10.16/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
+github.com/qydysky/part v0.10.17 h1:xcMgJaEvPlOPAEfOniTZZM/pDiafWW3FA5ZQXNPthpI=
+github.com/qydysky/part v0.10.17/go.mod h1:B3GD/j5jmvwfKtnzDWqRYFqnwOXEyoUg/jShFk1yQSM=
github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=