biligo

package module
v0.0.0-...-cc9f58c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 27, 2025 License: MIT Imports: 28 Imported by: 0

README

biligo

bilibili-api in golang, bro just wrapped everything.

总之就是封装了大部分常用我爱用的东西

好多东西啊什么都有这让我怎么写

比如动态、视频(在线人数、AI总结、视频流地址)、专栏、番剧、音频、搜索等的信息获取/接口调用 ReqXXX FetchXXX

还有一键解析字符串中所有的b站链接 ParseLink

还有扫码登录, 用迭代器实现了轮询回调 Login (demo/login.go), cookie 管理也有个很简陋的实现

还可以注册轮询视频AI总结完成的回调 RegisterVideoConclusion

还能监听直播间信息流, 主播开播/下播/吃红SC/被切断一瞬间就来通知, 快到超速了! (demo/liveMsgStream.go)

另外就是用 text/template 实现了为任意结构体的灵活格式化, 直接丢在 template/type 里就完事了, 还做了懒加载, 太好用了, 我管你慢不慢的 (自定义模板见 demo/customTemplate)

just go get github.com/Miuzarte/biligo

Documentation

Index

Constants

View Source
const (
	URL_DOMAIN    = `bilibili.com`
	URL_MAIN_PAGE = `https://www.bilibili.com`
)
View Source
const (
	TIME_LAYOUT_L24  = `2006/01/02 15:04:05`
	TIME_LAYOUT_L24C = `2006年01月02日15时04分05秒`
	TIME_LAYOUT_M24  = `01/02 15:04:05`
	TIME_LAYOUT_M24C = `01月02日15时04分05秒`
	TIME_LAYOUT_S24  = `02 15:04:05`
	TIME_LAYOUT_S24C = `02日15时04分05秒`
	TIME_LAYOUT_T24  = `15:04:05`
	TIME_LAYOUT_T24C = `15时04分05秒`
)
View Source
const (
	REGEXP_SHORT   = `(?:b23\.tv|acg\.tv|bili2233\.cn)/([0-9A-Za-z]+)` // 0: url, 1: id(av/BV/shortId)
	REGEXP_VIDEO   = `video/(BV1[1-9A-HJ-NP-Za-km-z]{9}|av[0-9]+)`     // 1: id(av/BV)
	REGEXP_BANGUMI = `bangumi/(?:media|play)/((md|ss|ep)[0-9]+)`       // 1: id(md/ss/dp), 2: "md"|"ss"|"ep"
	REGEXP_LIVE    = `live\.bilibili\.com/([0-9]+)`                    // 1: room id
	REGEXP_ARTICLE = `(?:read/cv|read/mobile/)([0-9]+)`                // 1: cvid(numbers)
	REGEXP_AUDIO   = `audio/au([0-9]+)`                                // 1: audio id
	REGEXP_SPACE   = `(?:space|m)\.bilibili\.com/(?:space/)?([0-9]+)`  // 1: space id
	REGEXP_DYNAMIC = `(?:t.bilibili.com|dynamic|opus)/([0-9]+)`        // 1: dynamic id
)
View Source
const (
	REGEXP_INDEX_SHORT_URL, REGEXP_INDEX_SHORT_ID         = 0, 1
	REGEXP_INDEX_ARCHIVE                                  = 1
	REGEXP_INDEX_BANGUMI_ID, REGEXP_INDEX_BANGUMI_ID_TYPE = 1, 2
	REGEXP_INDEX_LIVE                                     = 1
	REGEXP_INDEX_ARTICLE                                  = 1
	REGEXP_INDEX_AUDIO                                    = 1
	REGEXP_INDEX_SPACE                                    = 1
	REGEXP_INDEX_DYNAMIC                                  = 1
)
View Source
const (
	SEARCH_TYPE_VIDEO   SearchClass = "video"
	SEARCH_TYPE_VIDEO_C string      = "视频"

	SEARCH_TYPE_BANGUMI   SearchClass = "media_bangumi"
	SEARCH_TYPE_BANGUMI_C string      = "番剧"
	SEARCH_TYPE_FT        SearchClass = "media_ft"
	SEARCH_TYPE_FT_C      string      = "影视"

	SEARCH_TYPE_LIVE        SearchClass = "live" // 包括直播间和主播, 实际结果中不存在这个类型, 仅在请求中使用
	SEARCH_TYPE_LIVE_C      string      = "直播"
	SEARCH_TYPE_LIVE_USER   SearchClass = "live_user"
	SEARCH_TYPE_LIVE_USER_C string      = "主播"
	SEARCH_TYPE_LIVE_ROOM   SearchClass = "live_room"
	SEARCH_TYPE_LIVE_ROOM_C string      = "直播间"

	SEARCH_TYPE_ARTICLE   SearchClass = "article"
	SEARCH_TYPE_ARTICLE_C string      = "专栏"

	SEARCH_TYPE_BILI_USER   SearchClass = "bili_user"
	SEARCH_TYPE_BILI_USER_C string      = "用户"

	SEARCH_TYPE_TOPIC   SearchClass = "topic" // 老东西 搜不出啥
	SEARCH_TYPE_TOPIC_C string      = "话题"

	SEARCH_TYPE_PHOTO   SearchClass = "photo" // 搜不到东西
	SEARCH_TYPE_PHOTO_C string      = "相簿"
)
View Source
const (
	PROTOCOL_PLAIN = iota
	PROTOCOL_POPULARITY
	PROTOCOL_ZLIB
	PROTOCOL_BROTLI
)
View Source
const (
	OPERATION_HEARTBEAT
	OPERATION_HEARTBEAT_RESP

	OPERATION_NORMAL

	OPERATION_AUTHENTICATION
	OPERATION_AUTHENTICATION_RESP
)
View Source
const (
	// 视频详细信息 [VideoInfo]
	//	.WithQuery("aid", aid)
	//	.WithQuery("bvid", bvid)
	URL_VIDEO_INFO_WBI = `https://api.bilibili.com/x/web-interface/wbi/view`
	URL_VIDEO_INFO     = `https://api.bilibili.com/x/web-interface/view`
	// 视频在线人数 [VideoOnline]
	//	.WithQuerys("aid", aid, "cid", cid)
	URL_VIDEO_ONLINE = `https://api.bilibili.com/x/player/online/total`
	// 视频AI总结内容 [VideoConclusion]
	//	.WithQuerys("aid", aid, "cid", cid)
	//	?.WithQuery("up_mid", uid) // 似乎非必须
	URL_VIDEO_CONCLUSION_WBI = `https://api.bilibili.com/x/web-interface/view/conclusion/get`

	// 剧集基本信息, 返回的结果字段为 `result`, 信息很少 [MediaBase]
	//	.WithQuery("media_id", mdid)
	URL_MEDIA_INFO_BASE = `https://api.bilibili.com/pgc/review/user`
	// 剧集明细, 返回的结果字段为 `result`, 两种 query 返回的结果一致 (仅测试了番剧) [Media]
	//	.WithQuery("season_id", ssid)
	//	.WithQuery("ep_id", epid)
	URL_MEDIA_INFO_DETAIL = `https://api.bilibili.com/pgc/view/web/season`
	// 剧集分集信息, 返回的结果字段为 `result` [MediaSection]
	//	.WithQuery("season_id", ssid)
	URL_MEDIA_SECTION = `https://api.bilibili.com/pgc/web/season/section`

	// 直播间状态, 可批量 [LiveStatus]
	//	.WithQueryList("uids[]", uids...)
	URL_LIVE_STATUS_UIDS = `https://api.live.bilibili.com/room/v1/Room/get_status_info_by_uids`
	// 直播间信息, 拿不到用户名 [LiveRoomInfo]
	//	.WithQuery("room_id", roomId)
	URL_LIVE_INFO_ROOMID = `https://api.live.bilibili.com/room/v1/Room/get_info`

	// 专栏文章基本信息 [ArticleInfo]
	//	.WithQuery("id", id) // TrimPrefix(id, "cv")
	URL_ARTICLE_INFO = `https://api.bilibili.com/x/article/viewinfo`

	// 整合: [Song]
	// 歌曲基本信息 [SongInfo]
	//	.WithQuery("sid", auid) // TrimPrefix(auid, "au")
	URL_SONG_INFO = `https://www.bilibili.com/audio/music-service-c/web/song/info`
	// 歌曲TAG [SongTag]
	//	.WithQuery("sid", auid) // TrimPrefix(auid, "au")
	URL_SONG_TAG = `https://www.bilibili.com/audio/music-service-c/web/tag/song`
	// 歌曲创作成员列表 [SongMember]
	//	.WithQuery("sid", auid) // TrimPrefix(auid, "au")
	URL_SONG_MEMBER = `https://www.bilibili.com/audio/music-service-c/web/member/song`
	// 歌曲歌词 [SongLyric]
	//	.WithQuery("sid", auid) // TrimPrefix(auid, "au")
	URL_SONG_LIRIC = `https://www.bilibili.com/audio/music-service-c/web/song/lyric`

	// 用户名片信息 [SpaceCard]
	//	.WithQuery("mid", uid)
	//	.WithQuery("photo", "true") // 请求用户主页头图 space.s_img, space.l_img
	URL_SPACE_CARD = `https://api.bilibili.com/x/web-interface/card`

	// 用户关系状态数 [RelationStat]
	//	.WithQuery("vmid", uid)
	URL_RELATION_STAT = `https://api.bilibili.com/x/relation/stat`

	// 用户空间动态 [DynamicSpace]
	// .WithQuery("host_mid", uid)
	URL_DYNAMIC_SPACE = `https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space`
	// 用户空间动态 [DynamicSpaceDesktop]
	// .WithQuery("host_mid", uid)
	URL_DYNAMIC_SPACE_DESKTOP = `https://api.bilibili.com/x/polymer/web-dynamic/desktop/v1/feed/space`

	// 全部动态列表 [DynamicAll]
	URL_DYNAMIC_ALL = `https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all`
	// 新动态数量 [DynamicAllUpdate]
	//	.WithQuery("update_baseline", updateBaseline)
	URL_DYNAMIC_ALL_UPDATE = `https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/all/update`

	// 动态详情 [DynamicDetail]
	//	.WithQuery("id", id)
	// 图文动态无文字内容
	URL_DYNAMIC_DETAIL = `https://api.bilibili.com/x/polymer/web-dynamic/v1/detail`
	// 动态详情 [DynamicDetailDesktop]
	//	.WithQuery("id", id)
	// 二次请求补充文字内容
	URL_DYNAMIC_DETAIL_DESKTOP = `https://api.bilibili.com/x/polymer/web-dynamic/desktop/v1/detail`

	// 投票信息 [VoteInfo]
	//	.WithQuery("vote_id", voteId)
	URL_VOTE_INFO = `https://api.bilibili.com/x/vote/vote_info`
	// 投票信息(无图片)
	//	.WithQuery("vote_id", voteId)
	URL_VOTE_INFO_ = `https://api.vc.bilibili.com/vote_svr/v1/vote_svr/vote_info`

	// 综合搜索 [SearchAll]
	//	.WithQuery("keyword", keyword)
	URL_SEARCH_ALL_WBI = `https://api.bilibili.com/x/web-interface/wbi/search/all/v2`
	// 综合搜索(旧链接)
	URL_SEARCH_ALL_OLD = `https://api.bilibili.com/x/web-interface/search/all/v2`
	// 分类搜索 [SearchType] [SearchTypeLive]
	//	.WithQuerys("search_type", string([SearchClass]), "keyword", keyword)
	URL_SEARCH_TYPE_WBI = `https://api.bilibili.com/x/web-interface/wbi/search/type`
	// 分类搜索(旧链接)
	URL_SEARCH_TYPE_OLD = `https://api.bilibili.com/x/web-interface/search/type`

	// 直播间信息流认证秘钥 [LiveDanmuInfo]
	//	.WithQuery("id", roomId) // 直播间真实id
	URL_LIVE_DANMU_INFO = `https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo`

	// 视频流地址 [VideoPlayurl]
	//	.WithQuerys(
	//		"avid", aid, "cid", cid, "fnval", fnval, // [VIDED_FNVAL_DASHALL] / [VIDEO_FNVAL_MP4]
	//		"fourk", "1", // 请求 4K
	//		"try_look", "1", // 游客高清晰度
	//	)
	URL_VIDEO_PALYURL_WBI = `https://api.bilibili.com/x/player/wbi/playurl`
	// 视频流地址(旧链接)
	URL_VIDEO_PALYURL_OLD = `https://api.bilibili.com/x/player/playurl`

	// 评论区评论列表 [ReplyList]
	//	.WithQuerys("type", itoa([CommentClass]), "oid", id)
	URL_REPLY_LIST = `https://api.bilibili.com/x/v2/reply`

	// 申请登录二维码 [QrcodeGenerate]
	URL_LOGIN_QRCODE_GENERATE = `https://passport.bilibili.com/x/passport-login/web/qrcode/generate`
	// 扫码登录 [QrcodePoll]
	//	.WithQuery("qrcode_key", qrcodeKey)
	URL_LOGIN_QRCODE_POLL = `https://passport.bilibili.com/x/passport-login/web/qrcode/poll`

	// 导航栏用户信息 主要用于获取 wbi keys [Nav]
	// NOTE: 未登录时也能正常获取到 wbi keys,
	// 但是此时响应状态码不为 0
	URL_NAV = `https://api.bilibili.com/x/web-interface/nav`

	// URL_BUVID3  = `https://api.bilibili.com/x/web-frontend/getbuvid`
	URL_BUVID34 = `https://api.bilibili.com/x/frontend/finger/spi`
)

