网站首页 网站源码
namespace Dpz.Core.WebApi.Controllers;
/// <summary>
/// 弹幕管理
/// </summary>
[ApiController, Route("api/[controller]"), Authorize(Policy = "System")]
public class DanmakuController(IBarrageService barrageService, ILogger<DanmakuController> logger)
: ControllerBase
{
/// <summary>
/// 获取弹幕
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
[HttpGet]
[ProducesResponseType<List<VmBarrage>>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> GetDanmaku([FromQuery] DanmakuQueryDto query)
{
var list = await barrageService.GetPageAsync(
query.PageIndex,
query.PageSize,
query.Text,
query.Group
);
list.AddPaginationMetadata(Response.Headers);
return Ok(list);
}
/// <summary>
/// 获取弹幕分组
/// </summary>
/// <returns></returns>
[HttpGet("group")]
[ProducesResponseType<List<string>>(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> GetGroups()
{
var groups = await barrageService.GetGroupsAsync();
return Ok(groups);
}
/// <summary>
/// 删除弹幕
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpDelete]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> Delete([FromBody] [Required] string[] id)
{
await barrageService.DeleteAsync(id);
return NoContent();
}
/// <summary>
/// 导入A站弹幕
/// </summary>
/// <returns></returns>
[HttpPost("import/acfun")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> ImportAcFun([FromForm] ImportDanmaku import)
{
var extensionName = Path.GetExtension(import.File.FileName);
if (extensionName != ".json")
return NoContent();
try
{
var danmakus = await JsonSerializer.DeserializeAsync<List<AcFunDanmaku>>(
import.File.OpenReadStream(),
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
);
var source =
danmakus
?.Select(x => new VmBarrage
{
Group = import.Group,
Color = x.Color.ToString(),
Position = x.Mode == 5 ? 1 : 0,
SendTime = x.GetCreateTime(),
Size = x.Size,
Text = x.Body,
Time = x.Position / (decimal)1e3
})
?.ToArray() ?? [];
await barrageService.ImportAsync(source);
return NoContent();
}
catch (Exception e)
{
logger.LogError(e, "import acfun danmaku fail");
return BadRequest(e.Message);
}
}
/// <summary>
/// 导入B站弹幕
/// </summary>
/// <returns></returns>
[HttpPost("import/bilibili")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status401Unauthorized)]
public async Task<IActionResult> ImportBilibili([FromForm] ImportDanmaku import)
{
var extensionName = Path.GetExtension(import.File.FileName);
if (extensionName != ".xml")
return NoContent();
try
{
var source = await XElement.LoadAsync(
import.File.OpenReadStream(),
LoadOptions.None,
CancellationToken.None
);
var bilibiliDanmakus = (
from x in source.Elements("d")
let p = x.Attribute("p")
where p != null && !string.IsNullOrEmpty(p.Value)
let props = p.Value.Split(",")
where props.Length >= 5
let type = props[1] switch
{
"1" => DanmakuType.Rolling,
"4" => DanmakuType.Bottom,
"5" => DanmakuType.Top,
_ => DanmakuType.Rolling
}
select new VmBarrage
{
Group = import.Group,
Color = props[3],
Position = (int)type,
SendTime = long.Parse(props[4]).ToDateTime(),
Size = int.Parse(props[2]),
Text = x.Value,
Time = decimal.Parse(props[0]),
}
).ToArray();
await barrageService.ImportAsync(bilibiliDanmakus);
return NoContent();
}
catch (Exception e)
{
logger.LogError(e, "import bilibili danmaku fail");
return BadRequest(e.Message);
}
}
/// <summary>
/// AcFun弹幕
/// </summary>
private record AcFunDanmaku
{
public int Color { get; set; }
public int Mode { get; set; }
public long CreateTime { get; set; }
public string Body { get; set; }
public int Position { get; set; }
public int Size { get; set; }
public DateTime GetCreateTime()
{
var time = CreateTime / 1000D;
var utcTime = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddSeconds(time);
return utcTime.LocalDateTime;
}
}
private enum DanmakuType
{
Rolling = 0,
Top = 1,
Bottom = 2
}
}
上述代码是一个 ASP.NET Core Web API 控制器,名为 DanmakuController
,用于管理弹幕(通常用于视频或直播平台的实时评论)。以下是代码的主要功能和结构的详细解释:
Dpz.Core.WebApi.Controllers
,表示该控制器属于 Web API 的控制器集合。[ApiController]
: 指示该类是一个 API 控制器,启用一些 API 特性(如自动模型验证)。[Route("api/[controller]")]
: 定义路由模板,[controller]
会被替换为控制器的名称(即 Danmaku
)。[Authorize(Policy = "System")]
: 需要授权才能访问该控制器,只有符合 "System" 策略的用户才能访问。控制器提供了多个 API 端点,主要用于获取、删除和导入弹幕数据。
GetDanmaku
GET
api/danmaku
GetGroups
GET
api/danmaku/group
Delete
DELETE
api/danmaku
ImportAcFun
POST
api/danmaku/import/acfun
.json
,并将数据转换为 VmBarrage
对象后导入。ImportBilibili
POST
api/danmaku/import/bilibili
.xml
,并将数据转换为 VmBarrage
对象后导入。在导入弹幕的过程中,如果发生异常,会记录错误日志并返回 BadRequest
响应,包含错误信息。
IBarrageService
和 ILogger<DanmakuController>
,用于处理业务逻辑和记录日志。该控制器提供了一系列 API 接口,用于管理弹幕数据,包括获取、删除和导入弹幕,支持 A 站和 B 站的弹幕格式,适用于需要实时评论功能的应用场景。