demo/*.mkv
demo/qtbox
demo/main
+demo/face/*
}
return
+}
+
+var get_face_src_limit = p.Limit(1, 1000, 2000)
+
+func Get_face_src(uid string) (string) {
+ if uid == "" {return ""}
+ //等待令牌时阻塞,超时返回true
+ if get_face_src_limit.TO() {return ""}
+ apilog.Base(-1, "获取face")
+ defer apilog.Base(0)
+
+ req := p.Req()
+ if err := req.Reqf(p.Rval{
+ Url:"https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuMedalAnchorInfo?ruid=" + uid,
+ Referer:"https://live.bilibili.com/" + strconv.Itoa(c.Roomid),
+ Timeout:10,
+ Retry:2,
+ });err != nil {
+ apilog.E(err)
+ return ""
+ }
+ res := string(req.Respon)
+ if msg := p.Json().GetValFromS(res, "message");msg == nil || msg != "0" {
+ apilog.E("message", msg)
+ return ""
+ }
+
+ rface := p.Json().GetValFromS(res, "data.rface")
+ if rface == nil {
+ apilog.E("data.rface", rface)
+ return ""
+ }
+ return rface.(string) + `@58w_58h`
}
\ No newline at end of file
以下内容可能过时,点击查看[当前支持功能](https://github.com/qydysky/bili_danmu/blob/master/Reply/F.go#L16)
```
其他功能
-自动化功能、挑选有价值的弹幕,可在demo/config.json覆盖默认控制
+自动化功能、挑选有价值的弹幕,可在demo/config_F.json覆盖默认控制
//功能开关
var AllF = map[string]bool{
"Saveflv":true,//保存直播流(仅高清)
"Shortdanmu":true,//上下文相同文字缩减
}
```
+以下内容可能过时,其他小功能
+```
+弹幕重连
+直播流开播自动下载
+直播流下载重连
+...
+```
+
### demo
- 已配置了[go环境](https://golang.google.cn/dl/)

[截图地址](//zdir.ntsdtt.bid/ALL/Admin/Remote/%E5%9B%BE%E7%89%87/Screenshot_20200926_173834.png)
+Gtk弹幕窗
+
+
+
+[截图地址](//zdir.ntsdtt.bid/ALL/Admin/Remote/%E5%9B%BE%E7%89%87/Screenshot_20201021_082757.png)
+
Qt弹幕窗

[截图地址](//zdir.ntsdtt.bid/ALL/Admin/Remote/%E5%9B%BE%E7%89%87/Screenshot_20201002_045627.png)
}
{//重试
- retry := 20
- for retry > 0 && rr.ResponseCode != 200 {
- if e := rr.Reqf(p.Rval{
- Url:c.Live[cuLinkIndex],
- Retry:10,
- SleepTime:5,
- Cookie:Cookie,
- Timeout:-1,
- JustResponseCode:true,
- }); e != nil{l.W(e)}
- p.Sys().Timeoutf(2)
- retry -= 1
- }
- if retry == 0 {
- p.Sys().Timeoutf(5)
+ if e := rr.Reqf(p.Rval{
+ Url:c.Live[cuLinkIndex],
+ Retry:10,
+ SleepTime:5,
+ Cookie:Cookie,
+ Timeout:-1,
+ JustResponseCode:true,
+ }); e != nil{l.W(e)}
+
+ if rr.ResponseCode != 200 {
saveflv.wait.Done()
saveflv.cancel.Done()
cuLinkIndex += 1
fmt.Println(sh...)
fmt.Print("====\n\n")
- Gui_show("\n====")
- Gui_show(Itos(sh))
- Gui_show("====\n")
+ // Gui_show("\n====")
+ Gui_show(Itos(sh), "0buyguide")
+ // Gui_show("====\n")
msglog.Base(1, "礼").Fileonly(true).I(sh...).Fileonly(false)
}
fmt.Println(sh...)
fmt.Print("====\n\n")
- Gui_show("\n====")
- Gui_show(Itos(sh))
- Gui_show("====\n")
+ // Gui_show("\n====")
+ Gui_show(Itos(sh), "0jiezou")
+ // Gui_show("====\n")
msglog.Base(1, "礼").I(sh...)
if area_name != nil {
sh = append(sh, area_name)
}
- Gui_show(Itos(sh))
+ Gui_show(Itos(sh), "0room")
msglog.Base(1, "房").I(sh...)
}
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, "总督")
- case 2:sh = append(sh, "提督")
- case 3:sh = append(sh, "舰长")
+ 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)
}
}
fmt.Print(">>> ")
fmt.Println(sh...)
- Gui_show(Itos(append([]interface{}{">>> "}, sh...)))
+ Gui_show(Itos(append([]interface{}{">>> "}, sh...)), img)
msglog.Base(1, "房").Fileonly(true).I(sh...).Fileonly(false)
}
fmt.Println(sh...)
fmt.Print("====\n\n")
- Gui_show("\n====")
- Gui_show(Itos(sh))
- Gui_show("====\n")
+ // Gui_show("\n====")
+ Gui_show(Itos(sh), "0gift")
+ // Gui_show("====\n")
msglog.Base(1, "礼").Fileonly(true).I(sh...).Fileonly(false)
}
msglog.E("uname", uname)
return
} else {
- Gui_show(Itos([]interface{}{"用户", uname, "已被封禁"}))
+ Gui_show(Itos([]interface{}{"用户", uname, "已被封禁"}), "0room")
fmt.Println("用户", uname, "已被封禁")
msglog.Base(1, "封").I("用户", uname, "已被封禁")
}
Saveflv_wait()
}
if p.Sys().Type(roomid) == "float64" {
- Gui_show(Itos([]interface{}{"房间", roomid, "下播了"}))
+ Gui_show(Itos([]interface{}{"房间", roomid, "下播了"}), "0room")
msglog.I("房间", int(roomid.(float64)), "下播了")
return
}
- Gui_show(Itos([]interface{}{"房间", roomid, "下播了"}))
+ Gui_show(Itos([]interface{}{"房间", roomid, "下播了"}), "0room")
msglog.I("房间", roomid, "下播了")
}
}
go Saveflvf()
}
if p.Sys().Type(roomid) == "float64" {
- Gui_show(Itos([]interface{}{"房间", roomid, "开播了"}))
+ Gui_show(Itos([]interface{}{"房间", roomid, "开播了"}), "0room")
msglog.I("房间", int(roomid.(float64)), "开播了")
return
}
- Gui_show(Itos([]interface{}{"房间", roomid, "开播了"}))
+ Gui_show(Itos([]interface{}{"房间", roomid, "开播了"}), "0room")
msglog.I("房间", roomid, "开播了")
}
}
}
fmt.Println("\n====")
fmt.Println(sh...)
- Gui_show("\n====")
- Gui_show(Itos(sh))
+ // Gui_show("\n====")
if message != nil && message.(string) != ""{
fmt.Println(message)
- Gui_show(message.(string))
+ // Gui_show(message.(string))
sh = append(sh, message)
}
if message_jpn != nil && message.(string) != message_jpn.(string) && message_jpn.(string) != "" {
fmt.Println(message_jpn)
- Gui_show(message_jpn.(string))
+ // Gui_show(message_jpn.(string))
sh = append(sh, message_jpn)
}
fmt.Print("====\n\n")
{//额外
Assf(fmt.Sprintln(sh...))
- Gui_show("====\n")
+ // Gui_show("====\n")
+ Gui_show(Itos(sh), "0superchat")
}
msglog.Base(1, "礼").Fileonly(true).I(sh...).Fileonly(false)
}
infob := info.([]interface{})
msg := infob[1].(string)
auth := infob[2].([]interface{})[1]
+ uid := strconv.Itoa(int(infob[2].([]interface{})[0].(float64)))
msglog.Fileonly(true)
defer msglog.Fileonly(false)
return
}
}
- Msg_showdanmu(auth, msg)
+ Msg_showdanmu(auth, msg, uid)
}
}
//弹幕显示
//由于额外功能有些需要显示,为了统一管理,使用此方法进行处理
-func Msg_showdanmu(auth interface{}, msg string) {
+func Msg_showdanmu(auth interface{}, m ...string) {
+ msg := m[0]
{//附加功能 更少弹幕
if Lessdanmuf(msg, 20) > 0.7 {//与前20条弹幕重复的字数占比度>0.7的屏蔽
if auth != nil {msglog.I(auth, ":", msg)}
return
} else {msg = _msg}
Assf(msg)//ass
- Gui_show(fmt.Sprint(auth) +`: `+ msg)
+ if auth != nil {
+ Gui_show(fmt.Sprint(auth) +`: `+ msg, m[1])
+ } else {
+ Gui_show(msg)
+ }
}
fmt.Println(msg)
if auth != nil {msglog.I(auth, ":", msg)}
}
-func Gui_show(m string){
- if QtOn {QtDanmuChan <- m}
- if Gtk_on {Gtk_danmuChan <- m}
+func Gui_show(m ...string){
+ //m[0]:msg m[1]:uid
+ if QtOn {QtDanmuChan <- m[0]}
+ if Gtk_on {
+ if len(m) > 1 {
+ Gtk_danmuChan_uid <- m[1]
+ } else {Gtk_danmuChan_uid <- ""}
+ Gtk_danmuChan <- m[0]
+ }
}
func Itos(i []interface{}) string {
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
+ "github.com/gotk3/gotk3/gdk"
+ p "github.com/qydysky/part"
+ F "github.com/qydysky/bili_danmu/F"
)
const appId = "com.github.qydysky.bili_danmu.reply"
-var BList = list.New()
+var BTList = list.New()
+var BIList = list.New()
var (
Gtk_on bool
Gtk_Tra bool
- Gtk_danmuChan chan string = make(chan string, 10)
+ Gtk_img_path string = "face"
+ Gtk_danmuChan chan string = make(chan string, 100)
+ Gtk_danmuChan_uid chan string = make(chan string, 100)
)
func Gtk_danmu() {
}
}
- var y func()
- y = func(){
+ var y func(bool)
+ y = func(tra bool){
+ Gtk_Tra = true
+
s:=<-Gtk_danmuChan
t,_ := gtk.TextViewNew();
+ BTList.PushBack(t)
+ t.SetMarginStart(5)
t.SetEditable(false)
t.SetHExpand(true)
t.SetVExpand(false)
t.SetWrapMode(gtk.WRAP_WORD_CHAR)
+
+ img,_ :=gtk.ImageNew();
+ BIList.PushBack(img)
+
var handle glib.SignalHandle
handle,_ = t.Connect("size-allocate", func(){
+ Gtk_Tra = false
b,e := t.GetBuffer()
if e != nil {return}
b.SetText(s)
+
+ img_src := load_face(<-Gtk_danmuChan_uid)
+ pixbuf,e := gdk.PixbufNewFromFileAtSize(img_src, 40, 40);
+ if e != nil {return}
+ img.SetFromPixbuf(pixbuf)
t.HandlerDisconnect(handle)
- if Gtk_Tra {
- tmp := scrolledwindow0.GetVAdjustment()
- tmp.SetValue(tmp.GetUpper())
+ if tra {
+ handle,_ = t.Connect("size-allocate", func(){
+ tmp := scrolledwindow0.GetVAdjustment()
+ tmp.SetValue(tmp.GetUpper())
+ t.HandlerDisconnect(handle)
+ })
}
- if len(Gtk_danmuChan) != 0 {y()}
+ if len(Gtk_danmuChan) != 0 {y(tra)}
})
- {
- tmp := scrolledwindow0.GetVAdjustment()
- h := viewport0.GetViewWindow().WindowGetHeight()
- Gtk_Tra = tmp.GetUpper() - tmp.GetValue() < float64(h) + 10
- }
-
tmp,_ := t.Container.Widget.Cast()
- loc := int(grid0.Container.GetChildren().Length());
+ loc := BTList.Len();
grid0.InsertRow(loc);
- grid0.Attach(tmp, 0, loc, 1, 1)
- if Gtk_Tra && loc > 50 {
- l,_ := grid0.GetChildAt(0, 0)
- l.ToWidget().Destroy()
+ grid0.Attach(img, 0, loc - 1, 1, 1)
+ grid0.Attach(tmp, 1, loc - 1, 1, 1)
+ for tra && BTList.Len() > 50 {
+ BTList.Remove(BTList.Front()).(*gtk.TextView).Destroy()
+ BIList.Remove(BIList.Front()).(*gtk.Image).Destroy()
grid0.RemoveRow(0)
}
win.ShowAll()
}
glib.TimeoutAdd(uint(100), func() bool {
- if len(Gtk_danmuChan) != 0 {y()}
-
+ if !Gtk_Tra && len(Gtk_danmuChan) != 0 {
+ tmp := scrolledwindow0.GetVAdjustment()
+ h := viewport0.GetViewWindow().WindowGetHeight()
+ y(tmp.GetUpper() - tmp.GetValue() < float64(h) * 1.3)
+ }
return true
})
win.Show()
func onMainWindowDestroy() {
log.Println("onMainWindowDestroy")
}
+
+func load_face(uid string) string {
+ defaultuid := "0default"
+ if uid != "" && p.Checkfile().IsExist(Gtk_img_path + `/` + uid) {return Gtk_img_path + `/` + uid}
+ if src := F.Get_face_src(uid);src != "" {
+ req := p.Req()
+ if e := req.Reqf(p.Rval{
+ Url:src,
+ SaveToPath:Gtk_img_path + `/` + uid,
+ Timeout:3,
+ }); e != nil{log.Println(e);return Gtk_img_path + `/` + defaultuid}
+ return Gtk_img_path + `/` + uid
+ }
+ return Gtk_img_path + `/` + defaultuid
+}
\ No newline at end of file
-{
- "cmd": "DANMU_MSG",
- "info": [
- [
- 0,
- 1,
- 25,
- 16777215,
- 1601981229550,
- 925883313,
- 0,
- "7a317c96",
- 0,
- 0,
- 0,
- ""
- ],
- "鬼也是玩家吗",
- [
- 332143945,
- "爱吃甜食的叱干巧曼",
- 0,
- 0,
- 0,
- 10000,
- 1,
- ""
- ],
- [
- 7,
- "猫良",
- "数字猫",
- 3839755,
- 5805790,
- "",
- 0,
- 5805790,
- 5805790,
- 5805790,
- 0,
- 1,
- 6009977
- ],
- [
- 7,
- 0,
- 9868950,
- "\u003e50000"
- ],
- [
- "",
- ""
- ],
- 0,
- 0,
- null,
- {
- "ts": 1601981229,
- "ct": "EE03F05F"
- },
- 0,
- 0,
- null,
- null,
- 0
- ]
-}
\ No newline at end of file
+[
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 1,
+ 25,
+ 16777215,
+ 1601981229550,
+ 925883313,
+ 0,
+ "7a317c96",
+ 0,
+ 0,
+ 0,
+ ""
+ ],
+ "鬼也是玩家吗",
+ [
+ 332143945,
+ "爱吃甜食的叱干巧曼",
+ 0,
+ 0,
+ 0,
+ 10000,
+ 1,
+ ""
+ ],
+ [
+ 7,
+ "猫良",
+ "数字猫",
+ 3839755,
+ 5805790,
+ "",
+ 0,
+ 5805790,
+ 5805790,
+ 5805790,
+ 0,
+ 1,
+ 6009977
+ ],
+ [
+ 7,
+ 0,
+ 9868950,
+ "\u003e50000"
+ ],
+ [
+ "",
+ ""
+ ],
+ 0,
+ 0,
+ null,
+ {
+ "ts": 1601981229,
+ "ct": "EE03F05F"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ },
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 4,
+ 25,
+ 14893055,
+ 1603237288525,
+ 1603237302,
+ 0,
+ "0d9a2aee",
+ 0,
+ 0,
+ 5,
+ "#1953BAFF,#3353BAFF,#3353BAFF"
+ ],
+ "谢谢VVVVVega_赠送的3个吃瓜~",
+ [
+ 2905179,
+ "猫辞の小哥哥",
+ 1,
+ 0,
+ 0,
+ 10000,
+ 1,
+ "#00D1F1"
+ ],
+ [],
+ [
+ 25,
+ 0,
+ 5805790,
+ "\u003e50000"
+ ],
+ [
+ "title-131-2",
+ "title-131-2"
+ ],
+ 0,
+ 3,
+ null,
+ {
+ "ts": 1603237288,
+ "ct": "8E0D62CD"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ },
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 4,
+ 25,
+ 14893055,
+ 1603237313448,
+ 2130913535,
+ 0,
+ "dc5c2dd7",
+ 0,
+ 0,
+ 5,
+ "#1953BAFF,#3353BAFF,#3353BAFF"
+ ],
+ "点歌 drop pop candy",
+ [
+ 68283513,
+ "此方伍仁",
+ 1,
+ 0,
+ 0,
+ 10000,
+ 1,
+ "#00D1F1"
+ ],
+ [
+ 25,
+ "猫辞的",
+ "猫辞猫辞猫",
+ 1033927,
+ 398668,
+ "",
+ 0,
+ 6809855,
+ 398668,
+ 6850801,
+ 3,
+ 1,
+ 17794913
+ ],
+ [
+ 14,
+ 0,
+ 6406234,
+ "\u003e50000"
+ ],
+ [
+ "",
+ ""
+ ],
+ 0,
+ 3,
+ null,
+ {
+ "ts": 1603237313,
+ "ct": "8858B986"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ },
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 1,
+ 25,
+ 16772431,
+ 1603237890865,
+ -847143969,
+ 0,
+ "94ccf920",
+ 0,
+ 0,
+ 5,
+ "#1953BAFF,#3353BAFF,#3353BAFF"
+ ],
+ "(`・ω・´)",
+ [
+ 4995588,
+ "桜花喵喵_Official",
+ 1,
+ 0,
+ 0,
+ 10000,
+ 1,
+ "#00D1F1"
+ ],
+ [
+ 1,
+ "渣女",
+ "清泉qwq",
+ 755732,
+ 6406234,
+ "",
+ 0,
+ 6406234,
+ 6406234,
+ 6406234,
+ 0,
+ 1,
+ 47355
+ ],
+ [
+ 28,
+ 0,
+ 5805790,
+ "\u003e50000"
+ ],
+ [
+ "title-360-1",
+ "title-360-1"
+ ],
+ 0,
+ 3,
+ null,
+ {
+ "ts": 1603237890,
+ "ct": "64A75043"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ },
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 1,
+ 25,
+ 5566168,
+ 1603238036517,
+ 389215823,
+ 0,
+ "276ad711",
+ 0,
+ 0,
+ 0,
+ ""
+ ],
+ "叫 可乐",
+ [
+ 407515746,
+ "绿洲骆驼_",
+ 0,
+ 0,
+ 0,
+ 10000,
+ 1,
+ ""
+ ],
+ [
+ 13,
+ "猫辞的",
+ "猫辞猫辞猫",
+ 1033927,
+ 16746162,
+ "",
+ 0,
+ 16746162,
+ 16746162,
+ 16746162,
+ 0,
+ 1,
+ 17794913
+ ],
+ [
+ 10,
+ 0,
+ 9868950,
+ "\u003e50000"
+ ],
+ [
+ "",
+ ""
+ ],
+ 0,
+ 0,
+ null,
+ {
+ "ts": 1603238036,
+ "ct": "BDCA4AF3"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ },
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 1,
+ 25,
+ 5566168,
+ 1603238308586,
+ -1373134828,
+ 0,
+ "6cf1b82b",
+ 0,
+ 0,
+ 0,
+ ""
+ ],
+ "上课(=・ω・=)",
+ [
+ 289838259,
+ "菲莉娅Official",
+ 0,
+ 0,
+ 0,
+ 10000,
+ 1,
+ ""
+ ],
+ [
+ 22,
+ "伞妃",
+ "小伞一把Kokasa",
+ 26283,
+ 1725515,
+ "",
+ 0,
+ 6809855,
+ 1725515,
+ 5414290,
+ 3,
+ 1,
+ 1740548
+ ],
+ [
+ 24,
+ 0,
+ 5805790,
+ "\u003e50000"
+ ],
+ [
+ "title-352-1",
+ "title-352-1"
+ ],
+ 0,
+ 0,
+ null,
+ {
+ "ts": 1603238308,
+ "ct": "71FE2286"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ },
+ {
+ "cmd": "DANMU_MSG",
+ "info": [
+ [
+ 0,
+ 4,
+ 25,
+ 16750592,
+ 1603238461862,
+ 1073881206,
+ 0,
+ "3b60f872",
+ 0,
+ 0,
+ 5,
+ "#1953BAFF,#3353BAFF,#3353BAFF"
+ ],
+ "25牌牌就蓝了",
+ [
+ 19277984,
+ "养猫博士",
+ 1,
+ 1,
+ 1,
+ 10000,
+ 1,
+ "#00D1F1"
+ ],
+ [],
+ [
+ 49,
+ 0,
+ 16746162,
+ 8170
+ ],
+ [
+ "title-306-1",
+ "title-306-1"
+ ],
+ 0,
+ 3,
+ null,
+ {
+ "ts": 1603238461,
+ "ct": "E82EAD"
+ },
+ 0,
+ 0,
+ null,
+ null,
+ 0
+ ]
+ }
+]
\ No newline at end of file
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
+ <property name="row_spacing">3</property>
+ <property name="column_spacing">2</property>
+ <child>
+ <placeholder/>
+ </child>
<child>
<placeholder/>
</child>