Variables

View Source
var (
	ErrChainRespCodeNotZero = errors.New("response code not zero")
	ErrChainNilResp         = errors.New("response is nil")
	ErrChainNilBody         = errors.New("body is nil")
	ErrChainPathNotExists   = errors.New("path not exists")
)
View Source
var (
	ErrDownloadEmptyDUrl        = errors.New("empty durl")
	ErrDownloadNoUrlFound       = errors.New("no url found")
	ErrDownloadInvaliedFileSize = errors.New("invalid file size")
)
View Source
var (
	ErrFetchNoLocation      = errors.New("no location")
	ErrFetchRespCodeNotZero = errors.New("response code not zero")
	ErrFetchPathNotExists   = errors.New("path not exists")
	ErrFetchCidNotExists    = errors.New("cid not exists")
)
View Source
var (
	ErrLmsPacketNotBinary  = errors.New("packet not binary")
	ErrLmsFailedToGetToken = errors.New("failed to get token")
	ErrLmsNilConn          = errors.New("conn is nil")
	ErrLmsInvalidPacket    = errors.New("invalid packet")
	ErrLmsUnknownProtocol  = errors.New("unknown protocol")
)
View Source
var (
	ErrLoginEmptyQrcodeUrl = errors.New("empty qrcode url")
	ErrLoginEmptyQrcodeKey = errors.New("empty qrcode key")

	ErrLoginEmptyCookie       = errors.New("empty cookie")
	ErrLoginEmptyRefreshToken = errors.New("empty refresh token")
	ErrLoginNoDedeUserID      = errors.New("no DedeUserID in cookie")
	ErrLoginInvalidDedeUserID = errors.New("invalid DedeUserID in cookie")
	ErrLoginQrcodeExpired     = errors.New("qrcode expired")
	ErrLoginUnknownCode       = errors.New("unknown code")

	ErrLoginFailed         = errors.New("failed to login")
	ErrLoginUnexpectedHost = errors.New("unexpected host")
	ErrLoginEmptyUserId    = errors.New("empty user id")
)
View Source
var (
	ErrPollNoSummary         = errors.New("no summary") // 本视频暂无AI总结内容
	ErrPollNoVoiceRecognized = errors.New("no voice recognized")
	ErrPollUnknownCode       = errors.New("unknown code")
)
View Source
var (
	ErrParseMediaNoSsid = errors.New("no ssid in result")
	ErrParseLiveNoUid   = errors.New("no uid in result")
)
View Source
var (
	ErrSearchUnknownType = errors.New("unknown search type")
	ErrSearchEmptyType   = errors.New("empty search type")
)
View Source
var DefaultHeaders = map[string]string{
	"Accept":                    "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
	"Accept-Language":           "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
	"Dnt":                       "1",
	"Host":                      "www.bilibili.com",
	"Origin":                    "https://www.bilibili.com",
	"Referer":                   "https://www.bilibili.com/",
	"Priority":                  "u=1, i",
	"Sec-Ch-Ua":                 "\"Chromium\";v=\"141\", \"Microsoft Edge\";v=\"141\", \"Not.A/Brand\";v=\"99\"",
	"Sec-Ch-Ua-Mobile":          "?0",
	"Sec-Ch-Ua-Platform":        "\"Windows\"",
	"Sec-Fetch-Dest":            "document",
	"Sec-Fetch-Mode":            "navigate",
	"Sec-Fetch-Site":            "same-site",
	"Sec-Fetch-User":            "?1",
	"Upgrade-Insecure-Requests": "1",
	"User-Agent":                "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0",
}
View Source
var ErrClientNilRequest = errors.New("nil request provided")
View Source
var ErrFetchDynamicSpaceItemsNotEqual = errors.New("dynamic space items length not equal")
View Source
var ErrInvalidId = errors.New("invalid id")
View Source
var ErrWbiEmptyUrls = errors.New("empty image or sub url")
View Source
var LiveMsgCmdMap = map[string]struct{}{
	"ANCHOR_LOT_AWARD":                     {},
	"ANCHOR_LOT_CHECKSTATUS":               {},
	"ANCHOR_LOT_END":                       {},
	"ANCHOR_LOT_NOTICE":                    {},
	"ANCHOR_LOT_START":                     {},
	"AREA_RANK_CHANGED":                    {},
	"CHANGE_ROOM_INFO":                     {},
	"COMBO_SEND":                           {},
	"COMBO_END":                            {},
	"COMMON_ANIMATION":                     {},
	"COMMON_NOTICE_DANMAKU":                {},
	"CUT_OFF":                              {},
	"DANMU_AGGREGATION":                    {},
	"DANMU_MSG":                            {},
	"DM_INTERACTION":                       {},
	"ENTRY_EFFECT":                         {},
	"ENTRY_EFFECT_MUST_RECEIVE":            {},
	"FULL_SCREEN_SPECIAL_EFFECT":           {},
	"GIFT_STAR_PROCESS":                    {},
	"GOTO_BUY_FLOW":                        {},
	"GUARD_BUY":                            {},
	"GUARD_HONOR_THOUSAND":                 {},
	"HOT_RANK_CHANGED":                     {},
	"HOT_RANK_CHANGED_V2":                  {},
	"HOT_RANK_SETTLEMENT":                  {},
	"HOT_RANK_SETTLEMENT_V2":               {},
	"INTERACT_WORD":                        {},
	"LIKE_GUIDE_USER":                      {},
	"LIKE_INFO_V3_CLICK":                   {},
	"LIKE_INFO_V3_UPDATE":                  {},
	"LIVE":                                 {},
	"LIVE_PANEL_CHANGE":                    {},
	"LIVE_ANI_RES_UPDATE":                  {},
	"LOG_IN_NOTICE":                        {},
	"MESSAGEBOX_USER_GAIN_MEDAL":           {},
	"NOTICE_MSG":                           {},
	"ONLINE_RANK_COUNT":                    {},
	"ONLINE_RANK_V2":                       {},
	"ONLINE_RANK_TOP3":                     {},
	"PK_BATTLE_END":                        {},
	"PK_BATTLE_FINAL_PROCESS":              {},
	"PK_BATTLE_PRE":                        {},
	"PK_BATTLE_PRE_NEW":                    {},
	"PK_BATTLE_START":                      {},
	"PK_BATTLE_START_NEW":                  {},
	"PK_BATTLE_PROCESS":                    {},
	"PK_BATTLE_PROCESS_NEW":                {},
	"PK_BATTLE_SETTLE":                     {},
	"PK_BATTLE_SETTLE_USER":                {},
	"PK_BATTLE_SETTLE_V2":                  {},
	"PLAY_TOGETHER":                        {},
	"POPULAR_RANK_CHANGED":                 {},
	"POPULARITY_RED_POCKET_NEW":            {},
	"POPULARITY_RED_POCKET_START":          {},
	"POPULARITY_RED_POCKET_V2_NEW":         {},
	"POPULARITY_RED_POCKET_V2_START":       {},
	"POPULARITY_RED_POCKET_V2_WINNER_LIST": {},
	"POPULARITY_RED_POCKET_WINNER_LIST":    {},
	"PREPARING":                            {},
	"RANK_CHANGED":                         {},
	"RANK_REM":                             {},
	"RECALL_DANMU_MSG":                     {},
	"RECOMMEND_CARD":                       {},
	"REENTER_LIVE_ROOM":                    {},
	"REVENUE_RANK_CHANGED":                 {},
	"RING_STATUS_CHANGE":                   {},
	"RING_STATUS_CHANGE_V2":                {},
	"room_admin_entrance":                  {},
	"ROOM_ADMIN_REVOKE":                    {},
	"ROOM_ADMINS":                          {},
	"ROOM_CHANGE":                          {},
	"ROOM_CONTENT_AUDIT_REPORT":            {},
	"ROOM_REAL_TIME_MESSAGE_UPDATE":        {},
	"ROOM_SKIN_MSG":                        {},
	"ROOM_SILENT_OFF":                      {},
	"ROOM_SILENT_ON":                       {},
	"SEND_GIFT":                            {},
	"SHOPPING_CART_SHOW":                   {},
	"SPECIAL_GIFT":                         {},
	"SPREAD_SHOW_FEET_V2":                  {},
	"STOP_LIVE_ROOM_LIST":                  {},
	"SUPER_CHAT_ENTRANCE":                  {},
	"SUPER_CHAT_MESSAGE":                   {},
	"SUPER_CHAT_MESSAGE_DELETE":            {},
	"SUPER_CHAT_MESSAGE_JPN":               {},
	"SYS_MSG":                              {},
	"TRADING_SCORE":                        {},
	"USER_TOAST_MSG":                       {},
	"USER_TOAST_MSG_V2":                    {},
	"VIDEO_CONNECTION_JOIN_END":            {},
	"VIDEO_CONNECTION_JOIN_START":          {},
	"VIDEO_CONNECTION_MSG":                 {},
	"WARNING":                              {},
	"WATCHED_CHANGE":                       {},
	"WIDGET_BANNER":                        {},
	"WIDGET_GIFT_STAR_PROCESS":             {},
	"WIDGET_WISH_LIST":                     {},
}

Functions

func AV2BV

func AV2BV(aid int64) string

func AnyToAid

func AnyToAid(id string) (string, error)

AnyToAid 将任意 id 转换为 aid

func BV2AV

func BV2AV(bvid string) int64

func CookieUpdateBuvid34

func CookieUpdateBuvid34() error

func DoTemplate

func DoTemplate[T any](v *T) string

DoTemplate 填充时会根据类型选择模板, 外部类型在使用前需要通过 SetTemplateFor 函数自定义模板

func DoTemplateTo

func DoTemplateTo[T any](w io.Writer, v *T) error

DoTemplateTo 填充时会根据类型选择模板, 外部类型在使用前需要通过 SetTemplateFor 函数自定义模板

func DynamicDetailFix

func DynamicDetailFix(dd *DynamicDetail, dddi *DynamicDetailDesktopItem)

DynamicDetailFix 用 desktop api 补充正文

func ExportCookie

func ExportCookie() string

ExportCookie 导出当前的 Cookie

func ExportRefreshToken

func ExportRefreshToken() string

ExportRefreshToken 导出当前的 RefreshToken

func FetchSearchAll

func FetchSearchAll(keyword string) (j gjson.Result, err error)

FetchSearchAll 获取综合搜索

func FetchSearchType

func FetchSearchType(searchType SearchClass, keyword string) (j gjson.Result, err error)

FetchSearchType 获取分类搜索

func FetchVideoCid

func FetchVideoCid(id string) (cid string, err error)

func FetchVideoCidTryCache

func FetchVideoCidTryCache(id string) (cid string, err error)

FetchVideoCidTryCache 尝试从缓存中获取 cid, 如果没有则从网络获取并缓存

func FetchVideoInfo2

func FetchVideoInfo2(id string) (vi VideoInfo, vo VideoOnline, err error)

FetchVideoInfo2 获取视频信息、视频在线人数

id: avid/bvid

func FetchVideoInfo3

func FetchVideoInfo3(id string) (vi VideoInfo, vo VideoOnline, vc VideoConclusion, err error)

FetchVideoInfo3 获取视频信息、视频在线人数、总结

id: avid/bvid

func FormatDynamic deprecated

func FormatDynamic(j gjson.Result) string

FormatDynamic 格式化动态,

.Get("data.item")

转发原动态 .Get("orig")

