Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

实现粉丝牌直播间点赞 && 修复一些 bug #383

Merged
merged 1 commit into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Live
{
public class LikeLiveRoomRequest
{
public LikeLiveRoomRequest(int roomid, string csrf)
{
Roomid = roomid;
Csrf= csrf;
}

public int Roomid { get; set; }

public string Csrf { get; set; }

public string Csrf_token => Csrf;
}
}
11 changes: 11 additions & 0 deletions src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,18 @@ public interface ILiveApi : IBiliBiliApi
[HttpGet("/room/v1/Room/get_info?room_id={roomId}&from=room")]
Task<BiliApiResponse<GetLiveRoomInfoResponse>> GetLiveRoomInfo(int roomId);

/// <summary>
/// 请求直播主页用于配置直播相关 Cookie
/// </summary>
[HttpGet("/news/v1/notice/recom?product=live")]
Task<HttpResponseMessage> GetLiveHome();

/// <summary>
/// 点赞直播间
/// </summary>
[HttpPost("/xlive/web-ucenter/v1/interact/likeInteract")]
[Header("Referer", "https://live.bilibili.com/")]
[Header("Origin", "https://live.bilibili.com")]
Task<BiliApiResponse> LikeLiveRoom([FormContent] LikeLiveRoomRequest request);
}
}
6 changes: 0 additions & 6 deletions src/Ray.BiliBiliTool.Agent/BiliCookie.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,6 @@ public override void Check()
result = false;
}

// LiveBuvid 为空时发出警告
if (string.IsNullOrWhiteSpace(LiveBuvid))
{
_logger.LogWarning("直播Cookie {cookie}未正确配置,将在执行相关任务时尝试自动获取", GetPropertyDescription(nameof(LiveBuvid)));
}

if (!result)
throw new Exception($"请正确配置Cookie后再运行,配置方式见 {Constants.SourceCodeUrl}");
}
Expand Down
3 changes: 2 additions & 1 deletion src/Ray.BiliBiliTool.Application/LiveFansMedalAppService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ IAccountDomainService accountDomainService
public override void DoTask()
{
_liveDomainService.SendDanmakuToFansMedalLive();
_liveDomainService.SendHeartBeatToFansMdealLive();
_liveDomainService.LikeFansMedalLive();
_liveDomainService.SendHeartBeatToFansMedalLive();
}

}
Expand Down
22 changes: 3 additions & 19 deletions src/Ray.BiliBiliTool.Application/LoginTaskAppService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
using Ray.BiliBiliTool.Application.Attributes;
using Ray.BiliBiliTool.Application.Contracts;
using Ray.BiliBiliTool.Infrastructure.Enums;
using Ray.BiliBiliTool.Infrastructure;
using Microsoft.Extensions.DependencyInjection;

namespace Ray.BiliBiliTool.Application
{
Expand All @@ -27,23 +29,20 @@ public class LoginTaskAppService : AppService, ILoginTaskAppService
private readonly IPassportApi _passportApi;
private readonly IHostEnvironment _hostingEnvironment;
private readonly IQingLongApi _qingLongApi;
private readonly ILiveApi _liveApi;
private readonly IConfiguration _configuration;

public LoginTaskAppService(
IConfiguration configuration,
ILogger<LoginTaskAppService> logger,
IPassportApi passportApi,
IHostEnvironment hostingEnvironment,
IQingLongApi qingLongApi,
ILiveApi liveApi)
IQingLongApi qingLongApi)
{
_configuration = configuration;
_logger = logger;
_passportApi = passportApi;
_hostingEnvironment = hostingEnvironment;
_qingLongApi = qingLongApi;
_liveApi = liveApi;
}

[TaskInterceptor("扫码登录", TaskLevel.One)]
Expand Down Expand Up @@ -120,21 +119,6 @@ protected bool QrCodeLogin(out BiliCookie cookieInfo)
_logger.LogInformation("扫描成功!");
IEnumerable<string> cookies = check.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value;

