diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4d118ecca..cc29e47c1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,5 @@
+## 2.1.3
+- Code refactory
## 2.1.2
- Feature: enhancement CICD scripts
- Fix[#728]: compatible with qinglong history versions
diff --git a/common.props b/common.props
index 34810691c..e3a3f38b0 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
Ray
- 2.1.2
+ 2.1.3
$(NoWarn);CS1591;CS0436
diff --git a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs
index 704e93d89..93e438fff 100644
--- a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs
+++ b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs
@@ -15,683 +15,684 @@
using Ray.BiliBiliTool.Config.Options;
using Ray.BiliBiliTool.DomainService.Dtos;
using Ray.BiliBiliTool.DomainService.Interfaces;
-using Ray.BiliBiliTool.Infrastructure.Cookie;
-namespace Ray.BiliBiliTool.DomainService
+namespace Ray.BiliBiliTool.DomainService;
+
+///
+/// 直播
+///
+public class LiveDomainService : ILiveDomainService
{
+ private readonly ILogger _logger;
+ private readonly ILiveApi _liveApi;
+ private readonly IRelationApi _relationApi;
+ private readonly ILiveTraceApi _liveTraceApi;
+ private readonly IUserInfoApi _userInfoApi;
+ private readonly LiveLotteryTaskOptions _liveLotteryTaskOptions;
+ private readonly LiveFansMedalTaskOptions _liveFansMedalTaskOptions;
+ private readonly DailyTaskOptions _dailyTaskOptions;
+ private readonly SecurityOptions _securityOptions;
+ private readonly BiliCookie _biliCookie;
+ private readonly IWbiService _wbiService;
+
+ public LiveDomainService(ILogger logger,
+ ILiveApi liveApi,
+ IRelationApi relationApi,
+ ILiveTraceApi liveTraceApi,
+ IUserInfoApi userInfoApi,
+ IOptionsMonitor dailyTaskOptions,
+ IOptionsMonitor liveLotteryTaskOptions,
+ IOptionsMonitor liveFansMedalTaskOptions,
+ IOptionsMonitor securityOptions,
+ IWbiService wbiService,
+ BiliCookie biliCookie)
+ {
+ _logger = logger;
+ _liveApi = liveApi;
+ _relationApi = relationApi;
+ _liveTraceApi = liveTraceApi;
+ _userInfoApi = userInfoApi;
+ _liveLotteryTaskOptions = liveLotteryTaskOptions.CurrentValue;
+ _dailyTaskOptions = dailyTaskOptions.CurrentValue;
+ _liveFansMedalTaskOptions = liveFansMedalTaskOptions.CurrentValue;
+ _securityOptions = securityOptions.CurrentValue;
+ _wbiService = wbiService;
+ _biliCookie = biliCookie;
+ }
+
///
- /// 直播
+ /// 本次通过天选关注的主播
///
- public class LiveDomainService : ILiveDomainService
- {
- private readonly ILogger _logger;
- private readonly ILiveApi _liveApi;
- private readonly IRelationApi _relationApi;
- private readonly ILiveTraceApi _liveTraceApi;
- private readonly IUserInfoApi _userInfoApi;
- private readonly LiveLotteryTaskOptions _liveLotteryTaskOptions;
- private readonly LiveFansMedalTaskOptions _liveFansMedalTaskOptions;
- private readonly DailyTaskOptions _dailyTaskOptions;
- private readonly SecurityOptions _securityOptions;
- private readonly BiliCookie _biliCookie;
- private readonly IWbiService _wbiService;
-
- public LiveDomainService(ILogger logger,
- ILiveApi liveApi,
- IRelationApi relationApi,
- ILiveTraceApi liveTraceApi,
- IUserInfoApi userInfoApi,
- IOptionsMonitor dailyTaskOptions,
- IOptionsMonitor liveLotteryTaskOptions,
- IOptionsMonitor liveFansMedalTaskOptions,
- IOptionsMonitor securityOptions,
- IWbiService wbiService,
- BiliCookie biliCookie)
- {
- _logger = logger;
- _liveApi = liveApi;
- _relationApi = relationApi;
- _liveTraceApi = liveTraceApi;
- _userInfoApi = userInfoApi;
- _liveLotteryTaskOptions = liveLotteryTaskOptions.CurrentValue;
- _dailyTaskOptions = dailyTaskOptions.CurrentValue;
- _liveFansMedalTaskOptions = liveFansMedalTaskOptions.CurrentValue;
- _securityOptions = securityOptions.CurrentValue;
- _wbiService = wbiService;
- _biliCookie = biliCookie;
- }
+ private List _tianXuanFollowed = new();
- ///
- /// 本次通过天选关注的主播
- ///
- private List _tianXuanFollowed = new();
+ ///
+ /// 开始抽奖前最后一个关注的up
+ ///
+ private long _lastFollowUpId;
- ///
- /// 开始抽奖前最后一个关注的up
- ///
- private long _lastFollowUpId;
+ ///
+ /// 直播签到
+ ///
+ public async Task LiveSign()
+ {
+ var response = await _liveApi.Sign();
- ///
- /// 直播签到
- ///
- public async Task LiveSign()
+ if (response.Code == 0)
{
- var response = await _liveApi.Sign();
-
- if (response.Code == 0)
- {
- _logger.LogInformation("【签到结果】成功");
- _logger.LogInformation("【本次获取】{text},{special}", response.Data.Text, response.Data.SpecialText);
- }
- else
- {
- _logger.LogInformation("【签到结果】失败");
- _logger.LogInformation("【原因】{msg}", response.Message);
- }
+ _logger.LogInformation("【签到结果】成功");
+ _logger.LogInformation("【本次获取】{text},{special}", response.Data.Text, response.Data.SpecialText);
}
-
- ///
- /// 直播中心银瓜子兑换B币
- ///
- /// 兑换银瓜子后硬币余额
- public async Task ExchangeSilver2Coin()
+ else
{
- var result = false;
+ _logger.LogInformation("【签到结果】失败");
+ _logger.LogInformation("【原因】{msg}", response.Message);
+ }
+ }
- if (_dailyTaskOptions.DayOfExchangeSilver2Coin == 0)
- {
- _logger.LogInformation("已配置为关闭,跳过");
- return false;
- }
+ ///
+ /// 直播中心银瓜子兑换B币
+ ///
+ /// 兑换银瓜子后硬币余额
+ public async Task ExchangeSilver2Coin()
+ {
+ var result = false;
- int targetDay = _dailyTaskOptions.DayOfExchangeSilver2Coin == -2
- ? DateTime.Today.Day
- : _dailyTaskOptions.DayOfExchangeSilver2Coin == -1
- ? DateTime.Today.LastDayOfMonth().Day
- : _dailyTaskOptions.DayOfExchangeSilver2Coin;
+ if (_dailyTaskOptions.DayOfExchangeSilver2Coin == 0)
+ {
+ _logger.LogInformation("已配置为关闭,跳过");
+ return false;
+ }
- _logger.LogInformation("【目标兑换日期】{targetDay}号", targetDay);
- _logger.LogInformation("【今天】{day}号", DateTime.Today.Day);
+ int targetDay = _dailyTaskOptions.DayOfExchangeSilver2Coin == -2
+ ? DateTime.Today.Day
+ : _dailyTaskOptions.DayOfExchangeSilver2Coin == -1
+ ? DateTime.Today.LastDayOfMonth().Day
+ : _dailyTaskOptions.DayOfExchangeSilver2Coin;
- if (DateTime.Today.Day != targetDay)
- {
- _logger.LogInformation("跳过");
- return false;
- }
+ _logger.LogInformation("【目标兑换日期】{targetDay}号", targetDay);
+ _logger.LogInformation("【今天】{day}号", DateTime.Today.Day);
- BiliApiResponse queryStatus = await _liveApi.GetLiveWalletStatus();
- _logger.LogInformation("【银瓜子余额】 {silver}", queryStatus.Data.Silver);
- _logger.LogInformation("【硬币余额】 {coin}", queryStatus.Data.Coin);
- _logger.LogInformation("【今日剩余兑换次数】 {left}", queryStatus.Data.Silver_2_coin_left);
+ if (DateTime.Today.Day != targetDay)
+ {
+ _logger.LogInformation("跳过");
+ return false;
+ }
- if (queryStatus.Data.Silver_2_coin_left <= 0) return false;
+ BiliApiResponse queryStatus = await _liveApi.GetLiveWalletStatus();
+ _logger.LogInformation("【银瓜子余额】 {silver}", queryStatus.Data.Silver);
+ _logger.LogInformation("【硬币余额】 {coin}", queryStatus.Data.Coin);
+ _logger.LogInformation("【今日剩余兑换次数】 {left}", queryStatus.Data.Silver_2_coin_left);
- _logger.LogInformation("开始尝试兑换...");
- Silver2CoinRequest request = new(_biliCookie.BiliJct);
- var response = await _liveApi.Silver2Coin(request);
- if (response.Code == 0)
- {
- result = true;
- _logger.LogInformation("【兑换结果】成功兑换 {coin} 枚硬币", response.Data.Coin);
- _logger.LogInformation("【银瓜子余额】 {silver}", response.Data.Silver);
- }
- else
- {
- _logger.LogInformation("【兑换结果】失败");
- _logger.LogInformation("【原因】{reason}", response.Message);
- }
+ if (queryStatus.Data.Silver_2_coin_left <= 0) return false;
- return result;
+ _logger.LogInformation("开始尝试兑换...");
+ Silver2CoinRequest request = new(_biliCookie.BiliJct);
+ var response = await _liveApi.Silver2Coin(request);
+ if (response.Code == 0)
+ {
+ result = true;
+ _logger.LogInformation("【兑换结果】成功兑换 {coin} 枚硬币", response.Data.Coin);
+ _logger.LogInformation("【银瓜子余额】 {silver}", response.Data.Silver);
}
-
- #region 天选时刻抽奖
-
- ///
- /// 天选抽奖
- ///
- public async Task TianXuan()
+ else
{
- _tianXuanFollowed = new List();
-
- if (_liveLotteryTaskOptions.AutoGroupFollowings)
- {
- //获取此时最后一个关注的up,此后再新增的关注,与参与成功的抽奖,取交集,就是本地新增的天选关注
- _lastFollowUpId = await GetLastFollowUpId();
- }
-
- //获取直播的分区
- List areaList = (await _liveApi.GetAreaList()).Data.Data;
+ _logger.LogInformation("【兑换结果】失败");
+ _logger.LogInformation("【原因】{reason}", response.Message);
+ }
- //遍历分区
- int count = 0;
- foreach (var area in areaList)
- {
- _logger.LogInformation("【扫描分区】{area}...{newLine}", area.Name, Environment.NewLine);
+ return result;
+ }
- string defaultSort = "";
- //每个分区下搜索5页
- for (int i = 1; i < 6; i++)
- {
- var reData = (await _liveApi.GetList(area.Id, i, sortType: defaultSort)).Data;
- foreach (var item in reData.List ?? new List())
- {
- if (item.Pendant_info == null || item.Pendant_info.Count == 0) continue;
- var suc = item.Pendant_info.TryGetValue("2", out var pendant);
- if (!suc) continue;
- if (pendant.Pendent_id != 504) continue;
- count++;
-
- await TryJoinTianXuan(item);
- }
-
- if (reData.Has_more != 1) break;
- defaultSort = reData.New_tags.FirstOrDefault()?.Sort_type ?? "";
- }
+ #region 天选时刻抽奖
- defaultSort = "";
- }
+ ///
+ /// 天选抽奖
+ ///
+ public async Task TianXuan()
+ {
+ _tianXuanFollowed = new List();
- if (count == 0)
- {
- _logger.LogInformation("未搜索到直播间");
- return;
- }
+ if (_liveLotteryTaskOptions.AutoGroupFollowings)
+ {
+ //获取此时最后一个关注的up,此后再新增的关注,与参与成功的抽奖,取交集,就是本地新增的天选关注
+ _lastFollowUpId = await GetLastFollowUpId();
}
- public async Task TryJoinTianXuan(ListItemDto target)
- {
- _logger.LogDebug("【房间】{name}", target.Title);
- try
- {
- //黑名单
- if (_liveLotteryTaskOptions.DenyUidList.Contains(target.Uid.ToString()))
- {
- _logger.LogDebug("黑名单,跳过");
- return;
- }
+ //获取直播的分区
+ List areaList = (await _liveApi.GetAreaList()).Data.Data;
- CheckTianXuanDto check = (await _liveApi.CheckTianXuan(target.Roomid)).Data;
+ //遍历分区
+ int count = 0;
+ foreach (var area in areaList)
+ {
+ _logger.LogInformation("【扫描分区】{area}...{newLine}", area.Name, Environment.NewLine);
- if (check == null)
+ string defaultSort = "";
+ //每个分区下搜索5页
+ for (int i = 1; i < 6; i++)
+ {
+ var reData = (await _liveApi.GetList(area.Id, i, sortType: defaultSort)).Data;
+ foreach (var item in reData.List ?? new List())
{
- _logger.LogDebug("数据异常,跳过");
- return;
- }
+ if (item.Pendant_info == null || item.Pendant_info.Count == 0) continue;
+ var suc = item.Pendant_info.TryGetValue("2", out var pendant);
+ if (!suc) continue;
+ if (pendant.Pendent_id != 504) continue;
+ count++;
- if (check.Status != TianXuanStatus.Enable)
- {
- _logger.LogDebug("已开奖,跳过{newLine}", Environment.NewLine);
- return;
+ await TryJoinTianXuan(item);
}
- //根据配置过滤
- if (!check.AwardNameIsSatisfied(_liveLotteryTaskOptions.IncludeAwardNameList,
- _liveLotteryTaskOptions.ExcludeAwardNameList))
- {
- _logger.LogDebug("不满足配置的筛选条件,跳过{newLine}", Environment.NewLine);
- return;
- }
+ if (reData.Has_more != 1) break;
+ defaultSort = reData.New_tags.FirstOrDefault()?.Sort_type ?? "";
+ }
- //是否需要赠礼
- if (check.Gift_price > 0)
- {
- _logger.LogDebug("【赠礼】{gift}", check.GiftDesc);
- _logger.LogDebug("需赠送礼物,跳过{newLine}", Environment.NewLine);
- return;
- }
+ defaultSort = "";
+ }
- //条件
- if (check.Require_type != RequireType.None && check.Require_type != RequireType.Follow)
- {
- _logger.LogDebug("【条件】{text}", check.Require_text);
- _logger.LogDebug("要求粉丝勋章,跳过");
- return;
- }
+ if (count == 0)
+ {
+ _logger.LogInformation("未搜索到直播间");
+ return;
+ }
+ }
- _logger.LogInformation("【房间】{name}", target.ShortTitle);
- _logger.LogInformation("【主播】{name}({id})", target.Uname, target.Uid);
- _logger.LogInformation("【奖品】{name}【条件】{text}", check.Award_name, check.Require_text);
+ public async Task TryJoinTianXuan(ListItemDto target)
+ {
+ _logger.LogDebug("【房间】{name}", target.Title);
+ try
+ {
+ //黑名单
+ if (_liveLotteryTaskOptions.DenyUidList.Contains(target.Uid.ToString()))
+ {
+ _logger.LogDebug("黑名单,跳过");
+ return;
+ }
- var request = new JoinTianXuanRequest
- {
- Id = check.Id, Gift_id = check.Gift_id, Gift_num = check.Gift_num, Csrf = _biliCookie.BiliJct
- };
- var re = await _liveApi.Join(request);
- if (re.Code == 0)
- {
- _logger.LogInformation("【抽奖】成功 √{newLine}", Environment.NewLine);
- if (check.Require_type == RequireType.Follow)
- _tianXuanFollowed.AddIfNotExist(target, x => x.Uid == target.Uid);
- return;
- }
+ CheckTianXuanDto check = (await _liveApi.CheckTianXuan(target.Roomid)).Data;
- _logger.LogInformation("【抽奖】失败");
- _logger.LogInformation("【原因】{msg}{newLine}", re.Message, Environment.NewLine);
- }
- catch (Exception ex)
+ if (check == null)
{
- _logger.LogWarning("【异常】{msg},{detail}{newLine}", ex.Message, ex, Environment.NewLine);
- //ignore
+ _logger.LogDebug("数据异常,跳过");
+ return;
}
- }
- ///
- /// 将本次抽奖新增的关注统一转移到指定分组中
- ///
- public async Task GroupFollowing()
- {
- if (!_tianXuanFollowed.Any())
+ if (check.Status != TianXuanStatus.Enable)
{
- _logger.LogInformation("未关注主播");
+ _logger.LogDebug("已开奖,跳过{newLine}", Environment.NewLine);
return;
}
- _logger.LogInformation("【抽奖的主播】{ups}",
- string.Join(",", _tianXuanFollowed.Select(x => x.Uname)));
-
- //目标分组up集合
- List targetUps = await GetNeedGroup();
- _logger.LogInformation("【将自动分组】{ups}",
- string.Join(",", targetUps.Select(x => x.Uname)));
+ //根据配置过滤
+ if (!check.AwardNameIsSatisfied(_liveLotteryTaskOptions.IncludeAwardNameList,
+ _liveLotteryTaskOptions.ExcludeAwardNameList))
+ {
+ _logger.LogDebug("不满足配置的筛选条件,跳过{newLine}", Environment.NewLine);
+ return;
+ }
- if (!targetUps.Any())
+ //是否需要赠礼
+ if (check.Gift_price > 0)
{
+ _logger.LogDebug("【赠礼】{gift}", check.GiftDesc);
+ _logger.LogDebug("需赠送礼物,跳过{newLine}", Environment.NewLine);
return;
}
- //目标分组Id
- long targetGroupId = await GetOrCreateTianXuanGroupId();
+ //条件
+ if (check.Require_type != RequireType.None && check.Require_type != RequireType.Follow)
+ {
+ _logger.LogDebug("【条件】{text}", check.Require_text);
+ _logger.LogDebug("要求粉丝勋章,跳过");
+ return;
+ }
- //执行批量分组
- var referer = string.Format(RelationApiConstant.CopyReferer, _biliCookie.UserId);
- var req = new CopyUserToGroupRequest(
- targetUps.Select(x => x.Uid).ToList(),
- targetGroupId.ToString(),
- _biliCookie.BiliJct);
- var re = await _relationApi.CopyUpsToGroup(req, referer);
+ _logger.LogInformation("【房间】{name}", target.ShortTitle);
+ _logger.LogInformation("【主播】{name}({id})", target.Uname, target.Uid);
+ _logger.LogInformation("【奖品】{name}【条件】{text}", check.Award_name, check.Require_text);
- if (re.Code == 0)
+ var request = new JoinTianXuanRequest
{
- _logger.LogInformation("【分组结果】全部成功");
- }
- else
+ Id = check.Id,
+ Gift_id = check.Gift_id,
+ Gift_num = check.Gift_num,
+ Csrf = _biliCookie.BiliJct
+ };
+ var re = await _liveApi.Join(request);
+ if (re.Code == 0)
{
- _logger.LogWarning("【分组结果】失败");
- _logger.LogWarning("【原因】{msg}", re.Message);
+ _logger.LogInformation("【抽奖】成功 √{newLine}", Environment.NewLine);
+ if (check.Require_type == RequireType.Follow)
+ _tianXuanFollowed.AddIfNotExist(target, x => x.Uid == target.Uid);
+ return;
}
- }
-
- ///
- /// 获取抽奖前最后一个关注的up
- ///
- ///
- private async Task GetLastFollowUpId()
+ _logger.LogInformation("【抽奖】失败");
+ _logger.LogInformation("【原因】{msg}{newLine}", re.Message, Environment.NewLine);
+ }
+ catch (Exception ex)
{
- var followings = await _relationApi
- .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc));
- return followings.Data.List.FirstOrDefault()?.Mid ?? 0;
+ _logger.LogWarning("【异常】{msg},{detail}{newLine}", ex.Message, ex, Environment.NewLine);
+ //ignore
}
+ }
- ///
- /// 获取本次需要自动分组的主播
- ///
- ///
- private async Task> GetNeedGroup()
+ ///
+ /// 将本次抽奖新增的关注统一转移到指定分组中
+ ///
+ public async Task GroupFollowing()
+ {
+ if (!_tianXuanFollowed.Any())
{
- List addUpIds = new();
+ _logger.LogInformation("未关注主播");
+ return;
+ }
- //获取最后一个upId之后关注的所有upId
- var followings = await _relationApi
- .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc));
+ _logger.LogInformation("【抽奖的主播】{ups}",
+ string.Join(",", _tianXuanFollowed.Select(x => x.Uname)));
- foreach (UpInfo item in followings.Data.List)
- {
- if (item.Mid == _lastFollowUpId)
- {
- break;
- }
+ //目标分组up集合
+ List targetUps = await GetNeedGroup();
+ _logger.LogInformation("【将自动分组】{ups}",
+ string.Join(",", targetUps.Select(x => x.Uname)));
- addUpIds.Add(item.Mid);
- }
+ if (!targetUps.Any())
+ {
+ return;
+ }
- //和成功抽奖的主播取交集
- List target = new();
- foreach (var listItemDto in _tianXuanFollowed)
- {
- if (addUpIds.Contains(listItemDto.Uid))
- target.Add(listItemDto);
- }
+ //目标分组Id
+ long targetGroupId = await GetOrCreateTianXuanGroupId();
- return target;
- }
+ //执行批量分组
+ var referer = string.Format(RelationApiConstant.CopyReferer, _biliCookie.UserId);
+ var req = new CopyUserToGroupRequest(
+ targetUps.Select(x => x.Uid).ToList(),
+ targetGroupId.ToString(),
+ _biliCookie.BiliJct);
+ var re = await _relationApi.CopyUpsToGroup(req, referer);
- ///
- /// 获取或创建天选时刻分组
- ///
- ///
- private async Task GetOrCreateTianXuanGroupId()
+ if (re.Code == 0)
{
- //获取天选分组Id,没有就创建
- long groupId = 0;
- string referer = string.Format(RelationApiConstant.GetTagsReferer, _biliCookie.UserId);
- var groups = await _relationApi.GetTags(referer);
- var tianXuanGroup = groups.Data.FirstOrDefault(x => x.Name == "天选时刻");
- if (tianXuanGroup == null)
- {
- _logger.LogInformation("“天选时刻”分组不存在,尝试创建...");
- //创建一个
- var createRe =
- await _relationApi.CreateTag(new CreateTagRequest { Tag = "天选时刻", Csrf = _biliCookie.BiliJct });
- groupId = createRe.Data.Tagid;
- _logger.LogInformation("创建成功");
- }
- else
- {
- _logger.LogInformation("“天选时刻”分组已存在");
- groupId = tianXuanGroup.Tagid;
- }
-
- return groupId;
+ _logger.LogInformation("【分组结果】全部成功");
+ }
+ else
+ {
+ _logger.LogWarning("【分组结果】失败");
+ _logger.LogWarning("【原因】{msg}", re.Message);
}
+ }
- #endregion
- public async Task SendDanmakuToFansMedalLive()
- {
- if (!await CheckLiveCookie()) return;
+ ///
+ /// 获取抽奖前最后一个关注的up
+ ///
+ ///
+ private async Task GetLastFollowUpId()
+ {
+ var followings = await _relationApi
+ .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc));
+ return followings.Data.List.FirstOrDefault()?.Mid ?? 0;
+ }
+
+ ///
+ /// 获取本次需要自动分组的主播
+ ///
+ ///
+ private async Task> GetNeedGroup()
+ {
+ List addUpIds = new();
- var infoList = await GetFansMedalInfoList();
+ //获取最后一个upId之后关注的所有upId
+ var followings = await _relationApi
+ .GetFollowings(new GetFollowingsRequest(long.Parse(_biliCookie.UserId), FollowingsOrderType.TimeDesc));
- foreach (var info in infoList)
+ foreach (UpInfo item in followings.Data.List)
+ {
+ if (item.Mid == _lastFollowUpId)
{
- var medal = info.MedalInfo;
+ break;
+ }
- _logger.LogInformation("【直播间】{liveRoomName}", medal.Target_name);
- _logger.LogInformation("【粉丝牌】{medalName}", medal.Medal_info.Medal_name);
- _logger.LogInformation("正在发送弹幕...");
+ addUpIds.Add(item.Mid);
+ }
- // 通过空间主页信息获取直播间 id
- var liveHostUserId = medal.Medal_info.Target_id;
- var req = new GetSpaceInfoDto() { mid = liveHostUserId };
- await _wbiService.SetWridAsync(req);
+ //和成功抽奖的主播取交集
+ List target = new();
+ foreach (var listItemDto in _tianXuanFollowed)
+ {
+ if (addUpIds.Contains(listItemDto.Uid))
+ target.Add(listItemDto);
+ }
- var spaceInfo = await _userInfoApi.GetSpaceInfo(req);
- if (spaceInfo.Code != 0)
- {
- _logger.LogError("【获取直播间信息】失败");
- _logger.LogError("【原因】{message}", spaceInfo.Message);
- return;
- }
+ return target;
+ }
- var successCount = 0;
- var failedCount = 0;
+ ///
+ /// 获取或创建天选时刻分组
+ ///
+ ///
+ private async Task GetOrCreateTianXuanGroupId()
+ {
+ //获取天选分组Id,没有就创建
+ long groupId = 0;
+ string referer = string.Format(RelationApiConstant.GetTagsReferer, _biliCookie.UserId);
+ var groups = await _relationApi.GetTags(referer);
+ var tianXuanGroup = groups.Data.FirstOrDefault(x => x.Name == "天选时刻");
+ if (tianXuanGroup == null)
+ {
+ _logger.LogInformation("“天选时刻”分组不存在,尝试创建...");
+ //创建一个
+ var createRe =
+ await _relationApi.CreateTag(new CreateTagRequest { Tag = "天选时刻", Csrf = _biliCookie.BiliJct });
+ groupId = createRe.Data.Tagid;
+ _logger.LogInformation("创建成功");
+ }
+ else
+ {
+ _logger.LogInformation("“天选时刻”分组已存在");
+ groupId = tianXuanGroup.Tagid;
+ }
- // 发送弹幕
+ return groupId;
+ }
- while (successCount < _liveFansMedalTaskOptions.SendDanmakuNumber &&
- failedCount < _liveFansMedalTaskOptions.SendDanmakugiveUpThreshold)
- {
- var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest(
- _biliCookie.BiliJct,
- spaceInfo.Data.Live_room.Roomid,
- _liveFansMedalTaskOptions.DanmakuContent));
-
- if (sendResult.Code != 0)
- {
- _logger.LogError("【弹幕发送】失败");
- _logger.LogError("【原因】{message}", sendResult.Message);
- failedCount++;
- }
- else
- successCount++;
-
- var delay = new Random().Next(2000, 4000);
- await Task.Delay(delay);
- }
+ #endregion
+ public async Task SendDanmakuToFansMedalLive()
+ {
+ if (!await CheckLiveCookie()) return;
- _logger.LogInformation("【弹幕发送】发送情况:你向主播 {name} 发送弹幕{success}/{total}", spaceInfo.Data.Name,
- successCount, successCount + failedCount);
- }
- }
+ var infoList = await GetFansMedalInfoList();
- public async Task SendHeartBeatToFansMedalLive()
+ foreach (var info in infoList)
{
- if (!await CheckLiveCookie()) return;
+ var medal = info.MedalInfo;
- var infoList = new List();
- (await GetFansMedalInfoList()).FindAll(info => info.LiveRoomInfo.Live_Status != 0).ForEach(medal =>
- infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0))
- );
+ _logger.LogInformation("【直播间】{liveRoomName}", medal.Target_name);
+ _logger.LogInformation("【粉丝牌】{medalName}", medal.Medal_info.Medal_name);
+ _logger.LogInformation("正在发送弹幕...");
- if (infoList.Count == 0)
+ // 通过空间主页信息获取直播间 id
+ var liveHostUserId = medal.Medal_info.Target_id;
+ var req = new GetSpaceInfoDto() { mid = liveHostUserId };
+ await _wbiService.SetWridAsync(req);
+
+ var spaceInfo = await _userInfoApi.GetSpaceInfo(req);
+ if (spaceInfo.Code != 0)
{
- _logger.LogInformation("【直播观看时长】跳过,未检测到符合条件的主播");
+ _logger.LogError("【获取直播间信息】失败");
+ _logger.LogError("【原因】{message}", spaceInfo.Message);
return;
}
- var Now = () => new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+ var successCount = 0;
+ var failedCount = 0;
+
+ // 发送弹幕
- while (infoList.Min(
- info => info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold
- ? int.MaxValue
- : info.HeartBeatCount)
- < _liveFansMedalTaskOptions.HeartBeatNumber)
+ while (successCount < _liveFansMedalTaskOptions.SendDanmakuNumber &&
+ failedCount < _liveFansMedalTaskOptions.SendDanmakugiveUpThreshold)
{
- foreach (var info in infoList)
+ var sendResult = await _liveApi.SendLiveDanmuku(new SendLiveDanmukuRequest(
+ _biliCookie.BiliJct,
+ spaceInfo.Data.Live_room.Roomid,
+ _liveFansMedalTaskOptions.DanmakuContent));
+
+ if (sendResult.Code != 0)
{
- // 忽略连续失败超过上限的直播间
- if (info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold) continue;
-
- string uuid = Guid.NewGuid().ToString();
- var current = Now();
- if (current - info.LastBeatTime <= (LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000)
- {
- int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 -
- (current - info.LastBeatTime));
- _logger.LogDebug("【休眠】{time} 毫秒", sleepTime);
- Thread.Sleep(sleepTime);
- }
-
- // Heart Beat 接口
- var timestamp = Now();
- BiliApiResponse heartBeatResult = null;
- if (info.HeartBeatCount == 0)
- {
- heartBeatResult = await _liveTraceApi.EnterRoom(
- new EnterRoomRequest(
- info.RoomId,
- info.RoomInfo.Parent_area_id,
- info.RoomInfo.Area_id,
- info.HeartBeatCount,
- timestamp,
- _securityOptions.UserAgent,
- _biliCookie.BiliJct,
- info.RoomInfo.Uid,
- $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]")
- );
- }
- else
- {
- heartBeatResult = await _liveTraceApi.HeartBeat(
- new HeartBeatRequest(
- info.RoomId,
- info.RoomInfo.Parent_area_id,
- info.RoomInfo.Area_id,
- info.HeartBeatCount,
- _biliCookie.LiveBuvid,
- timestamp,
- info.HeartBeatInfo.Timestamp,
- _securityOptions.UserAgent,
- info.HeartBeatInfo.Secret_rule,
- info.HeartBeatInfo.Secret_key,
- _biliCookie.BiliJct,
- uuid,
- $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]")
- );
- }
-
- info.LastBeatTime = Now();
-
- if (heartBeatResult != null && heartBeatResult.Data != null)
- {
- info.HeartBeatInfo.Secret_key = heartBeatResult.Data.Secret_key;
- info.HeartBeatInfo.Secret_rule = heartBeatResult.Data.Secret_rule;
- info.HeartBeatInfo.Timestamp = heartBeatResult.Data.Timestamp;
- }
-
- if (heartBeatResult == null || heartBeatResult.Code != 0)
- {
- _logger.LogError("【心跳包】直播间 {room} 发送失败", info.RoomId);
- _logger.LogError("【原因】{message}", heartBeatResult != null ? heartBeatResult.Message : "");
- info.FailedTimes += 1;
- continue;
- }
-
- info.HeartBeatCount += 1;
- info.FailedTimes = 0;
-
- _logger.LogInformation("【直播间】{roomId} 的第 {index} 个心跳包发送成功", info.RoomId, info.HeartBeatCount);
+ _logger.LogError("【弹幕发送】失败");
+ _logger.LogError("【原因】{message}", sendResult.Message);
+ failedCount++;
}
+ else
+ successCount++;
+
+ var delay = new Random().Next(2000, 4000);
+ await Task.Delay(delay);
}
- var successCount = infoList.Count(info => info.HeartBeatCount >= _liveFansMedalTaskOptions.HeartBeatNumber);
- _logger.LogInformation("【直播观看时长】完成情况:{success}/{total} ", successCount, infoList.Count);
+
+ _logger.LogInformation("【弹幕发送】发送情况:你向主播 {name} 发送弹幕{success}/{total}", spaceInfo.Data.Name,
+ successCount, successCount + failedCount);
}
+ }
- ///
- /// 点赞直播间
- ///
- public async Task LikeFansMedalLive()
+ public async Task SendHeartBeatToFansMedalLive()
+ {
+ if (!await CheckLiveCookie()) return;
+
+ var infoList = new List();
+ (await GetFansMedalInfoList()).FindAll(info => info.LiveRoomInfo.Live_Status != 0).ForEach(medal =>
+ infoList.Add(new(medal.RoomId, medal.LiveRoomInfo, new(), 0, 0))
+ );
+
+ if (infoList.Count == 0)
{
- if (!await CheckLiveCookie()) return;
+ _logger.LogInformation("【直播观看时长】跳过,未检测到符合条件的主播");
+ return;
+ }
- var infoList = await GetFansMedalInfoList();
- infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 0);
- _logger.LogInformation("当前开播直播间数量:{num}", infoList.Count);
+ var Now = () => new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
+
+ while (infoList.Min(
+ info => info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold
+ ? int.MaxValue
+ : info.HeartBeatCount)
+ < _liveFansMedalTaskOptions.HeartBeatNumber)
+ {
foreach (var info in infoList)
{
- // Clike_Time 暂时设置为等于设置的LikeNumber,不清楚是否会被风控,我自己抓包最大值为10
- var request = new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct,
- _liveFansMedalTaskOptions.LikeNumber,
- info.LiveRoomInfo.Uid, _biliCookie.UserId);
+ // 忽略连续失败超过上限的直播间
+ if (info.FailedTimes >= _liveFansMedalTaskOptions.HeartBeatSendGiveUpThreshold) continue;
- var result = await _liveApi.LikeLiveRoom(request.RawTextBuild());
- if (result.Code == 0)
+ string uuid = Guid.NewGuid().ToString();
+ var current = Now();
+ if (current - info.LastBeatTime <= (LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000)
{
- _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId);
+ int sleepTime = (int)((LiveFansMedalTaskOptions.HeartBeatInterval + 5) * 1000 -
+ (current - info.LastBeatTime));
+ _logger.LogDebug("【休眠】{time} 毫秒", sleepTime);
+ Thread.Sleep(sleepTime);
}
- else
+
+ // Heart Beat 接口
+ var timestamp = Now();
+ BiliApiResponse heartBeatResult = null;
+ if (info.HeartBeatCount == 0)
{
- _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId);
- _logger.LogError("【原因】{message}", result.Message);
+ heartBeatResult = await _liveTraceApi.EnterRoom(
+ new EnterRoomRequest(
+ info.RoomId,
+ info.RoomInfo.Parent_area_id,
+ info.RoomInfo.Area_id,
+ info.HeartBeatCount,
+ timestamp,
+ _securityOptions.UserAgent,
+ _biliCookie.BiliJct,
+ info.RoomInfo.Uid,
+ $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]")
+ );
}
-
- var delay = new Random().Next(5000, 8000);
- await Task.Delay(delay);
- }
- }
-
- private async Task> GetFansMedalInfoList()
- {
- _logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表");
- var medalWallInfo = await _liveApi.GetMedalWall(_biliCookie.UserId);
-
- if (medalWallInfo.Code != 0)
- {
- _logger.LogError("【获取直播列表】失败");
- _logger.LogError("【原因】{message}", medalWallInfo.Message);
- return null;
- }
-
- var infoList = new List();
- foreach (var medal in medalWallInfo.Data.List)
- {
- _logger.LogInformation("【主播】{name} ", medal.Target_name);
- if (_liveFansMedalTaskOptions.IsSkipLevel20Medal && medal.Medal_info.Level >= 20)
+ else
{
- _logger.LogInformation("粉丝牌等级为 {level},观看将不再增长亲密度,跳过", medal.Medal_info.Level);
- continue;
+ heartBeatResult = await _liveTraceApi.HeartBeat(
+ new HeartBeatRequest(
+ info.RoomId,
+ info.RoomInfo.Parent_area_id,
+ info.RoomInfo.Area_id,
+ info.HeartBeatCount,
+ _biliCookie.LiveBuvid,
+ timestamp,
+ info.HeartBeatInfo.Timestamp,
+ _securityOptions.UserAgent,
+ info.HeartBeatInfo.Secret_rule,
+ info.HeartBeatInfo.Secret_key,
+ _biliCookie.BiliJct,
+ uuid,
+ $"[\"{_biliCookie.LiveBuvid}\",\"{uuid}\"]")
+ );
}
- // 通过空间主页信息获取直播间 id
- var liveHostUserId = medal.Medal_info.Target_id;
- var req = new GetSpaceInfoDto() { mid = liveHostUserId };
- await _wbiService.SetWridAsync(req);
+ info.LastBeatTime = Now();
- var spaceInfo = await _userInfoApi.GetSpaceInfo(req);
- if (spaceInfo.Code != 0)
+ if (heartBeatResult != null && heartBeatResult.Data != null)
{
- _logger.LogError("【获取空间信息】失败");
- _logger.LogError("【原因】{message}", spaceInfo.Message);
- continue;
+ info.HeartBeatInfo.Secret_key = heartBeatResult.Data.Secret_key;
+ info.HeartBeatInfo.Secret_rule = heartBeatResult.Data.Secret_rule;
+ info.HeartBeatInfo.Timestamp = heartBeatResult.Data.Timestamp;
}
- // 用以排除有牌子无直播间的up主
- if (spaceInfo.Data.Live_room is null)
+ if (heartBeatResult == null || heartBeatResult.Code != 0)
{
- _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过", medal.Target_name);
+ _logger.LogError("【心跳包】直播间 {room} 发送失败", info.RoomId);
+ _logger.LogError("【原因】{message}", heartBeatResult != null ? heartBeatResult.Message : "");
+ info.FailedTimes += 1;
continue;
}
+ info.HeartBeatCount += 1;
+ info.FailedTimes = 0;
- var roomId = spaceInfo.Data.Live_room.Roomid;
+ _logger.LogInformation("【直播间】{roomId} 的第 {index} 个心跳包发送成功", info.RoomId, info.HeartBeatCount);
+ }
+ }
- // 获取直播间详细信息
- var liveRoomInfo = await _liveApi.GetLiveRoomInfo(roomId);
- if (liveRoomInfo.Code != 0)
- {
- _logger.LogError("【获取直播间信息】失败");
- _logger.LogError("【原因】{message}", liveRoomInfo.Message);
- continue;
- }
+ var successCount = infoList.Count(info => info.HeartBeatCount >= _liveFansMedalTaskOptions.HeartBeatNumber);
+ _logger.LogInformation("【直播观看时长】完成情况:{success}/{total} ", successCount, infoList.Count);
+ }
+
+ ///
+ /// 点赞直播间
+ ///
+ public async Task LikeFansMedalLive()
+ {
+ if (!await CheckLiveCookie()) return;
+
+ var infoList = await GetFansMedalInfoList();
+ infoList = infoList.FindAll(info => info.LiveRoomInfo.Live_Status != 0);
+ _logger.LogInformation("当前开播直播间数量:{num}", infoList.Count);
+ foreach (var info in infoList)
+ {
+ // Clike_Time 暂时设置为等于设置的LikeNumber,不清楚是否会被风控,我自己抓包最大值为10
+ var request = new LikeLiveRoomRequest(info.RoomId, _biliCookie.BiliJct,
+ _liveFansMedalTaskOptions.LikeNumber,
+ info.LiveRoomInfo.Uid, _biliCookie.UserId);
- infoList.Add(new FansMedalInfoDto(roomId, medal, liveRoomInfo.Data));
+ var result = await _liveApi.LikeLiveRoom(request.RawTextBuild());
+ if (result.Code == 0)
+ {
+ _logger.LogInformation("【点赞直播间】{roomId} 完成", info.RoomId);
}
+ else
+ {
+ _logger.LogError("【点赞直播间】{roomId} 时候出现错误", info.RoomId);
+ _logger.LogError("【原因】{message}", result.Message);
+ }
+
+ var delay = new Random().Next(5000, 8000);
+ await Task.Delay(delay);
+ }
+ }
+
+ private async Task> GetFansMedalInfoList()
+ {
+ _logger.LogInformation("【获取直播列表】获取拥有粉丝牌的直播列表");
+ var medalWallInfo = await _liveApi.GetMedalWall(_biliCookie.UserId);
- return infoList;
+ if (medalWallInfo.Code != 0)
+ {
+ _logger.LogError("【获取直播列表】失败");
+ _logger.LogError("【原因】{message}", medalWallInfo.Message);
+ return new List();
}
- ///
- /// 自动配置直播相关 Cookie,来兼容较低版本中保存的 Cookie 配置
- ///
- ///
- /// bool 成功配置 or not
- ///
- private async Task CheckLiveCookie()
+ var infoList = new List();
+ foreach (var medal in medalWallInfo.Data.List)
{
- // 检测 _biliCookie 是否正确配置
- if (!string.IsNullOrWhiteSpace(_biliCookie.LiveBuvid)) return true;
+ _logger.LogInformation("【主播】{name} ", medal.Target_name);
+ if (_liveFansMedalTaskOptions.IsSkipLevel20Medal && medal.Medal_info.Level >= 20)
+ {
+ _logger.LogInformation("粉丝牌等级为 {level},观看将不再增长亲密度,跳过", medal.Medal_info.Level);
+ continue;
+ }
- try
+ // 通过空间主页信息获取直播间 id
+ var liveHostUserId = medal.Medal_info.Target_id;
+ var req = new GetSpaceInfoDto() { mid = liveHostUserId };
+ await _wbiService.SetWridAsync(req);
+
+ var spaceInfo = await _userInfoApi.GetSpaceInfo(req);
+ if (spaceInfo.Code != 0)
{
- _logger.LogInformation("检测到直播 Cookie 未正确配置,尝试自动配置中...");
+ _logger.LogError("【获取空间信息】失败");
+ _logger.LogError("【原因】{message}", spaceInfo.Message);
+ continue;
+ }
- // 请求主播主页来正确配置 cookie
- var liveHome = await _liveApi.GetLiveHome();
- var liveHomeContent =
- JsonConvert.DeserializeObject(await liveHome.Content.ReadAsStringAsync());
- if (liveHomeContent.Code != 0)
- {
- throw new Exception(liveHomeContent.Message);
- }
+ // 用以排除有牌子无直播间的up主
+ if (spaceInfo.Data.Live_room is null)
+ {
+ _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过", medal.Target_name);
+ continue;
+ }
- List liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value
- .ToList();
- _biliCookie.MergeCurrentCookie(liveCookies);
- _logger.LogDebug("LiveBuvid {value}", _biliCookie.LiveBuvid);
- _logger.LogInformation("直播 Cookie 配置成功!");
+ var roomId = spaceInfo.Data.Live_room.Roomid;
+
+ // 获取直播间详细信息
+ var liveRoomInfo = await _liveApi.GetLiveRoomInfo(roomId);
+ if (liveRoomInfo.Code != 0)
+ {
+ _logger.LogError("【获取直播间信息】失败");
+ _logger.LogError("【原因】{message}", liveRoomInfo.Message);
+ continue;
}
- catch (Exception exception)
+
+ infoList.Add(new FansMedalInfoDto(roomId, medal, liveRoomInfo.Data));
+ }
+
+ return infoList;
+ }
+
+ ///
+ /// 自动配置直播相关 Cookie,来兼容较低版本中保存的 Cookie 配置
+ ///
+ ///
+ /// bool 成功配置 or not
+ ///
+ private async Task CheckLiveCookie()
+ {
+ // 检测 _biliCookie 是否正确配置
+ if (!string.IsNullOrWhiteSpace(_biliCookie.LiveBuvid)) return true;
+
+ try
+ {
+ _logger.LogInformation("检测到直播 Cookie 未正确配置,尝试自动配置中...");
+
+ // 请求主播主页来正确配置 cookie
+ var liveHome = await _liveApi.GetLiveHome();
+ var liveHomeContent =
+ JsonConvert.DeserializeObject(await liveHome.Content.ReadAsStringAsync());
+ if (liveHomeContent.Code != 0)
{
- _logger.LogError("【配置直播Cookie】失败,放弃执行后续任务...");
- _logger.LogError("【原因】{message}", exception.Message);
- return false;
+ throw new Exception(liveHomeContent.Message);
}
- return true;
+ List liveCookies = liveHome.Headers.SingleOrDefault(header => header.Key == "Set-Cookie").Value
+ .ToList();
+ _biliCookie.MergeCurrentCookie(liveCookies);
+
+ _logger.LogDebug("LiveBuvid {value}", _biliCookie.LiveBuvid);
+ _logger.LogInformation("直播 Cookie 配置成功!");
}
+ catch (Exception exception)
+ {
+ _logger.LogError("【配置直播Cookie】失败,放弃执行后续任务...");
+ _logger.LogError("【原因】{message}", exception.Message);
+ return false;
+ }
+
+ return true;
}
}
\ No newline at end of file