Deprecated: use DynamicDetail.DoTemplate instead

func ImporCookie

func ImporCookie(cookieStr string) error

ImporCookie 导入新的 Cookie

func ImporRefreshToken

func ImporRefreshToken(refreshToken string)

ImporRefreshToken 导入新的 RefreshToken

func ImportIdentity

func ImportIdentity(id Identity) error

ImportIdentity 导入身份信息,包括 Cookie、RefreshToken 和 Uid

func IsTemplateOk

func IsTemplateOk[T any]() bool

IsTemplateOk 仅检查对应类型是否调用过 SetTemplateFor 且成功执行

func Login

func Login() (qrcodeUrl string, it iter.Seq2[LoginCodeState, error], err error)

func RegisterVideoConclusion

func RegisterVideoConclusion(ctx context.Context, id, cid string, f func(VideoConclusion, error)) (err error)

RegisterVideoConclusion 注册视频总结轮询回调, 视频无总结时返回 ErrPollNoSummary 错误

func SetTemplateFor

func SetTemplateFor[T any](conf ...TemplateConfig) (err error)

SetTemplateFor 为指定类型设置模板, 内置类型在不指定模板时使用内置模板, 外部类型在不指定模板时会 panic

func SetWsDialerProxy

func SetWsDialerProxy(pf func(*http.Request) (*url.URL, error))

func SongMemberTable

func SongMemberTable[T integer](i T) (s string)

SongMemberTable 返回歌曲成员类型的名称, 未知类型返回数字字符串

func WbiSign

func WbiSign(u *url.URL) error

WbiSign 为链接签名

func WbiUpdate

func WbiUpdate() error

WbiUpdate 无视过期时间更新

Types

type ArticleInfo

type ArticleInfo struct {
	Like      int  `json:"like" mapstructure:"like"`           // 0: 未点赞, 1: 已点赞
	Attention bool `json:"attention" mapstructure:"attention"` // 关注
	Favorite  bool `json:"favorite" mapstructure:"favorite"`   // 收藏
	Coin      int  `json:"coin" mapstructure:"coin"`

	Stats struct {
		View     int `json:"view" mapstructure:"view"`         // 阅读数
		Favorite int `json:"favorite" mapstructure:"favorite"` // 收藏数
		Like     int `json:"like" mapstructure:"like"`         // 点赞数
		Dislike  int `json:"dislike" mapstructure:"dislike"`   // 点踩数
		Reply    int `json:"reply" mapstructure:"reply"`       // 评论数
		Share    int `json:"share" mapstructure:"share"`       // 分享数
		Coin     int `json:"coin" mapstructure:"coin"`         // 投币数
		Dynamic  int `json:"dynamic" mapstructure:"dynamic"`   // 动态转发数
	} `json:"stats" mapstructure:"stats"`

	Title      string `json:"title" mapstructure:"title"`             // 标题
	BannerUrl  string `json:"banner_url" mapstructure:"banner_url"`   // 头图url
	Mid        int    `json:"mid" mapstructure:"mid"`                 // 作者uid
	AuthorName string `json:"author_name" mapstructure:"author_name"` // 作者昵称

	IsAuthor bool `json:"is_author" mapstructure:"is_author"`

	ImageUrls       []string `json:"image_urls" mapstructure:"image_urls"`               // 动态封面
	OriginImageUrls []string `json:"origin_image_urls" mapstructure:"origin_image_urls"` // 封面图片

	Shareable       bool `json:"sharable" mapstructure:"sharable"`
	ShowLaterWatch  bool `json:"show_later_watch" mapstructure:"show_later_watch"`
	ShowSmallWindow bool `json:"show_small_window" mapstructure:"show_small_window"`

	InList bool `json:"in_list" mapstructure:"in_list"` // 是否收于文集
	Pre    int  `json:"pre" mapstructure:"pre"`         // 上一篇文章cvid
	Next   int  `json:"next" mapstructure:"next"`       // 下一篇文章cvid

	Type     int    `json:"type" mapstructure:"type"`           // 0: 文章, 2: 笔记
	VideoUrl string `json:"video_url" mapstructure:"video_url"` // 专栏转视频的活动url
	Location string `json:"location" mapstructure:"location"`   // IP属地

	DisableShare bool `json:"disable_share" mapstructure:"disable_share"`

	Cvid string `json:"-" mapstructure:"-"` // 专栏id, 仅用于格式化
}

URL_ARTICLE_INFO "data"

func FetchArticleInfo

func FetchArticleInfo(id string) (ai ArticleInfo, err error)

FetchArticleInfo 获取专栏文章基本信息

func (*ArticleInfo) DoTemplate

func (ai *ArticleInfo) DoTemplate() string

func (*ArticleInfo) DoTemplateTo

func (ai *ArticleInfo) DoTemplateTo(w io.Writer) error

func (*ArticleInfo) WithCvid

func (ai *ArticleInfo) WithCvid(cvid string) *ArticleInfo

WithCvid 为 ArticleInfo 附加 cvid 用于格式化

type Buvid34

type Buvid34 struct {
	B_3 string `json:"b_3" mapstructure:"b_3"`
	B_4 string `json:"b_4" mapstructure:"b_4"`
}

"data"

func FetchBuvid34

func FetchBuvid34() (buvid34 Buvid34, err error)

FetchBuvid34 获取 buvid3 与 buvid4, 用于直播信息流

type Chain

type Chain struct {
	Req  *Request
	Resp *Response
	Body string
}

func (*Chain) Do

func (c *Chain) Do() (err error)

func (*Chain) ParseTo

func (c *Chain) ParseTo(v any, path ...string) (err error)

ParseTo 解析 json 数据到结构体中, path 为 json 中的路径, 例如 "data"

func (*Chain) ToArticle

func (c *Chain) ToArticle() (ai ArticleInfo, err error)

func (*Chain) ToBuvid34

func (c *Chain) ToBuvid34() (b Buvid34, err error)

func (*Chain) ToDynamicAll

func (c *Chain) ToDynamicAll() (da DynamicAll, err error)

func (*Chain) ToDynamicAllUpdate

func (c *Chain) ToDynamicAllUpdate() (dau DynamicAllUpdate, err error)

func (*Chain) ToDynamicDetail

func (c *Chain) ToDynamicDetail() (dd DynamicDetail, err error)

func (*Chain) ToDynamicDetailDesktop

func (c *Chain) ToDynamicDetailDesktop() (dd DynamicDetailDesktop, err error)

func (*Chain) ToDynamicSpace

func (c *Chain) ToDynamicSpace() (ds DynamicSpace, err error)

func (*Chain) ToDynamicSpaceDesktop

func (c *Chain) ToDynamicSpaceDesktop() (dsd DynamicSpaceDesktop, err error)

func (*Chain) ToLiveDanmuInfo

func (c *Chain) ToLiveDanmuInfo() (ldi LiveDanmuInfo, err error)

func (*Chain) ToLiveRoomInfo

func (c *Chain) ToLiveRoomInfo() (lri LiveRoomInfo, err error)

func (*Chain) ToLiveStatusUid

func (c *Chain) ToLiveStatusUid() (lsu LiveStatusUid, err error)

有数据时返回 {..., "data": {"{{uid}}": {...}}}, json 正常解析

空数据时返回 {..., "data": []}, json 返回错误:

json: cannot unmarshal array into Go value of type biligo.LiveStatusUid

func (*Chain) ToMedia

func (c *Chain) ToMedia() (m Media, err error)

func (*Chain) ToMediaBase

func (c *Chain) ToMediaBase() (mb MediaBase, err error)

func (*Chain) ToMediaSection

func (c *Chain) ToMediaSection() (ms MediaSection, err error)

func (*Chain) ToNav

func (c *Chain) ToNav() (n Nav, err error)

func (*Chain) ToQrcodeGenerate

func (c *Chain) ToQrcodeGenerate() (qg QrcodeGenerate, err error)

func (*Chain) ToQrcodePoll

func (c *Chain) ToQrcodePoll() (qp QrcodePoll, err error)

func (*Chain) ToRelationStat

func (c *Chain) ToRelationStat() (rs RelationStat, err error)

func (*Chain) ToReplyList

func (c *Chain) ToReplyList() (rl ReplyList, err error)

func (*Chain) ToSongInfo

func (c *Chain) ToSongInfo() (si SongInfo, err error)

func (*Chain) ToSongLyric

func (c *Chain) ToSongLyric() (sl SongLyric)

func (*Chain) ToSongMember

func (c *Chain) ToSongMember() (sm SongMember, err error)

func (*Chain) ToSongTag

func (c *Chain) ToSongTag() (st SongTag, err error)

func (*Chain) ToSpaceCard

func (c *Chain) ToSpaceCard() (sc SpaceCard, err error)

func (*Chain) ToVideoConclusion

func (c *Chain) ToVideoConclusion() (vc VideoConclusion, err error)

func (*Chain) ToVideoInfo

func (c *Chain) ToVideoInfo() (vi VideoInfo, err error)

func (*Chain) ToVideoOnline

func (c *Chain) ToVideoOnline() (vo VideoOnline, err error)

func (*Chain) ToVideoPlayurl

func (c *Chain) ToVideoPlayurl() (vp VideoPlayurl, err error)

func (*Chain) ToVoteInfo

func (c *Chain) ToVoteInfo() (vi VoteInfo, err error)

type CommentClass

type CommentClass = int
const (
	COMMENT_TYPE_VIDEO CommentClass // 视频稿件 (oid: 稿件 avid)
	COMMENT_TYPE_TOPIC              // 话题 (oid: 话题 id)

	COMMENT_TYPE_ACTIVITY          // 活动 (oid: 活动 id)
	COMMENT_TYPE_SHORT_VIDEO       // 小视频 (oid: 小视频 id)
	COMMENT_TYPE_BLACK_ROOM        // 小黑屋封禁信息 (oid: 封禁公示 id)
	COMMENT_TYPE_ANNOUNCEMENT      // 公告信息 (oid: 公告 id)
	COMMENT_TYPE_LIVE_ACTIVITY     // 直播活动 (oid: 直播间 id)
	COMMENT_TYPE_ACTIVITY_DRAFT    // 活动稿件 (oid: ?)
	COMMENT_TYPE_LIVE_ANNOUNCEMENT // 直播公告 (oid: ?)
	COMMENT_TYPE_ALBUM             // 相簿(图片动态) (oid: 相簿 id)
	COMMENT_TYPE_COLUMN            // 专栏 (oid: 专栏 cvid)
	COMMENT_TYPE_TICKET            // 票务 (oid: ?)
	COMMENT_TYPE_AUDIO             // 音频 (oid: 音频 auid)
	COMMENT_TYPE_JUDGMENT          // 风纪委员会 (oid: 众裁项目 id)
	COMMENT_TYPE_REVIEW            // 点评 (oid: ?)
	COMMENT_TYPE_DYNAMIC           // 动态(纯文字动态&分享) (oid: 动态 id)
	COMMENT_TYPE_PLAYLIST          // 播单 (oid: ?)
	COMMENT_TYPE_MUSIC_PLAYLIST    // 音乐播单 (oid: ?)
	COMMENT_TYPE_COMIC1            // 漫画 (oid: ?)
	COMMENT_TYPE_COMIC2            // 漫画 (oid: ?)
	COMMENT_TYPE_COMIC3            // 漫画 (oid: 漫画 mcid)

	COMMENT_TYPE_COURSE CommentClass = 33 // 课程 (oid: 课程 epid)
)

type DynamicAll

type DynamicAll struct {
	HasMore        bool            `json:"has_more" mapstructure:"has_more"`
	Items          []DynamicDetail `json:"items" mapstructure:"items"`
	Offset         string          `json:"offset" mapstructure:"offset"`
	UpdateBaseline string          `json:"update_baseline" mapstructure:"update_baseline"`
	UpdateNum      int             `json:"update_num" mapstructure:"update_num"`
}

"data"

func FetchDynamicAll

func FetchDynamicAll() (da DynamicAll, err error)

FetchDynamicAll 获取全部动态列表

type DynamicAllUpdate

type DynamicAllUpdate struct {
	UpdateNum int `json:"update_num" mapstructure:"update_num"`
}

"data"

func FetchDynamicAllUpdate

func FetchDynamicAllUpdate(updateBaseline string) (dau DynamicAllUpdate, err error)

FetchDynamicAllUpdate 获取新动态数量

type DynamicDetail

