Skip to content

Commit

Permalink
Capture more live error situations: 封禁、轮播、大航海专属
Browse files Browse the repository at this point in the history
  • Loading branch information
xfangfang committed Nov 11, 2023
1 parent 1dccd6d commit a502697
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 36 deletions.
2 changes: 1 addition & 1 deletion library/borealis
Binary file added resources/pictures/room-block.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/pictures/sorry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions wiliwili/include/activity/live_player_activity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ class LiveActivity : public brls::Activity, public LiveDataRequest {

void onError(const std::string& error) override;

void onNeedPay(const std::string& msg, const std::string& link,
const std::string& startTime,
const std::string& endTime) override;

std::vector<std::string> getQualityDescriptionList();
int getCurrentQualityIndex();

Expand Down
27 changes: 20 additions & 7 deletions wiliwili/include/api/bilibili.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

namespace bilibili {

class LiveResultWrapper;
class LiveUrlResultWrapper;
class LiveRoomPlayInfo;
class LiveResultWrapper; // 直播推荐
class LiveUrlResultWrapper; // 直播链接V1
class LiveRoomPlayInfo; // 直播链接V2
class LivePayInfo; // 大航海专属直播信息
class LivePayLink; // 大航海专属直播付费链接
class LiveFullAreaResultWrapper; // 直播分区列表
class LiveSecondResultWrapper; // 直播二级分区推荐
class SearchResult;
Expand Down Expand Up @@ -131,7 +133,7 @@ class BilibiliClient {
// 稍后再看 watch later
static void getWatchLater(
const std::function<void(WatchLaterListWrapper)>& callback = nullptr,
const ErrorCallback& error = nullptr);
const ErrorCallback& error = nullptr);

/**
* 获取用户创建的收藏列表或用户订阅的合集
Expand Down Expand Up @@ -285,7 +287,7 @@ class BilibiliClient {
const ErrorCallback& error = nullptr);

/// get live video url by roomid
/// @deprecated 部分直播间可能无法获取到直播地址,但可以获取到长时间有效的直播地址
/// @deprecated 部分直播间无法获取到直播地址
static void get_live_url(
int roomid, int qn = 10000,
const std::function<void(LiveUrlResultWrapper)>& callback = nullptr,
Expand All @@ -294,7 +296,17 @@ class BilibiliClient {
static void get_live_room_play_info(
int roomid, int qn = 0,
const std::function<void(LiveRoomPlayInfo)>& callback = nullptr,
const ErrorCallback& error = nullptr);
const ErrorCallback& error = nullptr);

static void get_live_pay_info(
int roomid,
const std::function<void(LivePayInfo)>& callback = nullptr,
const ErrorCallback& error = nullptr);

static void get_live_pay_link(
int roomid,
const std::function<void(LivePayLink)>& callback = nullptr,
const ErrorCallback& error = nullptr);

/**
* 主页 推荐
Expand All @@ -308,7 +320,8 @@ class BilibiliClient {
* @param error
*/
static void get_recommend(
int index = 1, int num = 24, int fresh_type = 4, std::string feed_version = "V1", int x_num = 3, int y_num = 4,
int index = 1, int num = 24, int fresh_type = 4,
std::string feed_version = "V1", int x_num = 3, int y_num = 4,
const std::function<void(RecommendVideoListResultWrapper)>& callback =
nullptr,
const ErrorCallback& error = nullptr);
Expand Down
6 changes: 6 additions & 0 deletions wiliwili/include/api/bilibili/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ const std::string LiveUrl = _liveBase + "/room/v1/Room/playUrl";
/// 直播API V2
const std::string RoomPlayInfo =
_liveBase + "/xlive/web-room/v2/index/getRoomPlayInfo";
/// 是否为大航海专属直播
const std::string RoomPayInfo =
_liveBase + "/av/v1/PayLive/liveValidate";
/// 大航海直播的付费链接
const std::string RoomPayLink =
_liveBase + "/xlive/web-ucenter/v1/payPlay/getInfo";
/// 直播历史记录
const std::string LiveReport =
_liveBase + "/xlive/web-room/v1/index/roomEntryAction";
Expand Down
23 changes: 22 additions & 1 deletion wiliwili/include/api/bilibili/result/home_live_result.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,16 +95,37 @@ class LiveRoomPlayInfo {
int live_status;
size_t live_time;
LivePlayUrlInfo playurl_info;
bool is_locked; // 是否被封禁
int lock_till; // 封禁解锁时间
};
inline void from_json(const nlohmann::json& nlohmann_json_j,
LiveRoomPlayInfo& nlohmann_json_t) {
if (!nlohmann_json_j.at("playurl_info").is_null()) {
nlohmann_json_j.at("playurl_info").get_to(nlohmann_json_t.playurl_info);
}
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, room_id, uid,
live_status, live_time));
live_status, live_time, is_locked,
lock_till));
}

