Skip to content

Commit

Permalink
### 2024年2月25日 -- 1.6.0
Browse files Browse the repository at this point in the history
+ 1.更新B站登录API,解决无法登录的问题。
+ 2.更新B站用户信息API,解决登陆后请求用户信息失败的问题。
  • Loading branch information
JelinYao committed Feb 25, 2024
1 parent b06133e commit beaeeb5
Show file tree
Hide file tree
Showing 16 changed files with 185 additions and 59 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ restclient: https://github.com/mrtazz/restclient-cpp
libjpeg-turbo: https://libjpeg-turbo.org/
sqlite: https://www.sqlite.org/index.html
## 更新记录
### 2024年2月25日 -- 1.6.0
+ 1.更新B站登录API,解决无法登录的问题。
+ 2.更新B站用户信息API,解决登陆后请求用户信息失败的问题。
### 2022年11月6日 -- 1.5.0
+ 1.引入开源库sqlite3、turbojpeg。
+ 2.支持写入mp3封面图片。
Expand Down
4 changes: 4 additions & 0 deletions include/utils/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <string>
#include <vector>
#include <algorithm>
#include <map>

using std::string;
using std::wstring;
using std::vector;
Expand Down Expand Up @@ -53,6 +55,8 @@ namespace string_utils {

std::string GetFileExtentionNameByUrl(const std::string& url);

std::map<std::wstring, std::wstring> CommandLineToArgMap(const wchar_t* command);

// 去掉Windows文件命名不能包含的特殊字符:\/:*?"<>|
template<class T>
T TrimFileName(T ch)
Expand Down
Binary file modified src/BVLoader/BVLoader.rc
Binary file not shown.
6 changes: 3 additions & 3 deletions src/BVLoader/BVLoader.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8f011e58-ee97-4a49-95b6-f6a33d4759c0}</ProjectGuid>
<RootNamespace>BVLoader</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<ProjectName>BVLoader</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
Expand Down
10 changes: 7 additions & 3 deletions src/BVLoader/define/api_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ constexpr const char* kUgcDetailApi = "https://api.bilibili.com/x/web-interface/
// UGC视频播放页查询接口
constexpr const char* kUgcPlayerApi = "https://api.bilibili.com/x/player/playurl?avid=%I64d&cid=%I64d&qn=%d&fourk=1";
// 请求二维码链接
static constexpr const char* kRequestLoginUrl = "https://passport.bilibili.com/qrcode/getLoginUrl";
// static constexpr const char* kRequestLoginUrl = "https://passport.bilibili.com/qrcode/getLoginUrl";
// 新版本
static constexpr const char* kRequestLoginUrl = "https://passport.bilibili.com/x/passport-login/web/qrcode/generate?source=main-fe-header";
// 请求登录结果
static constexpr const char* kRequestLoginInfo = "https://passport.bilibili.com/qrcode/getLoginInfo";
// static constexpr const char* kRequestLoginInfo = "https://passport.bilibili.com/qrcode/getLoginInfo";
// 新版本
static constexpr const char* kRequestLoginInfo = "https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=";
// 获取用户信息
static constexpr const char* kRequestUserInfo = "https://api.bilibili.com/nav";
static constexpr const char* kRequestUserInfo = "https://api.bilibili.com/x/web-interface/nav";
3 changes: 3 additions & 0 deletions src/BVLoader/define/message_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ enum ShowwndWparam {
enum {
WM_QRCODEWND_ASYNC_SUCCESS = kBaseWindowMessage + 1,
WM_QRCODEWND_ASYNC_ERROR,

WM_QRCODEWND_GET_QRCODE,
WM_QRCODEWND_GET_LOGIN_RESULT,
};

// qrcode window timer
Expand Down
1 change: 1 addition & 0 deletions src/BVLoader/define/soft_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ static constexpr const char* kAppNameAscii = "DownloadTools";
// qrcode login
static constexpr const wchar_t* kTextQrcodeExpired = L"二维码已过期";
static constexpr const wchar_t* kTextQrcodeRequestFailed = L"二维码请求失败";
static constexpr const wchar_t* kTextQrcodeResultParseFailed = L"二维码扫码结果解析失败";
static constexpr const wchar_t* kTextQrcodeConfirmed = L"扫描成功,请在手机上确认";

static constexpr const wchar_t* kDefaultCover = L"cover.png";
1 change: 1 addition & 0 deletions src/BVLoader/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
LOG(INFO) << "Process is already running, exit";
return 0;
}