type DynamicDetail struct {
	Basic dynamicBasic `json:"basic" mapstructure:"basic"`
	IdStr string       `json:"id_str" mapstructure:"id_str"` // 动态 id

	Modules struct {
		Author  dynamicModuleAuthor  `json:"module_author" mapstructure:"module_author"`
		Dynamic dynamicModuleDynamic `json:"module_dynamic" mapstructure:"module_dynamic"`
		// More dynamicModuleMore `json:"module_more" mapstructure:"module_more"`
		Stat dynamicModuleStat `json:"module_stat" mapstructure:"module_stat"`
	} `json:"modules" mapstructure:"modules"`

	Orig *DynamicDetail `json:"orig" mapstructure:"orig"` // 转发的动态

	// "DYNAMIC_TYPE_FORWARD"       //
	// "DYNAMIC_TYPE_NONE"          // 只存在于转发的动态 ".orig" 中
	// "DYNAMIC_TYPE_WORD"          // 没有对应的 "MAJOR_TYPE_xxx"
	// "DYNAMIC_TYPE_DRAW"          -> "MAJOR_TYPE_DRAW"
	// "DYNAMIC_TYPE_AV"            -> "MAJOR_TYPE_ARCHIVE"
	// "DYNAMIC_TYPE_ARTICLE"       -> "MAJOR_TYPE_ARTICLE"
	// "DYNAMIC_TYPE_MUSIC"         -> "MAJOR_TYPE_MUSIC"
	// "DYNAMIC_TYPE_LIVE"          // 直播间分享
	// "DYNAMIC_TYPE_LIVE_RCMD"     -> "MAJOR_TYPE_LIVE_RCMD" // 直播开播(动态流拿不到更新)
	// "DYNAMIC_TYPE_COMMON_SQUARE" // 装扮 / 剧集点评 / 普通分享
	// "DYNAMIC_TYPE_PGC_UNION"     -> "MAJOR_TYPE_PGC" // 番剧更新
	Type string `json:"type" mapstructure:"type"` // "DYNAMIC_TYPE_xxx"

	Visible bool `json:"visible" mapstructure:"visible"`
}

"data.item" / "data.item.orig"

func FetchDynamicDetail

func FetchDynamicDetail(id string) (dd DynamicDetail, err error)

FetchDynamicDetail 获取动态信息

func FetchDynamicDetailFix

func FetchDynamicDetailFix(id string) (dd DynamicDetail, err error)

FetchDynamicDetailFix 获取动态信息并补充正文

func (*DynamicDetail) DoTemplate

func (dd *DynamicDetail) DoTemplate() string

func (*DynamicDetail) DoTemplateTo

func (dd *DynamicDetail) DoTemplateTo(w io.Writer) error

func (*DynamicDetail) GetReplyList

func (dd *DynamicDetail) GetReplyList() (rl ReplyList, err error)

type DynamicDetailDesktop

type DynamicDetailDesktop struct {
	Item DynamicDetailDesktopItem `json:"item" mapstructure:"item"`
}

"data" 转发的原动态中也有一层 "item", 故无法省略

func FetchDynamicDetailDesktop

func FetchDynamicDetailDesktop(id string) (dd DynamicDetailDesktop, err error)

FetchDynamicDetailDesktop 获取动态信息 (网页版), 用于补充正文

type DynamicDetailDesktopItem

type DynamicDetailDesktopItem struct {
	Basic struct {
		RidStr string `json:"rid_str" mapstructure:"rid_str"`
		RType  int    `json:"rtype" mapstructure:"rtype"`
	} `json:"basic" mapstructure:"basic"`
	IdStr string `json:"id_str" mapstructure:"id_str"` // 动态 id

	Modules dynamicModules `json:"modules" mapstructure:"modules"`

	// "DYNAMIC_TYPE_FORWARD"       //
	// "DYNAMIC_TYPE_NONE"          // 只存在于转发的动态 ".orig" 中
	// "DYNAMIC_TYPE_WORD"          // 没有对应的 "MAJOR_TYPE_xxx"
	// "DYNAMIC_TYPE_DRAW"          -> "MAJOR_TYPE_DRAW"
	// "DYNAMIC_TYPE_AV"            -> "MAJOR_TYPE_ARCHIVE"
	// "DYNAMIC_TYPE_ARTICLE"       -> "MAJOR_TYPE_ARTICLE"
	// "DYNAMIC_TYPE_MUSIC"         -> "MAJOR_TYPE_MUSIC"
	// "DYNAMIC_TYPE_LIVE"          // 直播间分享
	// "DYNAMIC_TYPE_LIVE_RCMD"     -> "MAJOR_TYPE_LIVE_RCMD" // 直播开播(动态流拿不到更新)
	// "DYNAMIC_TYPE_COMMON_SQUARE" // 装扮 / 剧集点评 / 普通分享
	// "DYNAMIC_TYPE_PGC_UNION"     -> "MAJOR_TYPE_PGC" // 番剧更新
	Type string `json:"type" mapstructure:"type"` // "DYNAMIC_TYPE_xxx"

	Visible bool `json:"visible" mapstructure:"visible"`
}

type DynamicSpace

type DynamicSpace struct {
	HasMore        bool            `json:"has_more" mapstructure:"has_more"`
	Items          []DynamicDetail `json:"items" mapstructure:"items"`
	Offset         string          `json:"offset" mapstructure:"offset"`
	UpdateBaseline string          `json:"update_baseline" mapstructure:"update_baseline"` // ? ""
	UpdateNum      int             `json:"update_num" mapstructure:"update_num"`           // ? 0
}

"data"

func FetchDynamicSpace

func FetchDynamicSpace(uid string) (ds DynamicSpace, err error)

FetchDynamicSpace 获取用户空间动态

func FetchDynamicSpaceFix

func FetchDynamicSpaceFix(uid string) (ds DynamicSpace, err error)

FetchDynamicSpaceFix 获取用户空间动态并补充正文

type DynamicSpaceDesktop

type DynamicSpaceDesktop struct {
	ErrMsg         any                        `json:"err_msg" mapstructure:"err_msg"` // null
	HasMore        bool                       `json:"has_more" mapstructure:"has_more"`
	Items          []DynamicDetailDesktopItem `json:"items" mapstructure:"items"`
	Offset         string                     `json:"offset" mapstructure:"offset"`
	UpdateBaseline string                     `json:"update_baseline" mapstructure:"update_baseline"` // ? ""
	UpdateNum      int                        `json:"update_num" mapstructure:"update_num"`           // ? 0
}

"data"

func FetchDynamicSpaceDesktop

func FetchDynamicSpaceDesktop(uid string) (dsd DynamicSpaceDesktop, err error)

FetchDynamicSpaceDesktop 获取用户空间动态 (网页版), 用于补充正文

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error 附带了更详细的信息

biliErr := biligo.UnwarpErr(err)

isXxx := biliErr.Is(ErrXXX)

func UnwrapErr

func UnwrapErr(err error) *Error

func (*Error) DoTemplate

func (e *Error) DoTemplate() string

implement Templatable for convenient string output

func (*Error) DoTemplateTo

func (e *Error) DoTemplateTo(w io.Writer) error

implement Templatable for convenient string output

func (*Error) Error

func (e *Error) Error() string

func (*Error) Is

func (e *Error) Is(target error) bool

func (*Error) Unwrap

func (e *Error) Unwrap() error

type Identity

type Identity struct {
	Cookie       string `json:"cookie"`
	RefreshToken string `json:"refresh_token"`
	Uid          int    `json:"uid"`
}

func ExportIdentity

func ExportIdentity() Identity

ExportIdentity 导出当前的身份信息

type LinkType

type LinkType int
const (
	LINK_TYPE_SHORT LinkType
	LINK_TYPE_ARCHIVE
	LINK_TYPE_MEDIA
	LINK_TYPE_LIVE
	LINK_TYPE_ARTICLE
	LINK_TYPE_SONG
	LINK_TYPE_SPACE
	LINK_TYPE_DYNAMIC
)

func (LinkType) String

func (lt LinkType) String() string

type LiveDanmuInfo

type LiveDanmuInfo struct {
	Group            string  `json:"group" mapstructure:"group"`
	BusinessId       int     `json:"business_id" mapstructure:"business_id"`
	RefreshRowFactor float64 `json:"refresh_row_factor" mapstructure:"refresh_row_factor"`
	RefreshRate      int     `json:"refresh_rate" mapstructure:"refresh_rate"`
	MaxDelay         int     `json:"max_delay" mapstructure:"max_delay"`
	Token            string  `json:"token" mapstructure:"token"`
	HostList         []struct {
		Host    string `json:"host" mapstructure:"host"`
		Port    int    `json:"port" mapstructure:"port"`
		WsPort  int    `json:"ws_port" mapstructure:"ws_port"`
		WssPort int    `json:"wss_port" mapstructure:"wss_port"`
	} `json:"host_list" mapstructure:"host_list"`
}

"data"

func FetchLiveDanmuInfo

func FetchLiveDanmuInfo(roomId string) (ldi LiveDanmuInfo, err error)

FetchLiveDanmuInfo 获取信息流认证秘钥

type LiveMsgCmd

type LiveMsgCmd = string
const (
	LIVE_MSG_STREAM_LIVE      LiveMsgCmd = "LIVE"        // 直播开始
	LIVE_MSG_STREAM_PREPARING LiveMsgCmd = "PREPARING"   // 直播准备中 (结束)
	LIVE_MSG_STREAM_CHANGE    LiveMsgCmd = "ROOM_CHANGE" // 房间信息变更
	LIVE_MSG_STREAM_WARNING   LiveMsgCmd = "WARNING"     // 警告
	LIVE_MSG_STREAM_CUT_OFF   LiveMsgCmd = "CUT_OFF"     // 切断
)

type LiveMsgStream

type LiveMsgStream struct {
	*websocket.Conn
	// contains filtered or unexported fields
}

func NewLiveMsgStream

func NewLiveMsgStream(roomId int) *LiveMsgStream

func (*LiveMsgStream) ParseIter

func (s *LiveMsgStream) ParseIter(p liveMsgPacket) iter.Seq2[liveMsgPacket, error]

func (*LiveMsgStream) RunIter

func (s *LiveMsgStream) RunIter() iter.Seq2[string, error]

func (*LiveMsgStream) Stop

func (s *LiveMsgStream) Stop() *LiveMsgStream

type LiveRoomInfo

type LiveRoomInfo struct {
	Uid     int `json:"uid" mapstructure:"uid"`           // 主播mid
	RoomId  int `json:"room_id" mapstructure:"room_id"`   // 直播间长号
	ShortId int `json:"short_id" mapstructure:"short_id"` // 直播间短号, 为0是无短号

	Attention   int    `json:"attention" mapstructure:"attention"`     // 关注数量
	Online      int    `json:"online" mapstructure:"online"`           // 观看人数
	IsPortrait  bool   `json:"is_portrait" mapstructure:"is_portrait"` // 是否竖屏
	Description string `json:"description" mapstructure:"description"` // 描述
	LiveStatus  int    `json:"live_status" mapstructure:"live_status"` // 直播状态, 0: 未开播, 1: 直播中, 2: 轮播中

	AreaId         int    `json:"area_id" mapstructure:"area_id"`                   // 分区id
	ParentAreaId   int    `json:"parent_area_id" mapstructure:"parent_area_id"`     // 父分区id
	ParentAreaName string `json:"parent_area_name" mapstructure:"parent_area_name"` // 父分区名称
	OldAreaId      int    `json:"old_area_id" mapstructure:"old_area_id"`           // 旧版分区id

	Background string `json:"background" mapstructure:"background"` // 背景图片链接
	Title      string `json:"title" mapstructure:"title"`           // 标题
	UserCover  string `json:"user_cover" mapstructure:"user_cover"` // 封面
	Keyframe   string `json:"keyframe" mapstructure:"keyframe"`     // 关键帧, 开播后一段时间才有

	IsStrictRoom bool `json:"is_strict_room" mapstructure:"is_strict_room"`

	LiveTime string `json:"live_time" mapstructure:"live_time"` // 直播开始时间, 格式: `2006-01-02 15:04:05`
	Tags     string `json:"tags" mapstructure:"tags"`           // 标签, ','分隔
	IsAnchor int    `json:"is_anchor" mapstructure:"is_anchor"`

	RoomSilentType   string `json:"room_silent_type" mapstructure:"room_silent_type"`     // 禁言状态
	RoomSilentLevel  int    `json:"room_silent_level" mapstructure:"room_silent_level"`   // 禁言等级
	RoomSilentSecond int    `json:"room_silent_second" mapstructure:"room_silent_second"` // 禁言时间, 单位是秒

	AreaName     string `json:"area_name" mapstructure:"area_name"` // 分区名称
	Pendants     string `json:"pendants" mapstructure:"pendants"`
	AreaPendants string `json:"area_pendants" mapstructure:"area_pendants"`

	HotWords       []string `json:"hot_words" mapstructure:"hot_words"`               // 热词
	HotWordsStatus int      `json:"hot_words_status" mapstructure:"hot_words_status"` // 热词状态

	Verify string `json:"verify" mapstructure:"verify"`

	UpSession            string `json:"up_session" mapstructure:"up_session"`
	PkStatus             int    `json:"pk_status" mapstructure:"pk_status"` // pk状态
	PkId                 int    `json:"pk_id" mapstructure:"pk_id"`         // pk id
	BattleId             int    `json:"battle_id" mapstructure:"battle_id"`
	AllowChangeAreaTime  int    `json:"allow_change_area_time" mapstructure:"allow_change_area_time"`
	AllowUploadCoverTime int    `json:"allow_upload_cover_time" mapstructure:"allow_upload_cover_time"`
}

