网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
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
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码是一个 ASP.NET Core Web API 控制器,名为 DanmakuController,用于管理弹幕(通常用于视频或直播平台的实时评论)。以下是代码的主要功能和结构的详细解释:

1. 控制器概述

  • 命名空间: Dpz.Core.WebApi.Controllers,表示该控制器属于 Web API 的控制器集合。
  • 特性:
    • [ApiController]: 指示该类是一个 API 控制器,启用一些 API 特性(如自动模型验证)。
    • [Route("api/[controller]")]: 定义路由模板,[controller] 会被替换为控制器的名称(即 Danmaku)。
    • [Authorize(Policy = "System")]: 需要授权才能访问该控制器,只有符合 "System" 策略的用户才能访问。

2. 主要功能

控制器提供了多个 API 端点,主要用于获取、删除和导入弹幕数据。

2.1 获取弹幕

  • 方法: GetDanmaku
  • HTTP 方法: GET
  • 路由: api/danmaku
  • 功能: 根据查询参数(如页码、页大小、文本和分组)获取弹幕列表,并返回分页元数据。

2.2 获取弹幕分组

  • 方法: GetGroups
  • HTTP 方法: GET
  • 路由: api/danmaku/group
  • 功能: 获取所有弹幕分组的列表。

2.3 删除弹幕

  • 方法: Delete
  • HTTP 方法: DELETE
  • 路由: api/danmaku
  • 功能: 根据提供的 ID 数组删除弹幕。

2.4 导入 A 站弹幕

  • 方法: ImportAcFun
  • HTTP 方法: POST
  • 路由: api/danmaku/import/acfun
  • 功能: 从上传的 JSON 文件中导入 A 站(AcFun)的弹幕数据。验证文件扩展名是否为 .json,并将数据转换为 VmBarrage 对象后导入。

2.5 导入 B 站弹幕

  • 方法: ImportBilibili
  • HTTP 方法: POST
  • 路由: api/danmaku/import/bilibili
  • 功能: 从上传的 XML 文件中导入 B 站(Bilibili)的弹幕数据。验证文件扩展名是否为 .xml,并将数据转换为 VmBarrage 对象后导入。

3. 数据模型

  • AcFunDanmaku: 用于表示 A 站弹幕的模型,包含颜色、模式、创建时间、文本、位置和大小等属性。
  • DanmakuType: 枚举类型,定义了弹幕的显示位置(滚动、顶部、底部)。

4. 异常处理

在导入弹幕的过程中,如果发生异常,会记录错误日志并返回 BadRequest 响应,包含错误信息。

5. 其他

  • 依赖注入: 控制器通过构造函数注入 IBarrageServiceILogger<DanmakuController>,用于处理业务逻辑和记录日志。

总结

该控制器提供了一系列 API 接口,用于管理弹幕数据,包括获取、删除和导入弹幕,支持 A 站和 B 站的弹幕格式,适用于需要实时评论功能的应用场景。

loading