From f5c63cde56eb35c0125a0545f084441cdd4340ab Mon Sep 17 00:00:00 2001 From: Keuin Date: Tue, 11 Jul 2023 22:56:07 +0800 Subject: Refactor: move data structures to a separate package to avoid circular dependency. --- bilibili/client.go | 11 ++-- bilibili/danmaku_server_info.go | 5 +- bilibili/model.go | 8 --- bilibili/netprobe.go | 37 ++--------- bilibili/play_url.go | 28 +------- bilibili/request.go | 3 +- bilibili/request_test.go | 3 +- bilibili/room_profile.go | 82 +---------------------- bilibili/room_profile_test.go | 3 +- bilibili/room_status.go | 47 +------------- bilibili/room_status_test.go | 3 +- bilibili/streaming.go | 5 +- common/testing/testutil.go | 20 +----- danmaku/client.go | 4 +- danmaku/dmpkg/auth.go | 16 ++--- main.go | 8 +-- recording/config.go | 12 ++-- recording/runner.go | 5 +- types/live.go | 3 + types/live_list.go | 17 +++++ types/live_room.go | 141 ++++++++++++++++++++++++++++++++++++++++ types/net_type.go | 28 ++++++++ types/types.go | 9 +++ 23 files changed, 258 insertions(+), 240 deletions(-) delete mode 100644 bilibili/model.go create mode 100644 types/live.go create mode 100644 types/live_list.go create mode 100644 types/live_room.go create mode 100644 types/net_type.go create mode 100644 types/types.go diff --git a/bilibili/client.go b/bilibili/client.go index 65d858f..35d06e4 100644 --- a/bilibili/client.go +++ b/bilibili/client.go @@ -7,6 +7,7 @@ package bilibili import ( "context" "github.com/keuin/slbr/logging" + "github.com/keuin/slbr/types" "net" "net/http" ) @@ -21,15 +22,15 @@ type Bilibili struct { userAgent string http *http.Client ctx context.Context - netTypes []IpNetType + netTypes []types.IpNetType logger logging.Logger } -func NewBilibiliWithContext(ctx context.Context, netTypes []IpNetType, logger logging.Logger) Bilibili { - var nets []IpNetType +func NewBilibiliWithContext(ctx context.Context, netTypes []types.IpNetType, logger logging.Logger) Bilibili { + var nets []types.IpNetType nets = append(nets, netTypes...) if len(nets) == 0 { - nets = append(nets, IP64) + nets = append(nets, types.IP64) } var dialer net.Dialer @@ -47,7 +48,7 @@ func NewBilibiliWithContext(ctx context.Context, netTypes []IpNetType, logger lo } } -func NewBilibiliWithNetType(netTypes []IpNetType, logger logging.Logger) Bilibili { +func NewBilibiliWithNetType(netTypes []types.IpNetType, logger logging.Logger) Bilibili { ctx := context.Background() return NewBilibiliWithContext(ctx, netTypes, logger) } diff --git a/bilibili/danmaku_server_info.go b/bilibili/danmaku_server_info.go index b68d4b5..5df8ed7 100644 --- a/bilibili/danmaku_server_info.go +++ b/bilibili/danmaku_server_info.go @@ -2,9 +2,10 @@ package bilibili import ( "fmt" + "github.com/keuin/slbr/types" ) -type DanmakuServerInfoResponse = BaseResponse[danmakuInfo] +type DanmakuServerInfoResponse = types.BaseResponse[danmakuInfo] type danmakuInfo struct { Group string `json:"group"` @@ -21,7 +22,7 @@ type danmakuInfo struct { } `json:"host_list"` } -func (b Bilibili) GetDanmakuServerInfo(roomId RoomId) (resp DanmakuServerInfoResponse, err error) { +func (b Bilibili) GetDanmakuServerInfo(roomId types.RoomId) (resp DanmakuServerInfoResponse, err error) { url := fmt.Sprintf("https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo?id=%d&type=0", roomId) return callGet[DanmakuServerInfoResponse](b, url) } diff --git a/bilibili/model.go b/bilibili/model.go deleted file mode 100644 index ccffef9..0000000 --- a/bilibili/model.go +++ /dev/null @@ -1,8 +0,0 @@ -package bilibili - -type BaseResponse[T any] struct { - Code int `json:"code"` - Message string `json:"message"` - TTL int `json:"ttl"` - Data T `json:"data"` -} diff --git a/bilibili/netprobe.go b/bilibili/netprobe.go index 419cc20..3c9ad4a 100644 --- a/bilibili/netprobe.go +++ b/bilibili/netprobe.go @@ -2,44 +2,19 @@ package bilibili import ( "context" - "fmt" + "github.com/keuin/slbr/types" "net" ) -type IpNetType string - -var ( - IPv6Net IpNetType = "ipv6" - IPv4Net IpNetType = "ipv4" - IP64 IpNetType = "any" -) - -// GetDialNetString returns the string accepted by net.Dialer::DialContext -func (t IpNetType) GetDialNetString() string { - switch t { - case IPv4Net: - return "tcp4" - case IPv6Net: - return "tcp6" - case IP64: - return "tcp" - } - return "" -} - -func (t IpNetType) String() string { - return fmt.Sprintf("%s(%s)", string(t), t.GetDialNetString()) -} - type netContext = func(context.Context, string, string) (net.Conn, error) type netProbe struct { - list []IpNetType + list []types.IpNetType i int } -func newNetProbe(protocols []IpNetType) netProbe { - var netList []IpNetType +func newNetProbe(protocols []types.IpNetType) netProbe { + var netList []types.IpNetType netList = append(netList, protocols...) return netProbe{ list: netList, @@ -47,9 +22,9 @@ func newNetProbe(protocols []IpNetType) netProbe { } } -func (p *netProbe) NextNetworkType(dialer net.Dialer) (netContext, IpNetType) { +func (p *netProbe) NextNetworkType(dialer net.Dialer) (netContext, types.IpNetType) { if p.i >= len(p.list) { - return nil, IP64 + return nil, types.IP64 } network := p.list[p.i] p.i++ diff --git a/bilibili/play_url.go b/bilibili/play_url.go index 49e8298..c2c6709 100644 --- a/bilibili/play_url.go +++ b/bilibili/play_url.go @@ -2,33 +2,11 @@ package bilibili import ( "fmt" + "github.com/keuin/slbr/types" ) -type RoomUrlInfoResponse = BaseResponse[roomUrlInfo] - -type roomUrlInfo struct { - CurrentQuality int `json:"current_quality"` - AcceptQuality []string `json:"accept_quality"` - CurrentQualityNumber int `json:"current_qn"` - QualityDescription []qualityDescription `json:"quality_description"` - URLs []StreamingUrlInfo `json:"durl"` -} - -type qualityDescription struct { - QualityNumber int `json:"qn"` - Description string `json:"desc"` -} - -type StreamingUrlInfo struct { - URL string `json:"url"` - Length int `json:"length"` - Order int `json:"order"` - StreamType int `json:"stream_type"` - P2pType int `json:"p2p_type"` -} - -func (b Bilibili) GetStreamingInfo(roomId RoomId) (resp RoomUrlInfoResponse, err error) { +func (b Bilibili) GetStreamingInfo(roomId types.RoomId) (resp types.RoomUrlInfoResponse, err error) { url := fmt.Sprintf("https://api.live.bilibili.com/room/v1/Room/playUrl?"+ "cid=%d&otype=json&qn=10000&platform=web", roomId) - return callGet[RoomUrlInfoResponse](b, url) + return callGet[types.RoomUrlInfoResponse](b, url) } diff --git a/bilibili/request.go b/bilibili/request.go index 2e4b57e..fa31b19 100644 --- a/bilibili/request.go +++ b/bilibili/request.go @@ -2,6 +2,7 @@ package bilibili import ( "encoding/json" + "github.com/keuin/slbr/types" "io" "net" "net/http" @@ -29,7 +30,7 @@ func (b Bilibili) newGet(url string) (req *http.Request, err error) { } // callGet make a GET request and parse response as a JSON document with given model. -func callGet[T BaseResponse[V], V any](b Bilibili, url string) (resp T, err error) { +func callGet[T types.BaseResponse[V], V any](b Bilibili, url string) (resp T, err error) { req, err := b.newGet(url) if err != nil { b.logger.Error("Cannot create HTTP request instance on API %v: %v", url, err) diff --git a/bilibili/request_test.go b/bilibili/request_test.go index ed7d33e..4581084 100644 --- a/bilibili/request_test.go +++ b/bilibili/request_test.go @@ -2,6 +2,7 @@ package bilibili import ( "github.com/keuin/slbr/logging" + "github.com/keuin/slbr/types" "log" "testing" ) @@ -9,7 +10,7 @@ import ( func Test_callGet(t *testing.T) { // an always-fail request should not panic bi := NewBilibili(logging.NewWrappedLogger(log.Default(), "main")) - _, err := callGet[BaseResponse[struct{}]](bi, "https://256.256.256.256") + _, err := callGet[types.BaseResponse[struct{}]](bi, "https://256.256.256.256") if err == nil { t.Fatalf("the artificial request should fail, but it haven't") } diff --git a/bilibili/room_profile.go b/bilibili/room_profile.go index 98cc790..1d5bdf4 100644 --- a/bilibili/room_profile.go +++ b/bilibili/room_profile.go @@ -2,86 +2,10 @@ package bilibili import ( "fmt" + "github.com/keuin/slbr/types" ) -type roomProfile struct { - UID int `json:"uid"` - RoomID RoomId `json:"room_id"` - ShortID int `json:"short_id"` - Attention int `json:"attention"` - Online int `json:"online"` - IsPortrait bool `json:"is_portrait"` - Description string `json:"description"` - LiveStatus int `json:"live_status"` - AreaID int `json:"area_id"` - ParentAreaID int `json:"parent_area_id"` - ParentAreaName string `json:"parent_area_name"` - OldAreaID int `json:"old_area_id"` - Background string `json:"background"` - Title string `json:"title"` - UserCover string `json:"user_cover"` - Keyframe string `json:"keyframe"` - IsStrictRoom bool `json:"is_strict_room"` - LiveTime string `json:"live_time"` - Tags string `json:"tags"` - IsAnchor int `json:"is_anchor"` - RoomSilentType string `json:"room_silent_type"` - RoomSilentLevel int `json:"room_silent_level"` - RoomSilentSecond int `json:"room_silent_second"` - AreaName string `json:"area_name"` - Pendants string `json:"pendants"` - AreaPendants string `json:"area_pendants"` - HotWords []string `json:"hot_words"` - HotWordsStatus int `json:"hot_words_status"` - Verify string `json:"verify"` - NewPendants struct { - Frame struct { - Name string `json:"name"` - Value string `json:"value"` - Position int `json:"position"` - Desc string `json:"desc"` - Area int `json:"area"` - AreaOld int `json:"area_old"` - BgColor string `json:"bg_color"` - BgPic string `json:"bg_pic"` - UseOldArea bool `json:"use_old_area"` - } `json:"frame"` - Badge struct { - Name string `json:"name"` - Position int `json:"position"` - Value string `json:"value"` - Desc string `json:"desc"` - } `json:"badge"` - MobileFrame struct { - Name string `json:"name"` - Value string `json:"value"` - Position int `json:"position"` - Desc string `json:"desc"` - Area int `json:"area"` - AreaOld int `json:"area_old"` - BgColor string `json:"bg_color"` - BgPic string `json:"bg_pic"` - UseOldArea bool `json:"use_old_area"` - } `json:"mobile_frame"` - MobileBadge interface{} `json:"mobile_badge"` - } `json:"new_pendants"` - UpSession string `json:"up_session"` - PkStatus int `json:"pk_status"` - PkID int `json:"pk_id"` - BattleID int `json:"battle_id"` - AllowChangeAreaTime int `json:"allow_change_area_time"` - AllowUploadCoverTime int `json:"allow_upload_cover_time"` - StudioInfo struct { - Status int `json:"status"` - MasterList []interface{} `json:"master_list"` - } `json:"studio_info"` -} - -type RoomProfileResponse = BaseResponse[roomProfile] - -func (b Bilibili) GetRoomProfile(roomId RoomId) (resp RoomProfileResponse, err error) { +func (b Bilibili) GetRoomProfile(roomId types.RoomId) (resp types.RoomProfileResponse, err error) { url := fmt.Sprintf("https://api.live.bilibili.com/room/v1/Room/get_info?room_id=%d", roomId) - return callGet[RoomProfileResponse](b, url) + return callGet[types.RoomProfileResponse](b, url) } - -type RoomId uint64 diff --git a/bilibili/room_profile_test.go b/bilibili/room_profile_test.go index a1d68c5..131c348 100644 --- a/bilibili/room_profile_test.go +++ b/bilibili/room_profile_test.go @@ -3,6 +3,7 @@ package bilibili import ( testing2 "github.com/keuin/slbr/common/testing" "github.com/keuin/slbr/logging" + "github.com/keuin/slbr/types" "log" "testing" ) @@ -29,7 +30,7 @@ func TestBilibili_GetRoomProfile(t *testing.T) { resp.Message != "ok" || resp.Data.UID <= 0 || resp.Data.RoomID != roomId || - resp.Data.LiveStatus != int(Streaming) || + resp.Data.LiveStatus != int(types.Streaming) || resp.Data.Title == "" { t.Fatalf("Invalid GetRoomProfile response: %v", resp) } diff --git a/bilibili/room_status.go b/bilibili/room_status.go index cbb8bc4..f33277c 100644 --- a/bilibili/room_status.go +++ b/bilibili/room_status.go @@ -6,52 +6,11 @@ package bilibili import ( "fmt" + "github.com/keuin/slbr/types" ) -type LiveStatus int - -const ( - Inactive LiveStatus = 0 - Streaming LiveStatus = 1 - Playback LiveStatus = 2 -) - -var liveStatusStringMap = map[LiveStatus]string{ - Inactive: "inactive", - Streaming: "streaming", - Playback: "inactive (playback)", -} - -type roomPlayInfo struct { - RoomID uint64 `json:"room_id"` - ShortID uint `json:"short_id"` - UID uint `json:"uid"` - IsHidden bool `json:"is_hidden"` - IsLocked bool `json:"is_locked"` - IsPortrait bool `json:"is_portrait"` - LiveStatus LiveStatus `json:"live_status"` // 0: inactive 1: streaming 2: playback - HiddenTill int `json:"hidden_till"` - LockTill int `json:"lock_till"` - Encrypted bool `json:"encrypted"` - PwdVerified bool `json:"pwd_verified"` - LiveTime int `json:"live_time"` - RoomShield int `json:"room_shield"` - AllSpecialTypes []interface{} `json:"all_special_types"` - PlayurlInfo interface{} `json:"playurl_info"` -} - -type RoomPlayInfoResponse = BaseResponse[roomPlayInfo] - -func (s LiveStatus) IsStreaming() bool { - return s == Streaming -} - -func (s LiveStatus) String() string { - return liveStatusStringMap[s] -} - -func (b Bilibili) GetRoomPlayInfo(roomId RoomId) (resp RoomPlayInfoResponse, err error) { +func (b Bilibili) GetRoomPlayInfo(roomId types.RoomId) (resp types.RoomPlayInfoResponse, err error) { url := fmt.Sprintf("https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo"+ "?room_id=%d&protocol=0,1&format=0,1,2&codec=0,1&qn=0&platform=web&ptype=8&dolby=5&panorama=1", roomId) - return callGet[RoomPlayInfoResponse](b, url) + return callGet[types.RoomPlayInfoResponse](b, url) } diff --git a/bilibili/room_status_test.go b/bilibili/room_status_test.go index dde99f7..b287fbe 100644 --- a/bilibili/room_status_test.go +++ b/bilibili/room_status_test.go @@ -3,6 +3,7 @@ package bilibili import ( testing2 "github.com/keuin/slbr/common/testing" "github.com/keuin/slbr/logging" + "github.com/keuin/slbr/types" "log" "testing" ) @@ -29,7 +30,7 @@ func TestBilibili_GetRoomPlayInfo(t *testing.T) { resp.Message != "0" || resp.Data.UID <= 0 || resp.Data.RoomID != uint64(roomId) || - resp.Data.LiveStatus != Streaming { + resp.Data.LiveStatus != types.Streaming { t.Fatalf("Invalid GetRoomPlayInfo response: %v", resp) } } diff --git a/bilibili/streaming.go b/bilibili/streaming.go index 9f74950..2e0416c 100644 --- a/bilibili/streaming.go +++ b/bilibili/streaming.go @@ -6,6 +6,7 @@ import ( "fmt" errs "github.com/keuin/slbr/bilibili/errors" "github.com/keuin/slbr/common/files" + "github.com/keuin/slbr/types" "io" "net/http" "os" @@ -17,8 +18,8 @@ const InitReadBytes = 4096 // 4KiB // CopyLiveStream read data from a livestream video stream, copy them to a writer. func (b Bilibili) CopyLiveStream( ctx context.Context, - roomId RoomId, - stream StreamingUrlInfo, + roomId types.RoomId, + stream types.StreamingUrlInfo, fileCreator func() (*os.File, error), bufSize int64, ) (err error) { diff --git a/common/testing/testutil.go b/common/testing/testutil.go index 509c619..f99bec8 100644 --- a/common/testing/testutil.go +++ b/common/testing/testutil.go @@ -3,7 +3,7 @@ package testing import ( "encoding/json" "fmt" - "github.com/keuin/slbr/bilibili" + "github.com/keuin/slbr/types" "io" "net/http" ) @@ -12,23 +12,7 @@ import ( Some utility function for test-purpose only. */ -type LiveList struct { - Code int `json:"code"` - Message string `json:"message"` - TTL int `json:"ttl"` - Data struct { - Count int `json:"count"` - Data []struct { - Face string `json:"face"` - Link string `json:"link"` - Roomid bilibili.RoomId `json:"roomid"` - Roomname string `json:"roomname"` - Nickname string `json:"nickname"` - } `json:"data"` - } `json:"data"` -} - -func GetLiveListForGuestUser() (liveList LiveList, err error) { +func GetLiveListForGuestUser() (liveList types.LiveList, err error) { url := "https://api.live.bilibili.com/xlive/web-interface/v1/index/WebGetUnLoginRecList" resp, err := http.Get(url) if err != nil { diff --git a/danmaku/client.go b/danmaku/client.go index c74a449..3862154 100644 --- a/danmaku/client.go +++ b/danmaku/client.go @@ -9,8 +9,8 @@ package danmaku import ( "context" "fmt" - "github.com/keuin/slbr/bilibili" "github.com/keuin/slbr/danmaku/dmpkg" + "github.com/keuin/slbr/types" "nhooyr.io/websocket" ) @@ -87,7 +87,7 @@ func (d *DanmakuClient) Disconnect() error { return ws.Close(websocket.StatusInternalError, "disconnected") } -func (d *DanmakuClient) Authenticate(roomId bilibili.RoomId, authKey string) error { +func (d *DanmakuClient) Authenticate(roomId types.RoomId, authKey string) error { pkg := dmpkg.NewAuth(dmpkg.ProtoPlainJson, roomId, authKey) data, err := pkg.Marshal() if err != nil { diff --git a/danmaku/dmpkg/auth.go b/danmaku/dmpkg/auth.go index bb66f1d..b6a90d3 100644 --- a/danmaku/dmpkg/auth.go +++ b/danmaku/dmpkg/auth.go @@ -8,20 +8,20 @@ package dmpkg import ( "encoding/json" "fmt" - "github.com/keuin/slbr/bilibili" + "github.com/keuin/slbr/types" ) type authInfo struct { - UID uint64 `json:"uid"` - RoomId bilibili.RoomId `json:"roomid"` - ProtoVer int `json:"protover"` - Platform string `json:"platform"` - Type int `json:"type"` - Key string `json:"key"` + UID uint64 `json:"uid"` + RoomId types.RoomId `json:"roomid"` + ProtoVer int `json:"protover"` + Platform string `json:"platform"` + Type int `json:"type"` + Key string `json:"key"` } // NewAuth creates a new authentication exchange. -func NewAuth(protocol ProtocolVer, roomId bilibili.RoomId, authKey string) (exc DanmakuExchange) { +func NewAuth(protocol ProtocolVer, roomId types.RoomId, authKey string) (exc DanmakuExchange) { exc, _ = NewPlainExchange(OpConnect, authInfo{ UID: UidGuest, RoomId: roomId, diff --git a/main.go b/main.go index 7d3fc37..90e0d6a 100644 --- a/main.go +++ b/main.go @@ -9,9 +9,9 @@ import ( "context" "fmt" "github.com/akamensky/argparse" - "github.com/keuin/slbr/bilibili" "github.com/keuin/slbr/logging" "github.com/keuin/slbr/recording" + "github.com/keuin/slbr/types" "github.com/mitchellh/mapstructure" "github.com/samber/mo" "github.com/spf13/viper" @@ -110,11 +110,11 @@ func getTasks() (tasks []recording.TaskConfig) { return } var gc GlobalConfig - netType := reflect.TypeOf(bilibili.IP64) + netType := reflect.TypeOf(types.IP64) err = viper.Unmarshal(&gc, func(conf *mapstructure.DecoderConfig) { conf.DecodeHook = func(from reflect.Value, to reflect.Value) (interface{}, error) { if to.Type() == netType && - bilibili.IpNetType(from.String()).GetDialNetString() == "" { + types.IpNetType(from.String()).GetDialNetString() == "" { return nil, fmt.Errorf("invalid IpNetType: %v", from.String()) } return from.Interface(), nil @@ -138,7 +138,7 @@ func getTasks() (tasks []recording.TaskConfig) { } for i := 0; i < taskCount; i++ { tasks[i] = recording.TaskConfig{ - RoomId: bilibili.RoomId((*rooms)[i]), + RoomId: types.RoomId((*rooms)[i]), Transport: recording.DefaultTransportConfig(), Download: recording.DownloadConfig{ DiskWriteBufferBytes: int64(diskBufSize), diff --git a/recording/config.go b/recording/config.go index 9a95e62..52406f3 100644 --- a/recording/config.go +++ b/recording/config.go @@ -2,21 +2,21 @@ package recording import ( "fmt" - "github.com/keuin/slbr/bilibili" + "github.com/keuin/slbr/types" ) type TaskConfig struct { - RoomId bilibili.RoomId `mapstructure:"room_id"` + RoomId types.RoomId `mapstructure:"room_id"` Transport TransportConfig `mapstructure:"transport"` Download DownloadConfig `mapstructure:"download"` Watch WatchConfig `mapstructure:"watch"` } type TransportConfig struct { - SocketTimeoutSeconds int `mapstructure:"socket_timeout_seconds"` - RetryIntervalSeconds int `mapstructure:"retry_interval_seconds"` - MaxRetryTimes int `mapstructure:"max_retry_times"` - AllowedNetworkTypes []bilibili.IpNetType `mapstructure:"allowed_network_types"` + SocketTimeoutSeconds int `mapstructure:"socket_timeout_seconds"` + RetryIntervalSeconds int `mapstructure:"retry_interval_seconds"` + MaxRetryTimes int `mapstructure:"max_retry_times"` + AllowedNetworkTypes []types.IpNetType `mapstructure:"allowed_network_types"` } type DownloadConfig struct { diff --git a/recording/runner.go b/recording/runner.go index 13a4050..936fcab 100644 --- a/recording/runner.go +++ b/recording/runner.go @@ -15,6 +15,7 @@ import ( "github.com/keuin/slbr/common/files" "github.com/keuin/slbr/common/myurl" "github.com/keuin/slbr/logging" + "github.com/keuin/slbr/types" "github.com/samber/mo" "io" "os" @@ -250,7 +251,7 @@ func record( ctx, logger, task, - func() (bilibili.RoomProfileResponse, error) { + func() (types.RoomProfileResponse, error) { return bi.GetRoomProfile(task.RoomId) }, ) @@ -266,7 +267,7 @@ func record( ctx, logger, task, - func() (bilibili.RoomUrlInfoResponse, error) { + func() (types.RoomUrlInfoResponse, error) { return bi.GetStreamingInfo(task.RoomId) }, ) diff --git a/types/live.go b/types/live.go new file mode 100644 index 0000000..9fe2314 --- /dev/null +++ b/types/live.go @@ -0,0 +1,3 @@ +package types + +type RoomId uint64 diff --git a/types/live_list.go b/types/live_list.go new file mode 100644 index 0000000..8d4e890 --- /dev/null +++ b/types/live_list.go @@ -0,0 +1,17 @@ +package types + +type LiveList struct { + Code int `json:"code"` + Message string `json:"message"` + TTL int `json:"ttl"` + Data struct { + Count int `json:"count"` + Data []struct { + Face string `json:"face"` + Link string `json:"link"` + Roomid RoomId `json:"roomid"` + Roomname string `json:"roomname"` + Nickname string `json:"nickname"` + } `json:"data"` + } `json:"data"` +} diff --git a/types/live_room.go b/types/live_room.go new file mode 100644 index 0000000..6d39ecb --- /dev/null +++ b/types/live_room.go @@ -0,0 +1,141 @@ +package types + +type RoomUrlInfoResponse = BaseResponse[roomUrlInfo] + +type roomUrlInfo struct { + CurrentQuality int `json:"current_quality"` + AcceptQuality []string `json:"accept_quality"` + CurrentQualityNumber int `json:"current_qn"` + QualityDescription []qualityDescription `json:"quality_description"` + URLs []StreamingUrlInfo `json:"durl"` +} + +type qualityDescription struct { + QualityNumber int `json:"qn"` + Description string `json:"desc"` +} + +type StreamingUrlInfo struct { + URL string `json:"url"` + Length int `json:"length"` + Order int `json:"order"` + StreamType int `json:"stream_type"` + P2pType int `json:"p2p_type"` +} + +type roomProfile struct { + UID int `json:"uid"` + RoomID RoomId `json:"room_id"` + ShortID int `json:"short_id"` + Attention int `json:"attention"` + Online int `json:"online"` + IsPortrait bool `json:"is_portrait"` + Description string `json:"description"` + LiveStatus int `json:"live_status"` + AreaID int `json:"area_id"` + ParentAreaID int `json:"parent_area_id"` + ParentAreaName string `json:"parent_area_name"` + OldAreaID int `json:"old_area_id"` + Background string `json:"background"` + Title string `json:"title"` + UserCover string `json:"user_cover"` + Keyframe string `json:"keyframe"` + IsStrictRoom bool `json:"is_strict_room"` + LiveTime string `json:"live_time"` + Tags string `json:"tags"` + IsAnchor int `json:"is_anchor"` + RoomSilentType string `json:"room_silent_type"` + RoomSilentLevel int `json:"room_silent_level"` + RoomSilentSecond int `json:"room_silent_second"` + AreaName string `json:"area_name"` + Pendants string `json:"pendants"` + AreaPendants string `json:"area_pendants"` + HotWords []string `json:"hot_words"` + HotWordsStatus int `json:"hot_words_status"` + Verify string `json:"verify"` + NewPendants struct { + Frame struct { + Name string `json:"name"` + Value string `json:"value"` + Position int `json:"position"` + Desc string `json:"desc"` + Area int `json:"area"` + AreaOld int `json:"area_old"` + BgColor string `json:"bg_color"` + BgPic string `json:"bg_pic"` + UseOldArea bool `json:"use_old_area"` + } `json:"frame"` + Badge struct { + Name string `json:"name"` + Position int `json:"position"` + Value string `json:"value"` + Desc string `json:"desc"` + } `json:"badge"` + MobileFrame struct { + Name string `json:"name"` + Value string `json:"value"` + Position int `json:"position"` + Desc string `json:"desc"` + Area int `json:"area"` + AreaOld int `json:"area_old"` + BgColor string `json:"bg_color"` + BgPic string `json:"bg_pic"` + UseOldArea bool `json:"use_old_area"` + } `json:"mobile_frame"` + MobileBadge interface{} `json:"mobile_badge"` + } `json:"new_pendants"` + UpSession string `json:"up_session"` + PkStatus int `json:"pk_status"` + PkID int `json:"pk_id"` + BattleID int `json:"battle_id"` + AllowChangeAreaTime int `json:"allow_change_area_time"` + AllowUploadCoverTime int `json:"allow_upload_cover_time"` + StudioInfo struct { + Status int `json:"status"` + MasterList []interface{} `json:"master_list"` + } `json:"studio_info"` +} + +type RoomProfileResponse = BaseResponse[roomProfile] + +type LiveStatus int + +const ( + Inactive LiveStatus = 0 + Streaming LiveStatus = 1 + Playback LiveStatus = 2 +) + +var liveStatusStringMap = map[LiveStatus]string{ + Inactive: "inactive", + Streaming: "streaming", + Playback: "inactive (playback)", +} + +type roomPlayInfo struct { + RoomID uint64 `json:"room_id"` + ShortID uint `json:"short_id"` + UID uint `json:"uid"` + IsHidden bool `json:"is_hidden"` + IsLocked bool `json:"is_locked"` + IsPortrait bool `json:"is_portrait"` + LiveStatus LiveStatus `json:"live_status"` // 0: inactive 1: streaming 2: playback + HiddenTill int `json:"hidden_till"` + LockTill int `json:"lock_till"` + Encrypted bool `json:"encrypted"` + PwdVerified bool `json:"pwd_verified"` + LiveTime int `json:"live_time"` + RoomShield int `json:"room_shield"` + AllSpecialTypes []interface{} `json:"all_special_types"` + PlayurlInfo interface{} `json:"playurl_info"` +} + +type RoomPlayInfoResponse = BaseResponse[roomPlayInfo] + +func (s LiveStatus) IsStreaming() bool { + return s == Streaming +} + +func (s LiveStatus) String() string { + return liveStatusStringMap[s] +} diff --git a/types/net_type.go b/types/net_type.go new file mode 100644 index 0000000..ce82288 --- /dev/null +++ b/types/net_type.go @@ -0,0 +1,28 @@ +package types + +import "fmt" + +type IpNetType string + +var ( + IPv6Net IpNetType = "ipv6" + IPv4Net IpNetType = "ipv4" + IP64 IpNetType = "any" +) + +// GetDialNetString returns the string accepted by net.Dialer::DialContext +func (t IpNetType) GetDialNetString() string { + switch t { + case IPv4Net: + return "tcp4" + case IPv6Net: + return "tcp6" + case IP64: + return "tcp" + } + return "" +} + +func (t IpNetType) String() string { + return fmt.Sprintf("%s(%s)", string(t), t.GetDialNetString()) +} diff --git a/types/types.go b/types/types.go new file mode 100644 index 0000000..d1b1b70 --- /dev/null +++ b/types/types.go @@ -0,0 +1,9 @@ +// Package types include common data structures used in multiple packages. +package types + +type BaseResponse[T any] struct { + Code int `json:"code"` + Message string `json:"message"` + TTL int `json:"ttl"` + Data T `json:"data"` +} -- cgit v1.2.3