URL_LIVE_INFO_ROOMID "data"

func FetchLiveRoomInfo

func FetchLiveRoomInfo(roomId string) (lri LiveRoomInfo, err error)

FetchLiveRoomInfo 获取直播间信息, 拿不到用户名

func (*LiveRoomInfo) DoTemplate

func (lri *LiveRoomInfo) DoTemplate() string

LiveRoomInfo 中没有用户名信息, 更建议使用 LiveStatus.DoTemplate

func (*LiveRoomInfo) DoTemplateTo

func (lri *LiveRoomInfo) DoTemplateTo(w io.Writer) error

type LiveStatus

type LiveStatus struct {
	Title      string `json:"title" mapstructure:"title"`
	RoomId     int    `json:"room_id" mapstructure:"room_id"`
	Uid        int    `json:"uid" mapstructure:"uid"`
	Online     int    `json:"online" mapstructure:"online"`           // 在线人数
	LiveTime   int    `json:"live_time" mapstructure:"live_time"`     // 开播时间戳 (s)
	LiveStatus int    `json:"live_status" mapstructure:"live_status"` // 0 未开播, 1 直播中, 2 轮播中
	ShortId    int    `json:"short_id" mapstructure:"short_id"`       // 短号

	Area             int    `json:"area_id" mapstructure:"area_id"`                         // 分区id
	AreaName         string `json:"area_name" mapstructure:"area_name"`                     // 分区名
	AreaV2Id         int    `json:"area_v2_id" mapstructure:"area_v2_id"`                   // 新版分区id
	AreaV2Name       string `json:"area_v2_name" mapstructure:"area_v2_name"`               // 新版分区名
	AreaV2ParentName string `json:"area_v2_parent_name" mapstructure:"area_v2_parent_name"` // 父分区名
	AreaV2ParentId   int    `json:"area_v2_parent_id" mapstructure:"area_v2_parent_id"`     // 父分区id

	Uname   string `json:"uname" mapstructure:"uname"`       // 用户名
	Face    string `json:"face" mapstructure:"face"`         // 头像url
	TagName string `json:"tag_name" mapstructure:"tag_name"` // 标签, ','分隔
	Tags    string `json:"tags" mapstructure:"tags"`

	CoverFromUser string `json:"cover_from_user" mapstructure:"cover_from_user"` // 直播间封面url
	Keyframe      string `json:"keyframe" mapstructure:"keyframe"`               // 直播间关键帧url, 开播时才有

	LockTill      string `json:"lock_till" mapstructure:"lock_till"`
	HiddenTill    string `json:"hidden_till" mapstructure:"hidden_till"`
	BroadCastType int    `json:"broadcast_type" mapstructure:"broadcast_type"` // 0 普通, 1 手机直播
}

URL_LIVE_STATUS_UIDS "data.{{uid}}"

func (*LiveStatus) DoTemplate

func (ls *LiveStatus) DoTemplate() string

func (*LiveStatus) DoTemplateTo

func (ls *LiveStatus) DoTemplateTo(w io.Writer) error

type LiveStatusUid

type LiveStatusUid map[string]*LiveStatus // Uid -> LiveStatus

"data"

func FetchLiveStatus

func FetchLiveStatus(uid ...string) (lsu LiveStatusUid, err error)

FetchLiveStatus 批量获取直播间状态

有数据时返回 {..., "data": {"{{uid}}": {...}}}, json 正常解析

空数据时返回 {..., "data": []}, json 返回错误:

json: cannot unmarshal array into Go value of type biligo.LiveStatusUid

func (LiveStatusUid) DoTemplate

func (lsu LiveStatusUid) DoTemplate() map[string]string

func (LiveStatusUid) Get deprecated

func (lsu LiveStatusUid) Get(uid string) *LiveStatus

Deprecated: 直接使用 map 访问

type LoginCodeState

type LoginCodeState int
const (
	LOGIN_CODE_STATE_SUCCESS  LoginCodeState = 0     // 扫码登录成功
	LOGIN_CODE_STATE_EXPIRED  LoginCodeState = 86038 // 二维码已失效
	LOGIN_CODE_STATE_SCANED   LoginCodeState = 86090 // 二维码已扫码未确认
	LOGIN_CODE_STATE_UNSCANED LoginCodeState = 86101 // 未扫码
)

func (LoginCodeState) String

func (lcs LoginCodeState) String() string

type Media

type Media struct {
	Actors string `json:"actors" mapstructure:"actors"`
	Alias  string `json:"alias" mapstructure:"alias"`

	Areas []mediaArea `json:"areas" mapstructure:"areas"`

	BkgCover string `json:"bkg_cover" mapstructure:"bkg_cover"`
	Cover    string `json:"cover" mapstructure:"cover"`

	Episodes []mediaEpisode `json:"episodes" mapstructure:"episodes"`

	Evaluate string `json:"evaluate" mapstructure:"evaluate"` // 简介
	JpTitle  string `json:"jp_title" mapstructure:"jp_title"`
	Link     string `json:"link" mapstructure:"link"` // mdid
	MediaId  int    `json:"media_id" mapstructure:"media_id"`
	Mode     int    `json:"mode" mapstructure:"mode"`

	NewEp struct {
		Desc  string `json:"desc" mapstructure:"desc"` // "已完结, 全12话"
		Id    int    `json:"id" mapstructure:"id"`
		IsNew int    `json:"is_new" mapstructure:"is_new"`
		Title string `json:"title" mapstructure:"title"`
	} `json:"new_ep" mapstructure:"new_ep"`

	Publish struct {
		IsFinish      int    `json:"is_finish" mapstructure:"is_finish"`
		IsStarted     int    `json:"is_started" mapstructure:"is_started"`
		PubTime       string `json:"pub_time" mapstructure:"pub_time"`           // "2006-01-02 15:04:05"
		PubTimeShow   string `json:"pub_time_show" mapstructure:"pub_time_show"` // "2006年01月02日15:04"
		UnknowPubDate int    `json:"unknow_pub_date" mapstructure:"unknow_pub_date"`
		Weekday       int    `json:"weekday" mapstructure:"weekday"`
	} `json:"publish" mapstructure:"publish"`

	Rating mediaRating `json:"rating" mapstructure:"rating"`
	Record string      `json:"record" mapstructure:"record"` // 备案号

	SeasonId    int    `json:"season_id" mapstructure:"season_id"`
	SeasonTitle string `json:"season_title" mapstructure:"season_title"`

	Series struct {
		DisplayType int    `json:"display_type" mapstructure:"display_type"`
		SeriesId    int    `json:"series_id" mapstructure:"series_id"`
		SeriesTitle string `json:"series_title" mapstructure:"series_title"`
	} `json:"series" mapstructure:"series"`

	ShareCopy     string `json:"share_copy" mapstructure:"share_copy"`
	ShareSubTitle string `json:"share_sub_title" mapstructure:"share_sub_title"`
	ShareUrl      string `json:"share_url" mapstructure:"share_url"` // ssid

	SquareCover string `json:"square_cover" mapstructure:"square_cover"`
	Staff       string `json:"staff" mapstructure:"staff"`

	Stat struct {
		Coins      int    `json:"coins" mapstructure:"coins"`
		Danmakus   int    `json:"danmakus" mapstructure:"danmakus"`
		Favorite   int    `json:"favorite" mapstructure:"favorite"`
		Favorites  int    `json:"favorites" mapstructure:"favorites"`
		FollowText string `json:"follow_text" mapstructure:"follow_text"`
		Likes      int    `json:"likes" mapstructure:"likes"`
		Reply      int    `json:"reply" mapstructure:"reply"`
		Share      int    `json:"share" mapstructure:"share"`
		Views      int    `json:"views" mapstructure:"views"`
		Vt         int    `json:"vt" mapstructure:"vt"`
	} `json:"stat" mapstructure:"stat"`

	Status   int      `json:"status" mapstructure:"status"`
	Styles   []string `json:"styles" mapstructure:"styles"`
	SubTitle string   `json:"subtitle" mapstructure:"subtitle"` // "已观看1.7亿次"
	Title    string   `json:"title" mapstructure:"title"`
	Total    int      `json:"total" mapstructure:"total"`
	Type     int      `json:"type" mapstructure:"type"`
}

URL_MEDIA_INFO_DETAIL "result"

incomplete

func FetchMediaInfoEpid

func FetchMediaInfoEpid(epid string) (m Media, err error)

FetchMediaInfoEpid 获取剧集明细

func FetchMediaInfoSsid

func FetchMediaInfoSsid(ssid string) (m Media, err error)

FetchMediaInfoSsid 获取剧集明细

func (*Media) DoTemplate

func (m *Media) DoTemplate() string

func (*Media) DoTemplateTo

func (m *Media) DoTemplateTo(w io.Writer) error

type MediaBase

type MediaBase struct {
	Media struct {
		Areas []mediaArea `json:"areas" mapstructure:"areas"`

		Cover             string `json:"cover" mapstructure:"cover"`
		HorizontalPicture string `json:"horizontal_picture" mapstructure:"horizontal_picture"`
		MediaId           int    `json:"media_id" mapstructure:"media_id"` // 1

		NewEp struct {
			Id        int    `json:"id" mapstructure:"id"`
			Index     string `json:"index" mapstructure:"index"`
			IndexShow string `json:"index_show" mapstructure:"index_show"` // "第1话"
		} `json:"new_ep" mapstructure:"new_ep"`

		Rating mediaRating `json:"rating" mapstructure:"rating"`

		SeasonId int    `json:"season_id" mapstructure:"season_id"`
		ShareUrl string `json:"share_url" mapstructure:"share_url"`
		Title    string `json:"title" mapstructure:"title"`
		Type     int    `json:"type" mapstructure:"type"`           // 1
		TypeName string `json:"type_name" mapstructure:"type_name"` // "番剧"
	} `json:"media" mapstructure:"media"`
}

URL_MEDIA_INFO_BASE "result"

func FetchMediaInfoBase

func FetchMediaInfoBase(mdid string) (mb MediaBase, err error)

FetchMediaInfoBase 获取剧集基本信息

func (*MediaBase) DoTemplate

func (mb *MediaBase) DoTemplate() string

func (*MediaBase) DoTemplateTo

func (mb *MediaBase) DoTemplateTo(w io.Writer) error

type MediaSection

type MediaSection struct {
	MainSection mediaSection   `json:"main_section" mapstructure:"main_section"`
	Section     []mediaSection `json:"section" mapstructure:"section"`
}

URL_MEDIA_SECTION "result"

func FetchMediaSection

func FetchMediaSection(ssid string) (ms MediaSection, err error)

FetchMediaSection 获取剧集分集信息

