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

支持在搜索框中输入 AV/BV 号直接跳转到视频 #830

Merged
merged 1 commit into from
Oct 17, 2024
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
59 changes: 59 additions & 0 deletions src/Desktop/BiliCopilot.UI/Toolkits/IdToolkit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Bili Copilot. All rights reserved.

namespace BiliCopilot.UI.Toolkits;

/// <summary>
/// 视频 ID 工具箱.
/// </summary>
public static class IdToolkit
{
private const long XOR_CODE = 23442827791579L;
private const long MASK_CODE = 2251799813685247L;
private const long MAX_AID = 1L << 51;
private const long BASE = 58L;

private const string DATA = "FcwAPNKTMug3GV5Lj7EJnHpWsx4tb8haYeviqBz6rkCy12mUSDQX9RdoZf";

/// <summary>
/// 将 AV 号转换为 BV 号.
/// </summary>
/// <param name="aid">AID.</param>
/// <returns>BVId.</returns>
public static string Av2Bv(long aid)
{
var bytes = new char[] { 'B', 'V', '1', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
var bvIndex = bytes.Length - 1;
var tmp = (MAX_AID | aid) ^ XOR_CODE;

while (tmp > 0)
{
bytes[bvIndex] = DATA[(int)(tmp % BASE)];
tmp /= BASE;
bvIndex--;
}

Swap(ref bytes[3], ref bytes[9]);
Swap(ref bytes[4], ref bytes[7]);

return new string(bytes);
}

/// <summary>
/// 将 BV 号转换为 AV 号.
/// </summary>
/// <param name="bvid">BV Id.</param>
/// <returns>AVId.</returns>
public static long Bv2Av(string bvid)
{
var bvidArr = bvid.ToArray();
Swap(ref bvidArr[3], ref bvidArr[9]);
Swap(ref bvidArr[4], ref bvidArr[7]);
bvidArr = bvidArr.Skip(3).ToArray();

var tmp = bvidArr.Aggregate(0L, (pre, bvidChar) => (pre * BASE) + DATA.IndexOf(bvidChar));

return (tmp & MASK_CODE) ^ XOR_CODE;
}

private static void Swap(ref char a, ref char b) => (b, a) = (a, b);
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public VideoItemViewModel(
var primaryLan = ApplicationLanguages.Languages[0];
Style = style;
Title = info.Identifier.Title;
Cover = info.Identifier.Cover.Uri;
Cover = info.Identifier.Cover?.Uri;
Author = info.Publisher?.User?.Name;
Avatar = info.Publisher?.User?.Avatar?.Uri;
Duration = AppToolkit.FormatDuration(TimeSpan.FromSeconds(info.Duration ?? 0));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
// Copyright (c) Bili Copilot. All rights reserved.

using System.Diagnostics;
using BiliCopilot.UI.Models.Constants;
using BiliCopilot.UI.Pages.Overlay;
using BiliCopilot.UI.Toolkits;
using BiliCopilot.UI.ViewModels.Components;
using BiliCopilot.UI.ViewModels.Core;
using BiliCopilot.UI.ViewModels.Items;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -46,6 +48,34 @@ private async Task SearchAsync(string keyword)
return;
}

if (keyword.StartsWith("av", StringComparison.InvariantCultureIgnoreCase))
{
var videoId = keyword[2..];

// videoId should be a number.
if (long.TryParse(videoId, out var id))
{
this.Get<NavigationViewModel>().Back();
var video = new VideoInformation(new MediaIdentifier(videoId, default, default), default);
new VideoItemViewModel(video, VideoCardStyle.Search).PlayCommand.Execute(default);
return;
}
}
else if (keyword.StartsWith("BV"))
{
try
{
var video = new VideoInformation(new MediaIdentifier(IdToolkit.Bv2Av(keyword).ToString(), default, default), default);
this.Get<NavigationViewModel>().Back();
new VideoItemViewModel(video, VideoCardStyle.Search).PlayCommand.Execute(default);
return;
}
catch (Exception)
{
Debug.WriteLine("尝试解析BV号时失败.");
}
}

Keyword = keyword;
Sections = default;
SelectedSection = default;
Expand Down
2 changes: 1 addition & 1 deletion src/Libs/Danmaku.Core/DanmakuFrostMaster.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public bool DebugMode
/// </summary>
public DanmakuFrostMaster(Grid rootGrid, ILogger<DanmakuFrostMaster> logger = default)
{
rootGrid.Children.Clear();
rootGrid?.Children.Clear();
if (rootGrid.XamlRoot is null)
{
return;
Expand Down
Loading