CPaintManagerUI::SetInstance(hInstance);
#ifdef _DEBUG
CDuiString wstrResoucePath = CPaintManagerUI::GetInstancePath();
Expand Down
74 changes: 41 additions & 33 deletions src/BVLoader/service/async/async_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,12 @@ void AsyncService::OnGetLoginUrl(const std::shared_ptr<IAsyncTask>& task)
return;
}
// 数据解析
bool result = ParseLoginUrl(task, response);
if (!result && !IsDelegateEmpty()) {
NotifyDelegate(task->task_type, AsyncErrorCode::ERROR_PARSE_RESPONSE, nullptr);
QrcodeUrlInfo* info = new QrcodeUrlInfo();
bool result = ParseLoginUrl(task, response, info);
// 解析完毕,回调通知界面
if (!IsDelegateEmpty()) {
auto code = result ? AsyncErrorCode::ERROR_SUCCESS : AsyncErrorCode::ERROR_PARSE_RESPONSE;
NotifyDelegate(task->task_type, code, info);
}
}

Expand All @@ -276,9 +279,9 @@ void AsyncService::OnGetLoginInfo(const std::shared_ptr<IAsyncTask>& task)
}
RestClient::Connection http;
InitHttp(http);
std_str param("oauthKey=");
param += login_task->auth_key;
auto response = http.post(login_task->url, param);
std::string url = login_task->url +
login_task->auth_key + "&source=main-fe-header";
auto response = http.get(url);
if (response.curl_code != CURLE_OK) {
LOG(ERROR) << "DoHttpRequest network error, code: " << response.curl_code;
if (!IsDelegateEmpty()) {
Expand All @@ -287,9 +290,12 @@ void AsyncService::OnGetLoginInfo(const std::shared_ptr<IAsyncTask>& task)
return;
}
// 数据解析
bool result = ParseLoginInfo(task, response.body);
if (!result && !IsDelegateEmpty()) {
NotifyDelegate(login_task->task_type, AsyncErrorCode::ERROR_PARSE_RESPONSE, nullptr);
QrcodeLoginInfo* info = new QrcodeLoginInfo();
bool result = ParseLoginInfo(task, response.body, info);
// 解析完毕,回调通知界面
if (!IsDelegateEmpty()) {
auto code = result ? AsyncErrorCode::ERROR_SUCCESS : AsyncErrorCode::ERROR_PARSE_RESPONSE;
NotifyDelegate(task->task_type, code, info);
}
}

Expand Down Expand Up @@ -430,9 +436,11 @@ bool AsyncService::ParseUgcPlayerUrl(const std::shared_ptr<IAsyncTask>& task, st
return false;
}

bool AsyncService::ParseLoginUrl(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response)
bool AsyncService::ParseLoginUrl(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response, QrcodeUrlInfo* info)
{
// {"code":0,"message":"0","ttl":1,"data":{"url":"https://passport.bilibili.com/h5-app/passport/login/scan?navhide=1\u0026qrcode_key=8a7373d74db2c69108e6de6fc5bdf491\u0026from=main-fe-header","qrcode_key":"8a7373d74db2c69108e6de6fc5bdf491"}}
try {
assert(info);
Json::Value root;
Json::CharReaderBuilder builder;
std::shared_ptr<Json::CharReader> rd(builder.newCharReader());
Expand All @@ -447,23 +455,24 @@ bool AsyncService::ParseLoginUrl(const std::shared_ptr<IAsyncTask>& task, std_cs
return false;
}
auto& data = root[kHttpResponseData];
auto url = data["url"].asString();
auto auth_key = data["oauthKey"].asString();
// 解析完毕,回调通知界面
if (!IsDelegateEmpty()) {
QrcodeUrlInfo* userData = new QrcodeUrlInfo(std::move(url), std::move(auth_key));
NotifyDelegate(task->task_type, AsyncErrorCode::ERROR_SUCCESS, userData);
}
info->url = data["url"].asString();
info->auth_key = data["qrcode_key"].asString();
return true;
}
catch (...) {
LOG(ERROR) << "ParseLoginUrl parse json failed";
}
return false;
}

bool AsyncService::ParseLoginInfo(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response)
bool AsyncService::ParseLoginInfo(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response,
QrcodeLoginInfo* info)
{
try {
assert(info);
// {"code":20000,"message":"该版本已不支持当前功能,请升级新版本!"}
// {"code":0,"message":"0","ttl":1,"data":{"url":"","refresh_token":"","timestamp":0,"code":86038,"message":"二维码已失效"}}

Json::Value root;
Json::CharReaderBuilder builder;
std::shared_ptr<Json::CharReader> rd(builder.newCharReader());
Expand All @@ -473,15 +482,19 @@ bool AsyncService::ParseLoginInfo(const std::shared_ptr<IAsyncTask>& task, std_c
return false;
}
auto& data = root[kHttpResponseData];
int code = 0;
std_str url;
std_str cookie;
if (data.isInt()) {
code = data.asInt();
if (!data.isObject()) {
LOG(ERROR) << "接口返回数据出错:" << string_utils::Utf8ToA(response);
return false;
}
else {
// 登陆成功,解析用户信息
url = data["url"].asString();

info->url = data["url"].asString();
info->code = data["code"].asInt();
info->msg = data["message"].asString();

std_str url;
// 登陆成功,解析用户信息
url = data["url"].asString();
if (!url.empty()) {
size_t pos = url.find('?');
if (pos != std::string::npos) {
url = url.substr(pos + 1);
Expand All @@ -490,17 +503,12 @@ bool AsyncService::ParseLoginInfo(const std::shared_ptr<IAsyncTask>& task, std_c
string_utils::SplitStringA(url, "&", param_list);
size_t count = param_list.size();
for (size_t i = 0; i < count; ++i) {
cookie += param_list[i];
info->cookie += param_list[i];
if (i != count - 1) {
cookie.append("; ");
info->cookie.append("; ");
}
}
}
// 解析完毕,回调通知界面
if (!IsDelegateEmpty()) {
QrcodeLoginInfo* login_info = new QrcodeLoginInfo(code, std::move(url), std::move(cookie));
NotifyDelegate(task->task_type, AsyncErrorCode::ERROR_SUCCESS, login_info);
}
return true;
}
catch (...) {
Expand Down
6 changes: 4 additions & 2 deletions src/BVLoader/service/async/async_service.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,10 @@ class AsyncService
// Êý¾Ý½âÎö
bool ParseUgcInfo(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response);
bool ParseUgcPlayerUrl(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response);
bool ParseLoginUrl(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response);
bool ParseLoginInfo(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response);
bool ParseLoginUrl(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response,
QrcodeUrlInfo* info);
bool ParseLoginInfo(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response,
QrcodeLoginInfo* info);
bool ParseUserInfo(const std::shared_ptr<IAsyncTask>& task, std_cstr_ref response);

void NotifyDelegate(AsyncTaskType task_type, AsyncErrorCode code, void* data);
Expand Down
5 changes: 5 additions & 0 deletions src/BVLoader/service/async/async_service_define.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class PlayerInfo {
// 登录二维码url信息
class QrcodeUrlInfo {
public:
QrcodeUrlInfo() = default;

QrcodeUrlInfo(std_str_r_ref _url, std_str_r_ref _key)
: url(std::move(_url))
, auth_key(std::move(_key)) {
Expand All @@ -97,6 +99,8 @@ class QrcodeUrlInfo {
// 登录状态信息
class QrcodeLoginInfo {
public:
QrcodeLoginInfo() = default;

QrcodeLoginInfo(int _code, std_str_r_ref _url, std_str_r_ref _cookie)
: code(_code)
, url(std::move(_url))
Expand All @@ -106,6 +110,7 @@ class QrcodeLoginInfo {
int code = 0;
std_str url;
std_str cookie;
std_str msg;
};

// 用户信息
Expand Down
86 changes: 81 additions & 5 deletions src/BVLoader/wnd/wnd_login.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ LRESULT WndLogin::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
return OnMsgAsyncSuccess(wParam, lParam);
case WM_QRCODEWND_ASYNC_ERROR:
return OnMsgAsyncError(wParam, lParam);
case WM_QRCODEWND_GET_QRCODE:
return OnMsgGetQrcode(wParam, lParam);
case WM_QRCODEWND_GET_LOGIN_RESULT:
return OnMsgGetLoginResult(wParam, lParam);
default:
break;
}
Expand Down Expand Up @@ -104,12 +108,26 @@ void WndLogin::RefreshQrcode()

void WndLogin::OnAsyncComplete(AsyncTaskType task_type, AsyncErrorCode code, void* data, void* param)
{
if (task_type == AsyncTaskType::TASK_GET_LOGIN_URL
|| task_type == AsyncTaskType::TASK_GET_LOGIN_INFO) {
// 往UI线程转发
UINT msg = (code == AsyncErrorCode::ERROR_SUCCESS) ? WM_QRCODEWND_ASYNC_SUCCESS : WM_QRCODEWND_ASYNC_ERROR;
::PostMessage(m_hWnd, msg, (WPARAM)task_type, (LPARAM)data);
// 往UI线程转发
switch (task_type) {
case AsyncTaskType::TASK_GET_LOGIN_URL: {
::PostMessage(m_hWnd, WM_QRCODEWND_GET_QRCODE, (WPARAM)code, (LPARAM)data);
break;
}
case AsyncTaskType::TASK_GET_LOGIN_INFO: {
::PostMessage(m_hWnd, WM_QRCODEWND_GET_LOGIN_RESULT, (WPARAM)code, (LPARAM)data);
break;
}
default:
break;
}

//if (task_type == AsyncTaskType::TASK_GET_LOGIN_URL
// || task_type == AsyncTaskType::TASK_GET_LOGIN_INFO) {
// // 往UI线程转发
// UINT msg = (code == AsyncErrorCode::ERROR_SUCCESS) ? WM_QRCODEWND_ASYNC_SUCCESS : WM_QRCODEWND_ASYNC_ERROR;
// ::PostMessage(m_hWnd, msg, (WPARAM)task_type, (LPARAM)data);
//}
}

LRESULT WndLogin::OnMsgAsyncSuccess(WPARAM wParam, LPARAM lParam)
Expand Down Expand Up @@ -181,3 +199,61 @@ LRESULT WndLogin::OnMsgAsyncError(WPARAM wParam, LPARAM lParam)
}
return 0;
}

LRESULT WndLogin::OnMsgGetQrcode(WPARAM wParam, LPARAM lParam)
{
AsyncErrorCode code = (AsyncErrorCode)wParam;
auto info = reinterpret_cast<QrcodeUrlInfo*>(lParam);
assert(info);
std::unique_ptr<QrcodeUrlInfo> auto_ptr(info);
if (code == AsyncErrorCode::ERROR_SUCCESS) {
// 获取登录二维码成功
qrcode_view_->SetQrcodeUrl(std::move(info->url));
auth_key_ = std::move(info->auth_key);
// 开启定时器
StartLoginTimer();
}
else {
qrcode_view_->ShowExpire(kTextQrcodeRequestFailed);
}
return 0;
}

LRESULT WndLogin::OnMsgGetLoginResult(WPARAM wParam, LPARAM lParam)
{
AsyncErrorCode code = (AsyncErrorCode)wParam;
auto info = reinterpret_cast<QrcodeLoginInfo*>(lParam);
assert(info);
std::unique_ptr<QrcodeLoginInfo> auto_ptr(info);
if (code == AsyncErrorCode::ERROR_SUCCESS) {
// 成功
switch (info->code)
{
case 0: {
// 登陆成功
std_str* cookie = new std_str(std::move(info->cookie));
::PostMessage(main_wnd_, WM_MAINWND_LOGIN_SUCCESS, 0, (LPARAM)cookie);
Close();
break;
}
case 86038: // 二维码已失效
qrcode_view_->ShowExpire(kTextQrcodeExpired);
break;
case 86101: // 未扫码
StartLoginTimer();
break;
case 86090: // 二维码已扫码未确认
qrcode_view_->ShowExpire(kTextQrcodeConfirmed);
StartLoginTimer();
break;
default:
break;
}
}
else {
// 失败
qrcode_view_->ShowExpire(kTextQrcodeResultParseFailed);
}

return 0;
}
3 changes: 3 additions & 0 deletions src/BVLoader/wnd/wnd_login.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ class WndLogin
LRESULT OnMsgAsyncSuccess(WPARAM wParam, LPARAM lParam);
LRESULT OnMsgAsyncError(WPARAM wParam, LPARAM lParam);

LRESULT OnMsgGetQrcode(WPARAM wParam, LPARAM lParam);
LRESULT OnMsgGetLoginResult(WPARAM wParam, LPARAM lParam);

private:
QrcodeView* qrcode_view_ = nullptr;
std_str auth_key_;
Expand Down
Loading

0 comments on commit beaeeb5

Please sign in to comment.