type Nav struct {
	IsLogin       bool   `json:"isLogin" mapstructure:"isLogin"`
	EmailVerified int    `json:"email_verified" mapstructure:"email_verified"`
	Face          string `json:"face" mapstructure:"face"`
	FaceNft       int    `json:"face_nft" mapstructure:"face_nft"`
	FaceNftType   int    `json:"face_nft_type" mapstructure:"face_nft_type"`
	LevelInfo     struct {
		CurrentLevel int    `json:"current_level" mapstructure:"current_level"`
		CurrentMin   int    `json:"current_min" mapstructure:"current_min"`
		CurrentExp   int    `json:"current_exp" mapstructure:"current_exp"`
		NextExp      string `json:"next_exp" mapstructure:"next_exp"`
	} `json:"level_info" mapstructure:"level_info"`
	Mid            int     `json:"mid" mapstructure:"mid"`
	MobileVerified int     `json:"mobile_verified" mapstructure:"mobile_verified"`
	Money          float64 `json:"money" mapstructure:"money"`
	Moral          int     `json:"moral" mapstructure:"moral"`
	Official       struct {
		Role  int    `json:"role" mapstructure:"role"`
		Title string `json:"title" mapstructure:"title"`
		Desc  string `json:"desc" mapstructure:"desc"`
		Type  int    `json:"type" mapstructure:"type"`
	} `json:"official" mapstructure:"official"`
	OfficialVerify struct {
		Type int    `json:"type" mapstructure:"type"`
		Desc string `json:"desc" mapstructure:"desc"`
	} `json:"officialVerify" mapstructure:"officialVerify"`
	Pendant struct {
		Pid               int    `json:"pid" mapstructure:"pid"`
		Name              string `json:"name" mapstructure:"name"`
		Image             string `json:"image" mapstructure:"image"`
		Expire            int    `json:"expire" mapstructure:"expire"`
		ImageEnhance      string `json:"image_enhance" mapstructure:"image_enhance"`
		ImageEnhanceFrame string `json:"image_enhance_frame" mapstructure:"image_enhance_frame"`
		NPid              int    `json:"n_pid" mapstructure:"n_pid"`
	} `json:"pendant" mapstructure:"pendant"`
	Scores       int    `json:"scores" mapstructure:"scores"`
	Uname        string `json:"uname" mapstructure:"uname"`
	VipDueDate   int64  `json:"vipDueDate" mapstructure:"vipDueDate"`
	VipStatus    int    `json:"vipStatus" mapstructure:"vipStatus"`
	VipType      int    `json:"vipType" mapstructure:"vipType"`
	VipPayType   int    `json:"vip_pay_type" mapstructure:"vip_pay_type"`
	VipThemeType int    `json:"vip_theme_type" mapstructure:"vip_theme_type"`
	VipLabel     struct {
		Path                  string `json:"path" mapstructure:"path"`
		Text                  string `json:"text" mapstructure:"text"`
		LabelTheme            string `json:"label_theme" mapstructure:"label_theme"`
		TextColor             string `json:"text_color" mapstructure:"text_color"`
		BgStyle               int    `json:"bg_style" mapstructure:"bg_style"`
		BgColor               string `json:"bg_color" mapstructure:"bg_color"`
		BorderColor           string `json:"border_color" mapstructure:"border_color"`
		UseImgLabel           bool   `json:"use_img_label" mapstructure:"use_img_label"`
		ImgLabelUriHans       string `json:"img_label_uri_hans" mapstructure:"img_label_uri_hans"`
		ImgLabelUriHant       string `json:"img_label_uri_hant" mapstructure:"img_label_uri_hant"`
		ImgLabelUriHansStatic string `json:"img_label_uri_hans_static" mapstructure:"img_label_uri_hans_static"`
		ImgLabelUriHantStatic string `json:"img_label_uri_hant_static" mapstructure:"img_label_uri_hant_static"`
	} `json:"vip_label" mapstructure:"vip_label"`
	VipAvatarSubscript int    `json:"vip_avatar_subscript" mapstructure:"vip_avatar_subscript"`
	VipNicknameColor   string `json:"vip_nickname_color" mapstructure:"vip_nickname_color"`
	Vip                struct {
		Type       int   `json:"type" mapstructure:"type"`
		Status     int   `json:"status" mapstructure:"status"`
		DueDate    int64 `json:"due_date" mapstructure:"due_date"`
		VipPayType int   `json:"vip_pay_type" mapstructure:"vip_pay_type"`
		ThemeType  int   `json:"theme_type" mapstructure:"theme_type"`
		Label      struct {
			Path                  string `json:"path" mapstructure:"path"`
			Text                  string `json:"text" mapstructure:"text"`
			LabelTheme            string `json:"label_theme" mapstructure:"label_theme"`
			TextColor             string `json:"text_color" mapstructure:"text_color"`
			BgStyle               int    `json:"bg_style" mapstructure:"bg_style"`
			BgColor               string `json:"bg_color" mapstructure:"bg_color"`
			BorderColor           string `json:"border_color" mapstructure:"border_color"`
			UseImgLabel           bool   `json:"use_img_label" mapstructure:"use_img_label"`
			ImgLabelUriHans       string `json:"img_label_uri_hans" mapstructure:"img_label_uri_hans"`
			ImgLabelUriHant       string `json:"img_label_uri_hant" mapstructure:"img_label_uri_hant"`
			ImgLabelUriHansStatic string `json:"img_label_uri_hans_static" mapstructure:"img_label_uri_hans_static"`
			ImgLabelUriHantStatic string `json:"img_label_uri_hant_static" mapstructure:"img_label_uri_hant_static"`
		} `json:"label" mapstructure:"label"`
		AvatarSubscript    int    `json:"avatar_subscript" mapstructure:"avatar_subscript"`
		NicknameColor      string `json:"nickname_color" mapstructure:"nickname_color"`
		Role               int    `json:"role" mapstructure:"role"`
		AvatarSubscriptUrl string `json:"avatar_subscript_url" mapstructure:"avatar_subscript_url"`
		TvVipStatus        int    `json:"tv_vip_status" mapstructure:"tv_vip_status"`
		TvVipPayType       int    `json:"tv_vip_pay_type" mapstructure:"tv_vip_pay_type"`
		TvDueDate          int    `json:"tv_due_date" mapstructure:"tv_due_date"`
	} `json:"vip" mapstructure:"vip"`
	Wallet struct {
		Mid           int `json:"mid" mapstructure:"mid"`
		BcoinBalance  int `json:"bcoin_balance" mapstructure:"bcoin_balance"`
		CouponBalance int `json:"coupon_balance" mapstructure:"coupon_balance"`
		CouponDueTime int `json:"coupon_due_time" mapstructure:"coupon_due_time"`
	} `json:"wallet" mapstructure:"wallet"`
	HasShop        bool   `json:"has_shop" mapstructure:"has_shop"`
	ShopUrl        string `json:"shop_url" mapstructure:"shop_url"`
	AllowanceCount int    `json:"allowance_count" mapstructure:"allowance_count"`
	AnswerStatus   int    `json:"answer_status" mapstructure:"answer_status"`
	IsSeniorMember int    `json:"is_senior_member" mapstructure:"is_senior_member"`
	WbiImg         struct {
		ImgUrl string `json:"img_url" mapstructure:"img_url"`
		SubUrl string `json:"sub_url" mapstructure:"sub_url"`
	} `json:"wbi_img" mapstructure:"wbi_img"`
	IsJury bool `json:"is_jury" mapstructure:"is_jury"`
}

"data"

func FetchNav

func FetchNav() (nav Nav, err error)

FetchNav 获取导航栏用户信息

type ParseResult

type ParseResult struct {
	Type    LinkType
	Content string
}
func ParseLink(s string) (results []ParseResult, err error)

ParseLink 解析多个链接并去重, 返回错误的原因只有解析短链时的网络问题

func (ParseResult) FetchFormat

func (r ParseResult) FetchFormat() (string, error)

type QrcodeGenerate

type QrcodeGenerate struct {
	Url       string `json:"url" mapstructure:"url"`               // 二维码内容
	QrcodeKey string `json:"qrcode_key" mapstructure:"qrcode_key"` // 轮询时 query
}

"data"

func FetchLoginQrcodeGenerate

func FetchLoginQrcodeGenerate() (qg QrcodeGenerate, err error)

FetchLoginQrcodeGenerate 申请登录二维码

type QrcodePoll

type QrcodePoll struct {
	Url          string `json:"url" mapstructure:"url"`
	RefreshToken string `json:"refresh_token" mapstructure:"refresh_token"`
	Timestamp    int    `json:"timestamp" mapstructure:"timestamp"`
	Code         int    `json:"code" mapstructure:"code"` // [LoginCodeState]
	Message      string `json:"message" mapstructure:"message"`
}

"data"

func FetchLoginQrcodePoll

func FetchLoginQrcodePoll(qrcodeKey string) (qp QrcodePoll, header http.Header, err error)

FetchLoginQrcodePoll 扫码登录轮询

type RelationStat

type RelationStat struct {
	Mid       int `json:"mid" mapstructure:"mid"`
	Following int `json:"following" mapstructure:"following"` // 关注数
	Whisper   int `json:"whisper" mapstructure:"whisper"`
	Black     int `json:"black" mapstructure:"black"`
	Follower  int `json:"follower" mapstructure:"follower"` // 粉丝数
}

"data"

func FetchRelationStat

func FetchRelationStat(uid string) (rs RelationStat, err error)

FetchRelationStat 获取关注/粉丝数

type ReplyList

type ReplyList struct {
	Page struct {
		Num    int `json:"num" mapstructure:"num"`
		Size   int `json:"size" mapstructure:"size"`
		Count  int `json:"count" mapstructure:"count"`
		Acount int `json:"acount" mapstructure:"acount"`
	} `json:"page" mapstructure:"page"`
	// Config struct{} `json:"config" mapstructure:"config"`
	// Replies []struct{} `json:"replies" mapstructure:"replies"`
	// TopReplies []struct{} `json:"top_replies" mapstructure:"top_replies"`
	Upper struct {
		Mid int `json:"mid" mapstructure:"mid"` // uid
		Top struct {
			Member struct {
				Mid    string `json:"mid" mapstructure:"mid"`
				Uname  string `json:"uname" mapstructure:"uname"`
				Sex    string `json:"sex" mapstructure:"sex"`
				Sign   string `json:"sign" mapstructure:"sign"`
				Avatar string `json:"avatar" mapstructure:"avatar"`
			} `json:"member" mapstructure:"member"`
			Content struct {
				Message string `json:"message" mapstructure:"message"`
				// Members []any `json:"members" mapstructure:"members"`
				// Emote struct{} `json:"emote" mapstructure:"emote"`
				// JumpUrl struct{} `json:"jump_url" mapstructure:"jump_url"`
				MaxLine int `json:"max_line" mapstructure:"max_line"`
			} `json:"content" mapstructure:"content"`
		} `json:"top" mapstructure:"top"`
		Vote *VoteInfo `json:"vote" mapstructure:"vote"` // ?TODO: complete
	} `json:"upper" mapstructure:"upper"` // 置顶
}

"data"

func FetchReplyList

func FetchReplyList(typ CommentClass, oid string) (rl ReplyList, err error)

FetchReplyList 获取评论列表

type Request

type Request struct {
	*http.Request
	// contains filtered or unexported fields
}

func NewGet

func NewGet(url string) *Request

func NewGetCtx

func NewGetCtx(ctx context.Context, url string) *Request

func NewHead

func NewHead(url string) *Request

func NewHeadCtx

func NewHeadCtx(ctx context.Context, url string) *Request

func NewPost

func NewPost(url, contentType string, body io.Reader) *Request

func NewPostCtx

func NewPostCtx(ctx context.Context, url, contentType string, body io.Reader) *Request

func ReqArticleInfo

func ReqArticleInfo(id string) *Request

func ReqAudio

func ReqAudio(sid string) (info, tag, member, lyric *Request)

func ReqBuvid34

func ReqBuvid34() *Request

func ReqDynamicAll

func ReqDynamicAll() *Request

func ReqDynamicAllUpdate

func ReqDynamicAllUpdate(updateBaseline string) *Request

func ReqDynamicDetail

func ReqDynamicDetail(id string) *Request

func ReqDynamicDetailDesktop

func ReqDynamicDetailDesktop(id string) *Request

func ReqDynamicSpace

func ReqDynamicSpace(uid string) *Request

func ReqDynamicSpaceDesktop

func ReqDynamicSpaceDesktop(uid string) *Request

func ReqLiveDanmuInfo

func ReqLiveDanmuInfo(roomId string) *Request

func ReqLiveRoomInfo

func ReqLiveRoomInfo(roomId string) *Request

func ReqLiveStatus

func ReqLiveStatus(uid ...string) *Request

func ReqLoginQrcodeGenerate

func ReqLoginQrcodeGenerate() *Request

func ReqLoginQrcodePoll

func ReqLoginQrcodePoll(qrcodeKey string) *Request

func ReqMediaInfoBase

func ReqMediaInfoBase(mdid string) *Request

func ReqMediaInfoEpid

func ReqMediaInfoEpid(epid string) *Request

func ReqMediaInfoSsid

