mirror of
https://github.com/tursom/libbili-go.git
synced 2024-12-25 20:30:30 +08:00
create project
This commit is contained in:
commit
215855af08
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
# idea
|
||||
.idea/
|
||||
|
||||
# python venv
|
||||
venv/
|
||||
|
||||
# test cookie file
|
||||
live/Room_test.cookie.txt
|
||||
|
||||
vendor/
|
13
go.mod
Normal file
13
go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module libbili
|
||||
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/tursom/GoCollections v0.1.4
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/timandy/routine v1.0.5 // indirect
|
||||
golang.org/x/net v0.2.0 // indirect
|
||||
)
|
18
go.sum
Normal file
18
go.sum
Normal file
@ -0,0 +1,18 @@
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/timandy/routine v1.0.5 h1:JBVo2mOZlYVsod/v1jjmjSzxTH84x3vS9b6k4ZBTvdc=
|
||||
github.com/timandy/routine v1.0.5/go.mod h1:BT7/+zFFZkugUiUUClwDgZjQ/PNcivY1hqRLXQAftGU=
|
||||
github.com/tursom/GoCollections v0.1.4 h1:NV3vK2jmkzseEgpcKv716DlUEl8BzCyk3wM1njr0Cp8=
|
||||
github.com/tursom/GoCollections v0.1.4/go.mod h1:kwFG//g3vbmDShsnY8Vm47PsTUBWgk83RcEPYZLgmZU=
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
252
live/Room.go
Normal file
252
live/Room.go
Normal file
@ -0,0 +1,252 @@
|
||||
package live
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"mime/multipart"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
)
|
||||
|
||||
type (
|
||||
Room interface {
|
||||
SetCookie(cookie string)
|
||||
ID() uint32
|
||||
Send(msg string) (*DanmuResp, exceptions.Exception)
|
||||
SendDanmu(danmu *Danmu) (*DanmuResp, exceptions.Exception)
|
||||
GetDanmuColors() (*DanmuColors, exceptions.Exception)
|
||||
}
|
||||
|
||||
roomImpl struct {
|
||||
id uint32
|
||||
cookie string
|
||||
}
|
||||
|
||||
Danmu struct {
|
||||
Bubble int32 `json:"bubble,omitempty"`
|
||||
Msg string `json:"msg,omitempty"`
|
||||
Color string `json:"color,omitempty"`
|
||||
Mode int32 `json:"mode,omitempty"`
|
||||
Fontsize int32 `json:"fontsize,omitempty"`
|
||||
Rnd int64 `json:"rnd,omitempty"`
|
||||
RoomId uint32 `json:"roomid,omitempty"`
|
||||
Csrf string `json:"csrf,omitempty"`
|
||||
CsrfToken string `json:"csrf_token,omitempty"`
|
||||
}
|
||||
|
||||
DanmuResp struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
ModeInfo struct {
|
||||
Mode int `json:"mode"`
|
||||
ShowPlayerType int `json:"show_player_type"`
|
||||
Extra string `json:"extra"`
|
||||
} `json:"mode_info"`
|
||||
} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
DanmuColors struct {
|
||||
Code int `json:"code"`
|
||||
Data struct {
|
||||
Group []struct {
|
||||
Name string `json:"name"`
|
||||
Sort int `json:"sort"`
|
||||
Color []struct {
|
||||
Name string `json:"name"`
|
||||
Color string `json:"color"`
|
||||
ColorHex string `json:"color_hex"`
|
||||
Status int `json:"status"`
|
||||
Weight int `json:"weight"`
|
||||
ColorId int `json:"color_id"`
|
||||
Origin int `json:"origin"`
|
||||
} `json:"color"`
|
||||
} `json:"group"`
|
||||
Mode []struct {
|
||||
Name string `json:"name"`
|
||||
Mode int `json:"mode"`
|
||||
Type string `json:"type"`
|
||||
Status int `json:"status"`
|
||||
} `json:"mode"`
|
||||
} `json:"data"`
|
||||
Message string `json:"message"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
client = resty.New()
|
||||
)
|
||||
|
||||
func NewRoom(id uint32) Room {
|
||||
return &roomImpl{
|
||||
id: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *roomImpl) SetCookie(cookie string) {
|
||||
r.cookie = cookie
|
||||
}
|
||||
|
||||
func (r *roomImpl) ID() uint32 {
|
||||
return r.id
|
||||
}
|
||||
|
||||
func (r *roomImpl) Send(msg string) (*DanmuResp, exceptions.Exception) {
|
||||
if r.cookie == "" {
|
||||
// return err that no cookie set
|
||||
return nil, exceptions.NewIllegalParameterException("cookie not set", nil)
|
||||
}
|
||||
|
||||
return r.SendDanmu(&Danmu{
|
||||
Bubble: 0,
|
||||
Msg: msg,
|
||||
Color: "16777215",
|
||||
Mode: 1,
|
||||
Fontsize: 25,
|
||||
Rnd: time.Now().Unix(),
|
||||
RoomId: r.id,
|
||||
Csrf: "c1b21617a15daf838f505271ff8f5204",
|
||||
CsrfToken: "c1b21617a15daf838f505271ff8f5204",
|
||||
})
|
||||
}
|
||||
|
||||
func (r *roomImpl) SendDanmu(danmu *Danmu) (*DanmuResp, exceptions.Exception) {
|
||||
if r.cookie == "" {
|
||||
// return err that no cookie set
|
||||
return nil, exceptions.NewIllegalParameterException("cookie not set", nil)
|
||||
}
|
||||
|
||||
request := client.R()
|
||||
|
||||
form, boundary, exception := multipartForm(danmu)
|
||||
if exception != nil {
|
||||
return nil, exception
|
||||
}
|
||||
|
||||
request.SetBody(form)
|
||||
|
||||
//request, err := http.NewRequest("POST", "https://api.live.bilibili.com/msg/send", form)
|
||||
//if err != nil {
|
||||
// return nil, exceptions.Package(err)
|
||||
//}
|
||||
|
||||
//request.Header.Add("Accept", "*/*")
|
||||
request.Header.Set("Cookie", r.cookie)
|
||||
//request.Header.Set("Origin", "https://live.bilibili.com")
|
||||
//request.Header.Set("Referer", fmt.Sprintf("https://li|ve.bilibili.com/%d?spm_id_from=444.41.live_users.item.click", r.id))
|
||||
//request.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36")
|
||||
request.Header.Set("Content-Type", fmt.Sprintf("multipart/form-data; boundary=%s", boundary))
|
||||
//request.Header.Set("Sec-Ch-Ua", "\"Google Chrome\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\"")
|
||||
//request.Header.Set("Sec-Ch-Ua-Mobile", "?0")
|
||||
//request.Header.Set("Sec-Ch-Ua-Platform", "\"Windows\"")
|
||||
//request.Header.Set("Sec-Fetch-Dest", "empty")
|
||||
//request.Header.Set("Sec-Fetch-Mode", "cors")
|
||||
//request.Header.Set("Sec-Fetch-Site", "same-site")
|
||||
//request.Header.Set("content-length", strconv.Itoa(len(form)))
|
||||
|
||||
//do, err := http.DefaultClient.Do(request)
|
||||
do, err := request.Post("https://api.live.bilibili.com/msg/send")
|
||||
if do.StatusCode() != 200 {
|
||||
// return err
|
||||
fmt.Println(string(do.Body()))
|
||||
return nil, exceptions.NewPackageException(fmt.Sprintf("send response status failed: %d", do.StatusCode()),
|
||||
exceptions.Cfg().SetCause(do.StatusCode))
|
||||
}
|
||||
|
||||
var resp DanmuResp
|
||||
err = json.Unmarshal(do.Body(), &resp)
|
||||
if err != nil {
|
||||
return nil, exceptions.Package(err)
|
||||
}
|
||||
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
func multipartForm(danmu *Danmu) (formData []byte, boundary string, exception exceptions.Exception) {
|
||||
formBuffer := bytes.NewBuffer(nil)
|
||||
formWriter := multipart.NewWriter(formBuffer)
|
||||
|
||||
err := formWriter.WriteField("bubble", strconv.Itoa(int(danmu.Bubble)))
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("msg", danmu.Msg)
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("color", danmu.Color)
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("mode", strconv.Itoa(int(danmu.Mode)))
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("fontsize", strconv.Itoa(int(danmu.Fontsize)))
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("rnd", strconv.FormatInt(danmu.Rnd, 10))
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("roomid", strconv.Itoa(int(danmu.RoomId)))
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("csrf", danmu.Csrf)
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.WriteField("csrf_token", danmu.CsrfToken)
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
err = formWriter.Close()
|
||||
if err != nil {
|
||||
return nil, "", exceptions.Package(err)
|
||||
}
|
||||
|
||||
formBytes := formBuffer.Bytes()
|
||||
fmt.Println(string(formBytes))
|
||||
|
||||
return formBytes, formWriter.Boundary(), nil
|
||||
}
|
||||
|
||||
func (r *roomImpl) GetDanmuColors() (*DanmuColors, exceptions.Exception) {
|
||||
url := fmt.Sprintf("https://api.live.bilibili.com/xlive/web-room/v1/dM/GetDMConfigByGroup?room_id=%d", r.id)
|
||||
|
||||
request := client.R()
|
||||
|
||||
if r.cookie != "" {
|
||||
request.Header.Set("Cookie", r.cookie)
|
||||
}
|
||||
|
||||
response, err := request.Get(url)
|
||||
if err != nil {
|
||||
return nil, exceptions.Package(err)
|
||||
}
|
||||
|
||||
var colors DanmuColors
|
||||
err = json.Unmarshal(response.Body(), &colors)
|
||||
if err != nil {
|
||||
return nil, exceptions.Package(err)
|
||||
}
|
||||
|
||||
return &colors, nil
|
||||
}
|
66
live/Room.py
Normal file
66
live/Room.py
Normal file
@ -0,0 +1,66 @@
|
||||
import http.client
|
||||
import logging
|
||||
import time
|
||||
|
||||
import httpx
|
||||
|
||||
logging.basicConfig()
|
||||
logging.getLogger().setLevel(logging.DEBUG)
|
||||
|
||||
http.client.HTTPConnection.debuglevel = 1
|
||||
|
||||
# session.proxies = {
|
||||
# 'http': 'http://127.0.0.1:2080',
|
||||
# 'https': 'http://127.0.0.1:2080',
|
||||
# }
|
||||
|
||||
id = 917818
|
||||
|
||||
with open("Room_test.cookie.txt") as cookie_txt:
|
||||
cookie = cookie_txt.read()
|
||||
|
||||
session = httpx.Client(http2=True)
|
||||
|
||||
resp = session.post(
|
||||
"https://api.live.bilibili.com/msg/send",
|
||||
# files=(
|
||||
# ("bubble", (None, "0")),
|
||||
# ("msg", (None, "弹幕测试")),
|
||||
# ("color", (None, "16777215")),
|
||||
# ("mode", (None, "1")),
|
||||
# ("fontsize", (None, "25")),
|
||||
# ("rnd", (None, str(int(time.time())))),
|
||||
# ("roomid", (None, str(id))),
|
||||
# ("csrf", (None, "c1b21617a15daf838f505271ff8f5204")),
|
||||
# ("csrf_token", (None, "c1b21617a15daf838f505271ff8f5204")),
|
||||
# ),
|
||||
data={
|
||||
"bubble", "0",
|
||||
"msg", "弹幕测试",
|
||||
"color", "16777215",
|
||||
"mode", "1",
|
||||
"fontsize", "25",
|
||||
"rnd", str(int(time.time())),
|
||||
"roomid", str(id),
|
||||
"csrf", "c1b21617a15daf838f505271ff8f5204",
|
||||
"csrf_token", "c1b21617a15daf838f505271ff8f5204",
|
||||
},
|
||||
headers={
|
||||
"Accept": "*/*",
|
||||
"Cookie": cookie,
|
||||
# "Origin": "https://live.bilibili.com",
|
||||
# "Referer": f"https://li|ve.bilibili.com/{id}?spm_id_from=444.41.live_users.item.click",
|
||||
# "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
|
||||
# "Sec-Ch-Ua": "\"Google Chrome\";v=\"107\", \"Chromium\";v=\"107\", \"Not=A?Brand\";v=\"24\"",
|
||||
# "Sec-Ch-Ua-Mobile": "?0",
|
||||
# "Sec-Ch-Ua-Platform": "\"Windows\"",
|
||||
# "Sec-Fetch-Dest": "empty",
|
||||
# "Sec-Fetch-Mode": "cors",
|
||||
# "Sec-Fetch-Site": "same-site",
|
||||
},
|
||||
# cookies={
|
||||
# "Cookie": cookie,
|
||||
# },
|
||||
)
|
||||
|
||||
print(resp)
|
50
live/Room_test.go
Normal file
50
live/Room_test.go
Normal file
@ -0,0 +1,50 @@
|
||||
package live
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/tursom/GoCollections/exceptions"
|
||||
)
|
||||
|
||||
func getRoomImpl() (Room, exceptions.Exception) {
|
||||
cookieBytes, err := os.ReadFile("Room_test.cookie.txt")
|
||||
if err != nil {
|
||||
return nil, exceptions.NewPackageException("read cookie file failed", exceptions.Cfg().SetCause(err))
|
||||
}
|
||||
|
||||
room := NewRoom(917818)
|
||||
room.SetCookie(string(cookieBytes))
|
||||
|
||||
return room, nil
|
||||
}
|
||||
|
||||
func Test_roomImpl_Send(t *testing.T) {
|
||||
room, err := getRoomImpl()
|
||||
if err != nil {
|
||||
t.Fatalf("get room impl failed: %s", err)
|
||||
}
|
||||
|
||||
resp, err := room.Send("弹幕测试")
|
||||
if err != nil {
|
||||
t.Fatalf("test send danmu failed: %s", exceptions.GetStackTraceString(err.(exceptions.Exception)))
|
||||
}
|
||||
|
||||
t.Logf("send danmu resp: %v", resp)
|
||||
}
|
||||
|
||||
func Test_roomImpl_GetDanmuColors(t *testing.T) {
|
||||
room, err := getRoomImpl()
|
||||
if err != nil {
|
||||
t.Fatalf("get room impl failed: %s", err)
|
||||
}
|
||||
|
||||
colors, exception := room.GetDanmuColors()
|
||||
if exception != nil {
|
||||
t.Fatalf("get danmu colors failed: %s", exceptions.GetStackTraceString(exception))
|
||||
}
|
||||
|
||||
marshal, _ := json.Marshal(colors)
|
||||
t.Logf("get colors: %s", string(marshal))
|
||||
}
|
Loading…
Reference in New Issue
Block a user