// 请求主播主页来正确配置 cookie
var liveHome = _liveApi.GetLiveHome().Result;
var liveHomeContent = JsonConvert.DeserializeObject<BiliApiResponse>(liveHome.Content.ReadAsStringAsync().Result);
if (liveHomeContent.Code == 0)
{
// 合并 cookie
IEnumerable<string> liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value;
cookies = cookies.Union(liveCookies);
}
else
{
_logger.LogWarning("获取直播 cookie 时出现错误");
_logger.LogWarning("{msg}", liveHomeContent.Message);
}

cookieInfo = GetCookie(cookies);
result = true;

Expand Down
28 changes: 28 additions & 0 deletions src/Ray.BiliBiliTool.DomainService/Dtos/FansMedalInfoDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Live;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Ray.BiliBiliTool.DomainService.Dtos
{
public class FansMedalInfoDto
{
public FansMedalInfoDto(int roomId, MedalWallDto medalInfo, GetLiveRoomInfoResponse liveRoomInfo)
{
this.RoomId = roomId;
this.MedalInfo = medalInfo;
this.LiveRoomInfo = liveRoomInfo;
}

// 直播间 id
public int RoomId { get; set; }

// 粉丝牌信息
public MedalWallDto MedalInfo { get; set; }

// 直播间信息
public GetLiveRoomInfoResponse LiveRoomInfo { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public interface ILiveDomainService : IDomainService
/// <summary>
/// 直播时长挂机
/// </summary>
void SendHeartBeatToFansMdealLive();
void SendHeartBeatToFansMedalLive();

/// <summary>
/// 点赞直播间
/// </summary>
void LikeFansMedalLive();
}
}
138 changes: 78 additions & 60 deletions src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -405,19 +405,10 @@ public void SendDanmakuToFansMedalLive()
{
if (!CheckLiveCookie()) return;

_logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表");
var result = this._liveApi.GetMedalWall(int.Parse(this._biliCookie.UserId)).Result;

if (result.Code != 0)
GetFansMedalInfoList().ForEach(info =>
{
_logger.LogError("【获取直播列表】失败");
_logger.LogError("【原因】{message}", result.Message);
return;
}
var medal = info.MedalInfo;

// 遍历粉丝牌
foreach (var medal in result.Data.List)
{
_logger.LogInformation("【直播间】{liveRoomName}", medal.Target_name);
_logger.LogInformation("【粉丝牌】{medalName}", medal.Medal_info.Medal_name);

Expand All @@ -430,7 +421,7 @@ public void SendDanmakuToFansMedalLive()
{
_logger.LogError("【获取直播间信息】失败");
_logger.LogError("【原因】{message}", spaceInfo.Message);
continue;
return;
}

// 发送弹幕
Expand All @@ -443,60 +434,19 @@ public void SendDanmakuToFansMedalLive()
{
_logger.LogError("【弹幕发送】失败");
_logger.LogError("【原因】{message}", sendResult.Message);
continue;
return;
}

_logger.LogInformation("【弹幕发送】成功~,你和主播 {name} 的亲密值增加了100!", spaceInfo.Data.Name);
}
}
});
}

public void SendHeartBeatToFansMdealLive()
public void SendHeartBeatToFansMedalLive()
{
if (!CheckLiveCookie()) return;

_logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表");
var medalWallInfo = this._liveApi.GetMedalWall(int.Parse(this._biliCookie.UserId)).Result;

if (medalWallInfo.Code != 0)
{
_logger.LogError("【获取直播列表】失败");
_logger.LogError("【原因】{message}", medalWallInfo.Message);
return;
}

var infoList = new List<HeartBeatIterationInfoDto>();
foreach (var medal in medalWallInfo.Data.List)
{
_logger.LogInformation("【主播】{name} ", medal.Target_name);
if (_liveFansMedalTaskOptions.IsSkipLevel20Medal && medal.Medal_info.Level >= 20)
{
_logger.LogInformation("粉丝牌等级为 {level},观看将不再增长亲密度,跳过", medal.Medal_info.Level);
continue;
}

// 通过空间主页信息获取直播间 id
int liveHostUserId = medal.Medal_info.Target_id;
var spaceInfo = _userInfoApi.GetSpaceInfo(liveHostUserId).Result;
if (spaceInfo.Code != 0)
{
_logger.LogError("【获取空间信息】失败");
_logger.LogError("【原因】{message}", spaceInfo.Message);
continue;
}

var roomId = spaceInfo.Data.Live_room.Roomid;

// 获取直播间详细信息
var liveRoomInfo = _liveApi.GetLiveRoomInfo(roomId).Result;
if (liveRoomInfo.Code != 0)
{
_logger.LogError("【获取直播间信息】失败");
_logger.LogError("【原因】{message}", liveRoomInfo.Message);
continue;
}

infoList.Add(new(roomId, liveRoomInfo.Data, new(), 0, 0));
}
GetFansMedalInfoList().ForEach((medal) => infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0)));