class LivePayInfo {
public:
int permission;
std::string pic;

std::string message; // 额外的提示信息
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(LivePayInfo, permission, pic);

class LivePayLink {
public:
std::string start_time;
std::string end_time;
std::string goods_link;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(LivePayLink, start_time, end_time,
goods_link);

class LiveAreaResult {
public:
LiveAreaResult() = default;
Expand Down
51 changes: 45 additions & 6 deletions wiliwili/include/presenter/live_data.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@ class LiveDataRequest : public Presenter {

virtual void onError(const std::string& error) {}

virtual void onNeedPay(const std::string& msg, const std::string& link,
const std::string& startTime,
const std::string& endTime) {}

void requestData(int roomid) {
ASYNC_RETAIN
BILI::get_live_room_play_info(
roomid, defaultQuality,
[ASYNC_TOKEN](const auto& result) {
ASYNC_RELEASE
liveRoomPlayInfo = result;
qualityDescriptionMap.clear();
for (auto& i :
Expand All @@ -47,7 +50,10 @@ class LiveDataRequest : public Presenter {
liveUrl = i;
break;
}
onLiveData(liveRoomPlayInfo);
brls::sync([ASYNC_TOKEN]() {
ASYNC_RELEASE
onLiveData(liveRoomPlayInfo);
});
},
[ASYNC_TOKEN](BILI_ERR) {
brls::sync([ASYNC_TOKEN, error]() {
Expand All @@ -69,7 +75,40 @@ class LiveDataRequest : public Presenter {
brls::Logger::debug("report live history {}", roomid);
},
[](BILI_ERR) {
brls::Logger::error("report live history:", error);
brls::Logger::error("report live history: {}", error);
});
}

void requestPayLiveInfo(int roomid) {
ASYNC_RETAIN
BILI::get_live_pay_info(
roomid,
[ASYNC_TOKEN, roomid](const auto& payInfo) {
brls::Logger::debug("get live pay info {}", payInfo.permission);
if (payInfo.permission != 0) return;
BILI::get_live_pay_link(
roomid,
[ASYNC_TOKEN, payInfo](const auto& payLink) {
brls::Logger::debug("get live pay link {}",
payLink.goods_link);
brls::sync([ASYNC_TOKEN, payInfo, payLink]() {
ASYNC_RELEASE
this->onNeedPay(payInfo.message, payLink.goods_link,
payLink.start_time,
payLink.end_time);
});
},
[ASYNC_TOKEN, payInfo](BILI_ERR) {
brls::Logger::error("get live pay link:", error);
brls::sync([ASYNC_TOKEN, payInfo]() {
ASYNC_RELEASE
this->onNeedPay(payInfo.message, "", "", "");
});
});
},
[ASYNC_TOKEN](BILI_ERR) {
ASYNC_RELEASE
brls::Logger::error("get live pay info: {}", error);
});
}

Expand All @@ -80,7 +119,7 @@ class LiveDataRequest : public Presenter {
}

static inline int defaultQuality = 0;
bilibili::LiveRoomPlayInfo liveRoomPlayInfo;
bilibili::LiveStreamFormatCodec liveUrl;
std::unordered_map<int, std::string> qualityDescriptionMap;
bilibili::LiveRoomPlayInfo liveRoomPlayInfo{};
bilibili::LiveStreamFormatCodec liveUrl{};
std::unordered_map<int, std::string> qualityDescriptionMap{};
};
103 changes: 96 additions & 7 deletions wiliwili/source/activity/live_player_activity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// Created by fang on 2022/8/4.
//

#include <borealis/core/thread.hpp>
#include <borealis/views/dialog.hpp>

#include "activity/live_player_activity.hpp"
#include "utils/number_helper.hpp"

Expand All @@ -12,6 +15,7 @@
#include "view/mpv_core.hpp"
#include "view/live_core.hpp"
#include "view/grid_dropdown.hpp"
#include "view/qr_image.hpp"

#include "utils/shader_helper.hpp"
#include "utils/config_helper.hpp"
Expand All @@ -20,10 +24,6 @@
#include "live/extract_messages.hpp"
#include "live/ws_utils.hpp"

#include "bilibili.h"

#include "borealis/core/thread.hpp"

using namespace brls::literals;

static void process_danmaku(const std::vector<LiveDanmakuItem>& danmaku_list) {
Expand Down Expand Up @@ -61,6 +61,36 @@ static void onDanmakuReceived(std::string&& message) {
process_danmaku(danmaku_list);
}

static void showDialog(const std::string& msg, const std::string& pic,
bool forceQuit) {
brls::Dialog* dialog;
if (pic.empty()) {
dialog = new brls::Dialog(msg);
} else {
auto box = new brls::Box();
auto img = new brls::Image();
auto label = new brls::Label();
label->setText(msg);
label->setHorizontalAlign(brls::HorizontalAlign::CENTER);
label->setMargins(20, 0, 10, 0);
img->setMaxHeight(400);
img->setImageFromRes(pic);
box->addView(img);
box->addView(label);
box->setAxis(brls::Axis::COLUMN);
box->setAlignItems(brls::AlignItems::CENTER);
box->setMargins(20, 20, 20, 20);
dialog = new brls::Dialog(box);
}

dialog->setCancelable(false);
dialog->addButton("hints/ok"_i18n, [forceQuit]() {
if (forceQuit) brls::sync([]() { brls::Application::popActivity(); });
});
dialog->open();
}


LiveActivity::LiveActivity(const bilibili::LiveVideoResult& live)
: liveData(live) {
brls::Logger::debug("LiveActivity: create: {}", live.roomid);
Expand Down Expand Up @@ -204,6 +234,9 @@ void LiveActivity::onContentAvailable() {

// 根据房间号重新获取高清播放链接
this->requestData(liveData.roomid);

// 获取直播间是否为大航海专属直播
this->requestPayLiveInfo(liveData.roomid);
}

std::vector<std::string> LiveActivity::getQualityDescriptionList() {
Expand All @@ -225,12 +258,25 @@ void LiveActivity::onLiveData(const bilibili::LiveRoomPlayInfo& result) {
// todo:定时获取在线人数
this->video->setOnlineCount(liveData.watched_show.text_large);

if (result.live_status != 1) {
if (result.is_locked) {
brls::Logger::error("LiveActivity: live {} is locked", result.room_id);
this->video->showOSD(false);
showDialog(
fmt::format("这个房间已经被封禁(至 {})!(╯°口°)╯(┴—┴",
wiliwili::sec2FullDate(result.lock_till)),
"pictures/room-block.png", true);
return;
}
// 0: 未开播 1: 直播中 2: 轮播中
if (result.live_status == 0) {
// 未开播
brls::Logger::error("LiveActivity: not live");
this->video->showOSD(false);
this->video->setStatusLabelLeft("未开播");
showDialog("未开播", "pictures/sorry.png", true);
return;
} else if (result.live_status == 2) {
// todo: 支持轮播视频
this->video->showOSD(false);
showDialog("未开播", "pictures/sorry.png", true);
}
brls::Logger::debug("current quality: {}", liveUrl.current_qn);
for (auto& i : liveUrl.accept_qn) {
Expand Down Expand Up @@ -259,6 +305,49 @@ void LiveActivity::onError(const std::string& error) {
this->retryRequestData();
}

void LiveActivity::onNeedPay(const std::string& msg, const std::string& link,
const std::string& startTime,
const std::string& endTime) {
if (link.empty()) {
showDialog(msg, "", true);
return;
}

auto box = new brls::Box();
auto img = new QRImage();
auto label = new brls::Label();
auto header = new brls::Label();
auto subtitle = new brls::Label();
header->setFontSize(24);
header->setMargins(10, 0, 20, 0);
header->setText(msg);
subtitle->setTextColor(brls::Application::getTheme().getColor("font/grey"));
subtitle->setText(startTime + " - " + endTime);
subtitle->setMarginBottom(10);
subtitle->setHorizontalAlign(brls::HorizontalAlign::CENTER);
header->setHorizontalAlign(brls::HorizontalAlign::CENTER);
label->setHorizontalAlign(brls::HorizontalAlign::CENTER);
label->setMargins(20, 0, 10, 0);
label->setText("请使用手机客户端扫码开通");
img->setHeight(240);
img->setWidth(240);
img->setImageFromQRContent(link);
box->setAxis(brls::Axis::COLUMN);
box->setAlignItems(brls::AlignItems::CENTER);
box->setMargins(20, 20, 20, 20);
box->addView(header);
box->addView(subtitle);
box->addView(img);
box->addView(label);
auto dialog = new brls::Dialog(box);

dialog->setCancelable(false);
dialog->addButton("hints/ok"_i18n, []() {
brls::sync([]() { brls::Application::popActivity(); });
});
dialog->open();
}

void LiveActivity::retryRequestData() {
// 每隔一段时间自动重试
brls::cancelDelay(errorDelayIter);
Expand Down
Loading

0 comments on commit a502697

Please sign in to comment.