func ReqMediaInfoSsid(ssid string) *Request

func ReqMediaSection

func ReqMediaSection(ssid string) *Request

func ReqNav

func ReqNav() *Request

func ReqRelationStat

func ReqRelationStat(uid string) *Request

func ReqReplyList

func ReqReplyList(typ CommentClass, oid string) *Request

func ReqSearchAll

func ReqSearchAll(keyword string) *Request

func ReqSearchType

func ReqSearchType(searchType SearchClass, keyword string) *Request

func ReqSpaceCard

func ReqSpaceCard(uid string) *Request

func ReqVideoConclusion

func ReqVideoConclusion(aid, cid string) *Request

func ReqVideoInfo

func ReqVideoInfo(aid string) *Request

func ReqVideoOnline

func ReqVideoOnline(aid, cid string) *Request

func ReqVideoPlayurl

func ReqVideoPlayurl(q ...string) *Request

func ReqVoteInfo

func ReqVoteInfo(voteId string) *Request

func (*Request) Std

func (req *Request) Std() *http.Request

func (*Request) WbiSign

func (req *Request) WbiSign() *Request

func (*Request) WithQuery

func (req *Request) WithQuery(k, v string) *Request

func (*Request) WithQueryList

func (req *Request) WithQueryList(k string, v ...string) *Request

func (*Request) WithQuerys

func (req *Request) WithQuerys(kv ...string) *Request

type Response

type Response struct {
	*http.Response
}

func (*Response) Std

func (resp *Response) Std() *http.Response

func (*Response) ToGjson

func (resp *Response) ToGjson() (j gjson.Result, err error)

func (*Response) UnmarshalTo

func (resp *Response) UnmarshalTo(v any) error

type SearchAll

type SearchAll struct {

	// "video", "bangumi", ...
	PageInfo map[string]searchPageInfo `json:"page_info" mapstructure:"page_info"`
	Result   []struct {
		ResultType string           `json:"result_type" mapstructure:"result_type"`
		Data       []map[string]any `json:"data" mapstructure:"data"`
	} `json:"result" mapstructure:"result"`
	// contains filtered or unexported fields
}

"data"

type SearchClass

type SearchClass string

func (SearchClass) String

func (st SearchClass) String() string

type SearchType

type SearchType struct {
	Result []map[string]any `json:"result" mapstructure:"result"`
	// contains filtered or unexported fields
}

"data"

type SearchTypeLive

type SearchTypeLive struct {
	Pageinfo struct {
		LiveUser searchPageInfo `json:"live_user" mapstructure:"live_user"`
		LiveRoom searchPageInfo `json:"live_room" mapstructure:"live_room"`
	} `json:"pageinfo" mapstructure:"pageinfo"`
	Result struct {
		LiveUser map[string]any `json:"live_user" mapstructure:"live_user"`
		LiveRoom map[string]any `json:"live_room" mapstructure:"live_room"`
	} `json:"result" mapstructure:"result"`
	// contains filtered or unexported fields
}

"data"

type Song

type Song struct {
	Info   SongInfo
	Tag    SongTag
	Member SongMember
	Lyric  SongLyric
}

func FetchSong

func FetchSong(auid string) (song Song, err error)

FetchSong 获取音乐信息

func (*Song) DoTemplate

func (s *Song) DoTemplate() string

func (*Song) DoTemplateTo

func (s *Song) DoTemplateTo(w io.Writer) error

type SongInfo

type SongInfo struct {
	Id     int    `json:"id" mapstructure:"id"`
	Uid    int    `json:"uid" mapstructure:"uid"`
	Uname  string `json:"uname" mapstructure:"uname"`
	Author string `json:"author" mapstructure:"author"` // 作者名
	Title  string `json:"title" mapstructure:"title"`
	Cover  string `json:"cover" mapstructure:"cover"` // 封面图片url
	Intro  string `json:"intro" mapstructure:"intro"` // 简介
	Lyric  string `json:"lyric" mapstructure:"lyric"` // lrc歌词url

	Crtype int `json:"crtype" mapstructure:"crtype"` // 1

	Duration int `json:"duration" mapstructure:"duration"` // 时长 (s)
	Passtime int `json:"passtime" mapstructure:"passtime"` // 发布时间 (s)
	Curtime  int `json:"curtime" mapstructure:"curtime"`   // 当前请求时间 (s)

	Aid  int    `json:"aid" mapstructure:"aid"`   // 关联稿件
	Bvid string `json:"bvid" mapstructure:"bvid"` // 关联稿件
	Cid  int    `json:"cid" mapstructure:"cid"`   // 关联稿件

	Msid       int    `json:"msid" mapstructure:"msid"`
	Attr       int    `json:"attr" mapstructure:"attr"`
	Limit      int    `json:"limit" mapstructure:"limit"`
	ActivityId int    `json:"activity_id" mapstructure:"activity_id"`
	Limitdesc  string `json:"limitdesc" mapstructure:"limitdesc"`

	CoinNum int `json:"coin_num" mapstructure:"coin_num"` // 投币
	CTime   int `json:"ctime" mapstructure:"ctime"`       // 投稿时间 (ms)

	Statistic struct {
		Sid     int `json:"sid" mapstructure:"sid"`         // auid
		Play    int `json:"play" mapstructure:"play"`       // 播放
		Collect int `json:"collect" mapstructure:"collect"` // 收藏
		Comment int `json:"comment" mapstructure:"comment"` // 评论
		Share   int `json:"share" mapstructure:"share"`     // 分享
	} `json:"statistic" mapstructure:"statistic"`

	CollectIds []int `json:"collectIds" mapstructure:"collectIds"` // 歌曲所在的收藏夹mlid
	IsCooper   bool  `json:"isCooper" mapstructure:"isCooper"`     // ?
}

URL_SONG_INFO "data"

type SongLyric

type SongLyric = string

URL_SONG_LIRIC "data"

lrc 格式

type SongMember

type SongMember []struct {
	Type int `json:"type" mapstructure:"type"` // [SongMemberMap]
	List []struct {
		Mid      int    `json:"mid" mapstructure:"mid"`             // 0
		MemberId int    `json:"member_id" mapstructure:"member_id"` // ?
		Name     string `json:"name" mapstructure:"name"`           // 昵称
	} `json:"list" mapstructure:"list"`
}

URL_SONG_MEMBER "data"

只有 Type 与 List.Name 字段是有用的

func (SongMember) Format

func (sm SongMember) Format(format string, sep string, subSep string) string

Format 格式化成员信息

"%s:%s", "\n", "/"

歌手:师欣/琉盈君/花音/小小六
作词:小小六
...

func (SongMember) Ok

func (sm SongMember) Ok() bool

func (SongMember) String

func (sm SongMember) String() string

type SongTag

type SongTag []struct {
	Type    string `json:"type" mapstructure:"type"` // "song"
	Subtype int    `json:"subtype" mapstructure:"subtype"`
	Key     int    `json:"key" mapstructure:"key"`
	Info    string `json:"info" mapstructure:"info"` // "音乐", "人声", "翻唱", "粤语", "偶像", "流行"...
}

URL_SONG_TAG "data"

只有 Info 字段是有用的

func (SongTag) Join

func (st SongTag) Join(sep string) string

Join 格式化 Info 字段, 用 sep 分隔

func (SongTag) Ok

func (st SongTag) Ok() bool

func (SongTag) String

func (st SongTag) String() string

type SpaceCard

type SpaceCard struct {
	Card struct {
		Mid       string `json:"mid" mapstructure:"mid"`             // uid
		Name      string `json:"name" mapstructure:"name"`           // 昵称
		Sex       string `json:"sex" mapstructure:"sex"`             // 性别 // "男"
		Face      string `json:"face" mapstructure:"face"`           // 头像 url
		Spacesta  int    `json:"spacesta" mapstructure:"spacesta"`   // 0: 正常, -2: 封禁
		Fans      int    `json:"fans" mapstructure:"fans"`           // 粉丝数
		Friend    int    `json:"friend" mapstructure:"friend"`       // 关注数
		Attention int    `json:"attention" mapstructure:"attention"` // 关注数

		Sign string `json:"sign" mapstructure:"sign"` // 签名

		LevelInfo struct {
			CurrentLevel int `json:"current_level" mapstructure:"current_level"`
			CurrentMin   int `json:"current_min" mapstructure:"current_min"`
			CurrentExp   int `json:"current_exp" mapstructure:"current_exp"`
			NextExp      int `json:"next_exp" mapstructure:"next_exp"`
		} `json:"level_info" mapstructure:"level_info"`

		Pendant struct {
			Pid               int    `json:"pid" mapstructure:"pid"`
			Name              string `json:"name" mapstructure:"name"`
			Image             string `json:"image" mapstructure:"image"`
			Expire            int    `json:"expire" mapstructure:"expire"`
			ImageEnhance      string `json:"image_enhance" mapstructure:"image_enhance"`
			ImageEnhanceFrame string `json:"image_enhance_frame" mapstructure:"image_enhance_frame"`
			NPid              int    `json:"n_pid" mapstructure:"n_pid"`
		} `json:"pendant" mapstructure:"pendant"`
	} `json:"card" mapstructure:"card"`

	Space struct {
		SImg string `json:"s_img" mapstructure:"s_img"`
		LImg string `json:"l_img" mapstructure:"l_img"`
	}

	ArchiveCount int `json:"archive_count" mapstructure:"archive_count"` // 投稿数
	ArticleCount int `json:"article_count" mapstructure:"article_count"` // 专栏数 // 0, Deprecated?
	Follower     int `json:"follower" mapstructure:"follower"`           // 粉丝数
	LikeNum      int `json:"like_num" mapstructure:"like_num"`           // 获赞数
}

URL_SPACE_CARD "data"

func FetchSpaceCard

func FetchSpaceCard(uid string) (sc SpaceCard, err error)

FetchSpaceCard 获取用户名片信息

func (*SpaceCard) DoTemplate

func (sc *SpaceCard) DoTemplate() string

func (*SpaceCard) DoTemplateTo

func (sc *SpaceCard) DoTemplateTo(w io.Writer) error

type Templatable

type Templatable interface {
	DoTemplate() string
	DoTemplateTo(io.Writer) error
}

Templatable 用于明确声明类型支持模板格式化

func FormatSearch

func FormatSearch(results []gjson.Result) []Templatable

func FormatSearchAll

func FormatSearchAll(j gjson.Result) []Templatable

func FormatSearchType

func FormatSearchType(j gjson.Result) []Templatable

func SearchFormatAll

func SearchFormatAll(keyword string) ([]Templatable, error)

func SearchFormatAuto

func SearchFormatAuto(searchType SearchClass, keyword string) ([]Templatable, error)

SearchFormatAuto 在 searchType 为空字符串时使用综合搜索, 返回值可被断言为: *VideoInfo, *Media, *LiveStatus, *ArticleInfo, *SpaceCard, *Error

func SearchFormatType

func SearchFormatType(searchType SearchClass, keyword string) ([]Templatable, error)

type TemplateConfig

type TemplateConfig struct {
	Template string
	Funcs    template.FuncMap
}

type VideoCodec

type VideoCodec = string
const (
	VIDEO_CODEC_AV1  VideoCodec = "av01.0.00M.10.0.110.01.01.01.0"
	VIDEO_CODEC_AVC  VideoCodec = "avc1.640034"
	VIDEO_CODEC_HEVC VideoCodec = "hev1.1.6.L153.90"
)
const (
	AUDIO_CODEC_M4A VideoCodec = "mp4a.40.2"
)

type VideoConclusion

type VideoConclusion struct {
	Code        int              `json:"code" mapstructure:"code"`
	ModelResult conclusionResult `json:"model_result" mapstructure:"model_result"`
	Stid        string           `json:"stid" mapstructure:"stid"`
	Status      int              `json:"status" mapstructure:"status"`
	LikeNum     int              `json:"like_num" mapstructure:"like_num"`
	DislikeNum  int              `json:"dislike_num" mapstructure:"dislike_num"`
}

URL_VIDEO_CONCLUSION_WBI "data"

func FetchVideoConclusion

func FetchVideoConclusion(id, cid string) (vc VideoConclusion, err error)

FetchVideoConclusion 获取视频AI总结

id: avid/bvid
cid: 分 p 对应的 cid

func (*VideoConclusion) DoTemplate

func (vc *VideoConclusion) DoTemplate() string

func (*VideoConclusion) DoTemplateTo

func (vc *VideoConclusion) DoTemplateTo(w io.Writer) error

