summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bilibili/client.go11
-rw-r--r--bilibili/danmaku_server_info.go5
-rw-r--r--bilibili/netprobe.go37
-rw-r--r--bilibili/play_url.go28
-rw-r--r--bilibili/request.go3
-rw-r--r--bilibili/request_test.go3
-rw-r--r--bilibili/room_profile.go82
-rw-r--r--bilibili/room_profile_test.go3
-rw-r--r--bilibili/room_status.go47
-rw-r--r--bilibili/room_status_test.go3
-rw-r--r--bilibili/streaming.go5
-rw-r--r--common/testing/testutil.go20
-rw-r--r--danmaku/client.go4
-rw-r--r--danmaku/dmpkg/auth.go16
-rw-r--r--main.go8
-rw-r--r--recording/config.go12
-rw-r--r--recording/runner.go5
-rw-r--r--types/live.go3
-rw-r--r--types/live_list.go17
-rw-r--r--types/live_room.go141
-rw-r--r--types/net_type.go28
-rw-r--r--types/types.go (renamed from bilibili/model.go)3
22 files changed, 251 insertions, 233 deletions
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/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/bilibili/model.go b/types/types.go
index ccffef9..d1b1b70 100644
--- a/bilibili/model.go
+++ b/types/types.go
@@ -1,4 +1,5 @@
-package bilibili
+// Package types include common data structures used in multiple packages.
+package types
type BaseResponse[T any] struct {
Code int `json:"code"`