if (infoList.Count == 0)
{
Expand All @@ -519,9 +469,9 @@ public void SendHeartBeatToFansMdealLive()

string uuid = Guid.NewGuid().ToString();
var current = Now();
if (current - info.LastBeatTime <= LiveFansMedalTaskOptions.HeartBeatInterval * 1000)
if (current - info.LastBeatTime <= (LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000)
{
int sleepTime = (int)(LiveFansMedalTaskOptions.HeartBeatInterval * 1000 - (current - info.LastBeatTime));
int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 - (current - info.LastBeatTime));
_logger.LogDebug("【休眠】{time} 毫秒", sleepTime);
Thread.Sleep(sleepTime);
}
Expand Down Expand Up @@ -592,6 +542,74 @@ public void SendHeartBeatToFansMdealLive()
_logger.LogInformation("【直播观看时长】完成情况:{success}/{total} ", successCount, infoList.Count);
}

public void LikeFansMedalLive()
{
if (!CheckLiveCookie()) return;

GetFansMedalInfoList().ForEach(info =>
{
var result = _liveApi.LikeLiveRoom(new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct)).Result;
if (result.Code == 0)
{
_logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId);
}
else
{
_logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId);
_logger.LogError("【原因】{message}", result.Message);
}
});
}

private List<FansMedalInfoDto> GetFansMedalInfoList()
{
_logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表");
var medalWallInfo = this._liveApi.GetMedalWall(int.Parse(this._biliCookie.UserId)).Result;

if (medalWallInfo.Code != 0)
{
_logger.LogError("【获取直播列表】失败");
_logger.LogError("【原因】{message}", medalWallInfo.Message);
return null;
}

var infoList = new List<FansMedalInfoDto>();
foreach (var medal in medalWallInfo.Data.List)
{
_logger.LogInformation("【主播】{name} ", medal.Target_name);
if (_liveFansMedalTaskOptions.IsSkipLevel20Medal && medal.Medal_info.Level >= 20)
{
_logger.LogInformation("粉丝牌等级为 {level},观看将不再增长亲密度,跳过", medal.Medal_info.Level);
continue;
}

// 通过空间主页信息获取直播间 id
int liveHostUserId = medal.Medal_info.Target_id;
var spaceInfo = _userInfoApi.GetSpaceInfo(liveHostUserId).Result;
if (spaceInfo.Code != 0)
{
_logger.LogError("【获取空间信息】失败");
_logger.LogError("【原因】{message}", spaceInfo.Message);
continue;
}

var roomId = spaceInfo.Data.Live_room.Roomid;

// 获取直播间详细信息
var liveRoomInfo = _liveApi.GetLiveRoomInfo(roomId).Result;
if (liveRoomInfo.Code != 0)
{
_logger.LogError("【获取直播间信息】失败");
_logger.LogError("【原因】{message}", liveRoomInfo.Message);
continue;
}

infoList.Add(new FansMedalInfoDto(roomId, medal, liveRoomInfo.Data));
}

return infoList;
}

/// <summary>
/// 自动配置直播相关 Cookie,来兼容较低版本中保存的 Cookie 配置
/// </summary>
Expand Down