func (*VideoConclusion) Ok

func (vcf *VideoConclusion) Ok() bool

type VideoDownload

type VideoDownload struct {
	// contains filtered or unexported fields
}

func NewDownloadVideoMp4

func NewDownloadVideoMp4(ctx context.Context, id, cid string, qn VideoQuality) *VideoDownload

func (*VideoDownload) Init

func (vd *VideoDownload) Init() (size int64, err error)

Init 返回文件大小以便提前申请内存

func (*VideoDownload) Start

func (vd *VideoDownload) Start(w io.Writer) (written int64, err error)

type VideoFormat

type VideoFormat = int
const (
	VIDEO_FNVAL_FLV VideoFormat = 0
	VIDEO_FNVAL_MP4 VideoFormat = 1

	VIDEO_FNVAL_DASH        VideoFormat = 16
	VIDEO_FNVAL_HDR         VideoFormat = 64
	VIDEO_FNVAL_4K          VideoFormat = 128
	VIDEO_FNVAL_DOLBYAUDIO  VideoFormat = 256
	VIDEO_FNVAL_DOLBYVISION VideoFormat = 512
	VIDEO_FNVAL_8K          VideoFormat = 1024
	VIDEO_FNVAL_AV1         VideoFormat = 2048

	VIDED_FNVAL_DASHALL VideoFormat = VIDEO_FNVAL_DASH |
		VIDEO_FNVAL_HDR |
		VIDEO_FNVAL_4K |
		VIDEO_FNVAL_DOLBYAUDIO |
		VIDEO_FNVAL_DOLBYVISION |
		VIDEO_FNVAL_8K |
		VIDEO_FNVAL_AV1
)

type VideoInfo

type VideoInfo struct {
	Bvid      string `json:"bvid" mapstructure:"bvid"`
	Aid       int    `json:"aid" mapstructure:"aid"`
	Videos    int    `json:"videos" mapstructure:"videos"`       // 分P数
	Copyright int    `json:"copyright" mapstructure:"copyright"` // 1: 原创, 2: 转载
	Pic       string `json:"pic" mapstructure:"pic"`             // 封面 url
	Title     string `json:"title" mapstructure:"title"`         // 标题
	PubDate   int    `json:"pubdate" mapstructure:"pubdate"`     // 发布时间
	CTime     int    `json:"ctime" mapstructure:"ctime"`         // 投稿时间
	Desc      string `json:"desc" mapstructure:"desc"`           // 简介
	State     int    `json:"state" mapstructure:"state"`         // 状态 // TODO: complete
	Duration  int    `json:"duration" mapstructure:"duration"`   // 所有分P总时长(s)

	Owner struct {
		Mid  int    `json:"mid" mapstructure:"mid"`
		Name string `json:"name" mapstructure:"name"`
		Face string `json:"face" mapstructure:"face"`
	} `json:"owner" mapstructure:"owner"`

	Stat struct {
		Aid        int    `json:"aid" mapstructure:"aid"`
		View       int    `json:"view" mapstructure:"view"`         // 播放
		Danmaku    int    `json:"danmaku" mapstructure:"danmaku"`   // 弹幕
		Reply      int    `json:"reply" mapstructure:"reply"`       // 评论
		Favorite   int    `json:"favorite" mapstructure:"favorite"` // 收藏
		Coin       int    `json:"coin" mapstructure:"coin"`         // 投币
		Share      int    `json:"share" mapstructure:"share"`
		NowRank    int    `json:"now_rank" mapstructure:"now_rank"`
		HisRank    int    `json:"his_rank" mapstructure:"his_rank"`
		Like       int    `json:"like" mapstructure:"like"`       // 点赞
		Dislike    int    `json:"dislike" mapstructure:"dislike"` // 0, Deprecated?
		Evaluation string `json:"evaluation" mapstructure:"evaluation"`
		Vt         int    `json:"vt" mapstructure:"vt"`
	} `json:"stat" mapstructure:"stat"`

	ArgueInfo struct {
		ArgueMsg  string `json:"argue_msg" mapstructure:"argue_msg"`
		ArgueType int    `json:"argue_type" mapstructure:"argue_type"`
		ArgueLink string `json:"argue_link" mapstructure:"argue_link"`
	} `json:"argue_info" mapstructure:"argue_info"`

	Dynamic   string         `json:"dynamic" mapstructure:"dynamic"`     // 视频同步发布的的动态的文字内容
	Cid       int            `json:"cid" mapstructure:"cid"`             // P1的 cid
	Dimension videoDimension `json:"dimension" mapstructure:"dimension"` // P1的分辨率

	IsChargeableSeason      bool `json:"is_chargeable_season" mapstructure:"is_chargeable_season"`
	IsStory                 bool `json:"is_story" mapstructure:"is_story"`
	IsUpowerExclusive       bool `json:"is_upower_exclusive" mapstructure:"is_upower_exclusive"` // 充电专属视频
	IsUpowerPay             bool `json:"is_upower_pay" mapstructure:"is_upower_pay"`
	IsUpowerPreview         bool `json:"is_upower_preview" mapstructure:"is_upower_preview"` // 是否支持试看
	IsUpowerExclusiveWithQa bool `json:"is_upower_exclusive_with_qa" mapstructure:"is_upower_exclusive_with_qa"`
	NoCache                 bool `json:"no_cache" mapstructure:"no_cache"` // 是否禁止缓存

	Pages []videoPage `json:"pages" mapstructure:"pages"` // 分P信息

	Online VideoOnline `json:"-" mapstructure:"-"` // 在线人数, 仅用于格式化
}

URL_VIDEO_INFO_WBI, URL_VIDEO_INFO "data"

func FetchVideoInfo

func FetchVideoInfo(id string) (vi VideoInfo, err error)

FetchVideoInfo 获取视频信息

id: avid/bvid

func (*VideoInfo) DoTemplate

func (vi *VideoInfo) DoTemplate() string

func (*VideoInfo) DoTemplateTo

func (vi *VideoInfo) DoTemplateTo(w io.Writer) error

func (*VideoInfo) GetReplyList

func (vi *VideoInfo) GetReplyList() (rl ReplyList, err error)

func (*VideoInfo) WithOnline

func (vi *VideoInfo) WithOnline(vo VideoOnline) *VideoInfo

WithOnline 为 VideoInfo 附加在线人数信息用于格式化

type VideoOnline

type VideoOnline struct {
	// 所有平台
	Total string `json:"total" mapstructure:"total"`
	// web端
	Count string `json:"count" mapstructure:"count"`

	ShowSwitch struct {
		Total bool `json:"total" mapstructure:"total"`
		Count bool `json:"count" mapstructure:"count"`
	} `json:"show_switch" mapstructure:"show_switch"`
	AbTest struct {
		Group string `json:"group" mapstructure:"group"`
	} `json:"abtest" mapstructure:"abtest"`
}

URL_VIDEO_ONLINE "data"

func FetchVideoOnline

func FetchVideoOnline(id, cid string) (vo VideoOnline, err error)

FetchVideoOnline 获取视频在线人数

id: avid/bvid
cid: 分 p 对应的 cid

func (VideoOnline) Ok

func (vo VideoOnline) Ok() bool

type VideoPlayurl

type VideoPlayurl struct {
	From              string   `json:"from" mapstructure:"from"`                             // "bili"
	Result            string   `json:"result" mapstructure:"result"`                         // "success"
	Message           string   `json:"message" mapstructure:"message"`                       // "ok"
	Quality           int      `json:"quality" mapstructure:"quality"`                       // 80
	Format            string   `json:"format" mapstructure:"format"`                         // "mp4"
	Timelength        int      `json:"timelength" mapstructure:"timelength"`                 // 0
	AcceptFormat      string   `json:"accept_format" mapstructure:"accept_format"`           // "mp4720,mp4"
	AcceptDescription []string `json:"accept_description" mapstructure:"accept_description"` // ["高清 720P", "流畅 360P"]
	AcceptQuality     []int    `json:"accept_quality" mapstructure:"accept_quality"`         // [64, 16]
	VideoCodecid      int      `json:"video_codecid" mapstructure:"video_codecid"`           // 7
	SeekParam         string   `json:"seek_param" mapstructure:"seek_param"`                 // "v"
	SeekType          string   `json:"seek_type" mapstructure:"seek_type"`                   // "play"

	Durl videoPlayurlDurl `json:"durl" mapstructure:"durl"` // mp4 流地址

	Dash *videoPlayurlDash `json:"dash" mapstructure:"dash"`

	SupportFormats []videoPlayurlSupportFormat `json:"support_formats" mapstructure:"support_formats"` // "support_formats" : {}

	// HighFormat *struct{} `json:"high_format" mapstructure:"high_format"`
	LastPlayTime int `json:"last_play_time" mapstructure:"last_play_time"` // (s)
	LastPlayCid  int `json:"last_play_cid" mapstructure:"last_play_cid"`
	// ViewInfo *struct{} `json:"view_info" mapstructure:"view_info"`
	PlayConf struct {
		IsNewDescription bool `json:"is_new_description" mapstructure:"is_new_description"` // 是否使用新描述
	}
}

"data"

func FetchVideoPlayurl

func FetchVideoPlayurl(id, cid string, fnval VideoFormat, qn ...VideoQuality) (vp VideoPlayurl, err error)

FetchVideoPlayurl 获取视频流地址, 不提供 cid 时默认获取 P1, 取 dash 流时不需要 qn, 取 mp4 流时不传 qn 获取的清晰度应该是 720p, 未经大量测试, 同时, B站引入 dash 后较新的视频 mp4 只有 720p 与 360p

type VideoQuality

type VideoQuality = int
const (
	VIDEO_QN_240      VideoQuality = 6
	VIDEO_QN_360      VideoQuality = 16
	VIDEO_QN_480      VideoQuality = 32
	VIDEO_QN_720      VideoQuality = 64
	VIDEO_QN_720P60   VideoQuality = 74
	VIDEO_QN_1080     VideoQuality = 80
	VIDEO_QN_1080PLUS VideoQuality = 112
	VIDEO_QN_1080P60  VideoQuality = 116
	VIDEO_QN_4K       VideoQuality = 120
	VIDEO_QN_HDR      VideoQuality = 125
	VIDEO_QN_DOLBY    VideoQuality = 126
	VIDEO_QN_8K       VideoQuality = 127
)

type VoteInfo

type VoteInfo struct {
	VoteId        int          `json:"vote_id" mapstructure:"vote_id"`
	Title         string       `json:"title" mapstructure:"title"`
	Desc          string       `json:"desc" mapstructure:"desc"`
	JoinNum       int          `json:"join_num" mapstructure:"join_num"`
	Type          int          `json:"type" mapstructure:"type"`
	ChoiceCnt     int          `json:"choice_cnt" mapstructure:"choice_cnt"` // 可选数
	EndTime       int          `json:"end_time" mapstructure:"end_time"`     // 结束时间 (s)
	Status        int          `json:"status" mapstructure:"status"`
	VotePublisher int          `json:"vote_publisher" mapstructure:"vote_publisher"` // 投票发起者uid
	DefaultShare  int          `json:"default_share" mapstructure:"default_share"`
	CTime         int          `json:"ctime" mapstructure:"ctime"` // 创建时间 (s)
	Options       []voteOption `json:"options" mapstructure:"options"`
	OptionsCnt    int          `json:"options_cnt" mapstructure:"options_cnt"` // 选项数
	VoteLevel     int          `json:"vote_level" mapstructure:"vote_level"`   // 投票发起者账号等级
	Face          string       `json:"face" mapstructure:"face"`               // 投票发起者头像url
	Name          string       `json:"name" mapstructure:"name"`               // 投票发起者昵称
}

"data.vote_info"

func FetchVoteInfo

func FetchVoteInfo(voteId string) (vi VoteInfo, err error)

FetchVoteInfo 获取投票信息

func (*VoteInfo) DoTemplate

func (vi *VoteInfo) DoTemplate() string

func (*VoteInfo) DoTemplateTo

func (vi *VoteInfo) DoTemplateTo(w io.Writer) error

type WbiKeys

type WbiKeys struct {
	Img   string
	Sub   string
	Mixin string
	// contains filtered or unexported fields
}

func WbiGet

func WbiGet() (wk WbiKeys, err error)

func (*WbiKeys) Sign

func (wk *WbiKeys) Sign(u *url.URL) (err error)

Sign 为链接签名

func (*WbiKeys) Update

func (wk *WbiKeys) Update() (err error)

Update 无视过期时间更新

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL