using System.Net.Http;
using System.ServiceModel.Syndication;
using System.Xml;
using AngleSharp;
using AngleSharp.Html;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Web.Library.Api;
using Microsoft.AspNetCore.SignalR;
using OpenIddict.Client.AspNetCore;
using IConfiguration = Microsoft.Extensions.Configuration.IConfiguration;
// ReSharper disable UnusedVariable
#pragma warning disable CS0162

namespace Dpz.Core.Web.Controllers;

public class HomeController(
    IBingWallpaper bingWallpaper,
    IConfiguration configuration,
    IFusionCache fusionCache
) : Controller
{
    /// <summary>
    /// home
    /// </summary>
    /// <param name="cacheService"></param>
    /// <returns></returns>
    public async Task<IActionResult> Index([FromServices] IHomeCacheService cacheService)
    {
        ViewBag.Menu = MenuItem.Home;
        this.SetTitle("首页");
        var model = await cacheService.GetCacheDataAsync();
        return View(model);
    }

    [Route(("news.html"))]
    public async Task<IActionResult> News(
        [FromServices] IHomeCacheService cacheService,
        string mode = ""
    )
    {
        var news = await cacheService.GetTodayNewsAsync();
        if (mode == "content")
        {
            return Content(
                news == null
                    ? ""
                    : string.Join(
                        "\n",
                        (news.NewsList ?? []).Select(x =>
                            $"{(news.NewsList ?? []).IndexOf(x) + 1}. {x.Title}"
                        )
                    )
            );
        }

        return View(news);
    }

    public async Task<IActionResult> TodayNews([FromServices] IHomeCacheService cacheService)
    {
        var news = await cacheService.GetTodayNewsAsync();
        return PartialView("_TodayNews", news);
    }

    public async Task<IActionResult> SystemNotifications(
        [FromServices] ISystemNotificationHistoryService notificationService
    )
    {
        var notifications = await notificationService.GetRecentAsync();
        return PartialView("_SystemNotificationsPartial", notifications);
    }

    [HttpGet, Route("datetime")]
    public async Task<IActionResult> Date()
    {
        return await Task.FromResult(View());
    }

#if DEBUG
    public IActionResult Demo(string? msg = null)
    {
        var s = User;
        return Json(new { time = DateTime.Now, message = msg });
    }

    public IActionResult Demo2()
    {
        throw new ArgumentException("param is null");
    }

    public async Task<IActionResult> Demo3(
        [FromServices] IHubContext<Dpz.Core.Web.Library.Hub.Notification> hubContext
    )
    {
        var s = new ProgressMessage
        {
            Message = "测试消息",
            Type = MessageType.Success,
            ProgressValues = [100m, 100m],
        };
        await hubContext.Clients.All.SendCoreAsync("hotTopicMessage", [s]);
        return View();
    }

    public IActionResult LayDemo()
    {
        return View();
    }

    public async Task<IActionResult> Demo4([FromServices] IHttpClientFactory httpClientFactory)
    {
        var httpClient = httpClientFactory.CreateClient("edge");
        var request = new HttpRequestMessage(HttpMethod.Get, "https://api.dpangzi.com/api/Article");

        var response = await httpClient.SendAsync(request);
        var json = await response.Content.ReadAsStringAsync();
        return Content(json, "application/json");
    }
#endif

    [HttpGet("~/connect/oidc")]
    public IActionResult Login(string fromUrl = "/")
    {
        if (User.Authenticated)
        {
            return Redirect(string.IsNullOrWhiteSpace(fromUrl) ? "/" : fromUrl);
        }

        return Challenge(
            new AuthenticationProperties { RedirectUri = fromUrl },
            OpenIddictClientAspNetCoreDefaults.AuthenticationScheme
        );
        //return View(model: fromUrl);
    }

    [Route("markdown-guide.html")]
    public async Task<IActionResult> Markdown(
        [FromServices] IHttpClientFactory httpClientFactory,
        string version = ""
    )
    {
        ViewBag.Menu = MenuItem.Markdown;
        this.SetTitle("Markdown 语法示例");

        var client = httpClientFactory.CreateClient("edge");

        var markdown = await fusionCache.GetOrSetAsync<string>(
            "markdown-guide:content",
            async (_, cancellationToken) =>
            {
                var request = new HttpRequestMessage(
                    HttpMethod.Get,
                    "https://cdn.dpangzi.com/markdown-guide.md"
                );
                var response = await client.SendAsync(request, cancellationToken);
                return await response.Content.ReadAsStringAsync(cancellationToken);
            },
            options => options.SetDuration(TimeSpan.FromDays(1))
        );
        return View(model: markdown);
    }

    [Route("act/{id}")]
    public async Task<IActionResult> Activity(
        [FromServices] IDynamicPageService dynamicPageService,
        string id = ""
    )
    {
        var cache = await fusionCache.TryGetAsync<ActivityModel>(CacheKey.DynamicPageKey(id));
        if (cache.HasValue)
        {
            Response.ContentType = cache.Value.ContentType;
            return View(model: cache.Value.Content);
        }

        var page = await dynamicPageService.FindAsync(id);
        if (page == null)
        {
            return NotFound();
        }

        var content = page.Content ?? "";

        if (page.ContentType == PageContentType.Html)
        {
            var htmlContext = BrowsingContext.New(Configuration.Default);
            var document = await htmlContext.OpenAsync(x => x.Content(content));
            if (page.Styles.Count > 0)
            {
                foreach (var item in page.Styles)
                {
                    var link = document.CreateElement("link");
                    link.SetAttribute("href", Url.Action("Activity", new { id = item.Name }));
                    link.SetAttribute("rel", "stylesheet");
                    document.Head?.Append(link);
                }
            }

            if (page.Scripts.Count > 0)
            {
                foreach (var item in page.Scripts)
                {
                    var script = document.CreateElement("script");
                    script.SetAttribute("src", Url.Action("Activity", new { id = item.Name }));
                    document.Body?.Append(script);
                }
            }

            await using var writer = new StringWriter();
            document.ToHtml(writer, new PrettyMarkupFormatter());
            content = writer.ToString();
        }

        var contentType = (page.ContentType ?? PageContentType.Html).GetDescription();
        Response.ContentType = contentType;

        var cacheValue = new ActivityModel(content, contentType);
        await fusionCache.SetAsync(CacheKey.DynamicPageKey(id), cacheValue, TimeSpan.FromDays(30));

        return View(model: content);
    }

    public async Task<IActionResult> GroupBarrages(
        [FromServices] IBarrageService barrageService,
        string group
    )
    {
        var list = await barrageService.GetGroupBarragesAsync(group);
        return Json(list);
    }

    public async Task<IActionResult> Wallpaper(bool clear = false)
    {
        if (clear)
        {
            await bingWallpaper.ClearCacheAsync();
        }

        var data = await bingWallpaper.GetRandomWallpaperAsync();
        return Json(data);
    }

    public async Task<IActionResult> TodayWallpaper(bool clear = false)
    {
        if (clear)
        {
            await bingWallpaper.ClearCacheAsync();
        }

        var data = await bingWallpaper.GetTodayWallpapersAsync();
        return Json(data);
    }

    [Route("friends.html")]
    public async Task<IActionResult> Friends([FromServices] IAppOptionService service)
    {
        this.SetTitle("友情链接");
        ViewBag.Menu = MenuItem.Friends;
        var list = await service.GetFriendsAsync();
        return View(list);
    }

    [Route("feed.rss")]
    public async Task<IActionResult> Rss([FromServices] IArticleService articleService)
    {
        var feed = new SyndicationFeed(
            "叫我阿胖",
            "追赶大佬脚步的阿胖",
            new Uri("https://core.dpangzi.com/feed.rss"),
            "feed.rss",
            DateTime.Now
        )
        {
            ImageUrl = new Uri("https://cdn.dpangzi.com/logo.png"),
            Copyright = new TextSyndicationContent($"© {DateTime.Now.Year} 叫我阿胖"),
            Language = "zh-Hans",
        };

        var articles = await articleService.GetLatestAsync(50);
        feed.Items = articles
            .Select(x =>
            {
                var content = new TextSyndicationContent(x.Introduction);
                var addr = Url.Action(
                    "Read",
                    "Article",
                    new { id = x.Id },
                    HttpContext.Request.Scheme
                );
                var uri = new Uri(addr!);
                return new SyndicationItem(x.Title, content, uri, x.Id, x.CreateTime)
                {
                    Authors = { new SyndicationPerson(x.Author.Name) },
                    LastUpdatedTime = x.LastUpdateTime,
                };
            })
            .ToList();

        var settings = new XmlWriterSettings
        {
            Encoding = Encoding.UTF8,
            NewLineHandling = NewLineHandling.Entitize,
            NewLineOnAttributes = true,
            Indent = true,
            Async = true,
        };

        using var stream = new MemoryStream();
        await using var xmlWriter = XmlWriter.Create(stream, settings);
        var rssFormatter = new Rss20FeedFormatter(feed, false);
        rssFormatter.WriteTo(xmlWriter);
        await xmlWriter.FlushAsync();
        return File(stream.ToArray(), "text/xml; charset=utf-8"); //application/rss+xml
    }

    [HttpGet("sitemap")]
    public IActionResult Sitemap()
    {
        var host = configuration.GetSection("upyun")["Host"];
        if (string.IsNullOrEmpty(host))
        {
            return NotFound();
        }

        var baseUri = new Uri(host);
        var uri = new Uri(baseUri, "/sitemap/sitemap.xml");
        return Redirect(uri.ToString());
    }

    [HttpGet, Route("blacklist.html")]
    public async Task<IActionResult> GetBlacklist([FromServices] IBlockService blockService)
    {
        var blockAccessThreshold = configuration.GetValue("BlockAccessThreshold", 0);
        var blocks = await blockService.GetBlocksAsync(blockAccessThreshold);
        return View(blocks);
    }

    [HttpGet, Route("albums.html")]
    public async Task<IActionResult> GetAlbums(
        [FromServices] IPictureRecordService pictureRecordService
    )
    {
        this.SetTitle("我的相册");
        var pageMetaPage = new VmPageMetadata
        {
            Description = "发现美好瞬间,分享生活点滴",
            Keywords = ["相册", "我的相册"],
            Relations = ["Home", "GetAlbums"],
        };
        ViewBag.Menu = MenuItem.Albums;
        ViewData["PageMetadata"] = pageMetaPage;
        var albums = await pictureRecordService.GetPagesAsync([], null);
        return View(albums);
    }

    [HttpGet, Route("pages/albums")]
    public async Task<IActionResult> GetPageAlbums(
        [FromServices] IPictureRecordService pictureRecordService,
        int pageIndex,
        int pageSize
    )
    {
        var albums = await pictureRecordService.GetPagesAsync([], null, pageIndex, pageSize);
        return Json(albums.ToPagedListWarp());
    }

    [HttpGet, Route("dialog-demo.html")]
    public IActionResult DialogDemo()
    {
        this.SetTitle("Dialog 测试演示");
        ViewBag.Menu = MenuItem.Home;
        return View();
    }

    [HttpGet, Route("robots.txt")]
    public async Task<IActionResult> Robots([FromServices] IAppOptionService service)
    {
        var content = await service.GetRobotsAsync();
        return Content(content, "text/plain; charset=utf-8");
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

这是一个ASP.NET Core MVC应用程序中的 HomeController 控制器类,负责处理网站首页相关的各种功能。让我详细解释这个代码的主要功能:

控制器基本信息

使用了C# 12的主构造函数语法,注入了三个依赖服务:

  • IBingWallpaper bingWallpaper - 必应壁纸服务
  • IConfiguration configuration - 配置服务
  • IFusionCache fusionCache - 缓存服务

主要功能模块

1. 首页和新闻相关

  • Index() - 网站首页,显示缓存的首页数据
  • News() - 新闻页面,支持两种模式(页面视图/纯文本内容)
  • TodayNews() - 今日新闻的部分视图
  • SystemNotifications() - 系统通知的部分视图

2. 身份验证

  • Login() - 使用OpenIddict进行OAuth登录,支持重定向到指定URL

3. 内容展示

  • Markdown() - Markdown语法示例页面,从CDN获取内容并缓存
  • Activity() - 动态页面展示,支持HTML/CSS/JS的动态注入和缓存
  • Friends() - 友情链接页面

4. 壁纸功能

  • Wallpaper() - 获取随机壁纸,支持清除缓存
  • TodayWallpaper() - 获取今日壁纸

5. RSS和站点地图

  • Rss() - 生成RSS订阅源,包含最新50篇文章
  • Sitemap() - 重定向到网站地图
  • Robots() - 返回robots.txt文件内容

6. 其他功能

  • GroupBarrages() - 获取群组弹幕数据
  • GetBlacklist() - 显示黑名单页面
  • GetAlbums() / GetPageAlbums() - 相册功能,支持分页
  • Date() - 日期时间页面
  • DialogDemo() - 对话框演示页面

7. 调试功能(仅在DEBUG模式下可用)

  • Demo() - 返回JSON测试数据
  • Demo2() - 测试异常处理
  • Demo3() - 测试SignalR消息推送
  • LayDemo() - 测试页面
  • Demo4() - 测试HTTP客户端

技术特点

  1. 缓存策略 - 大量使用FusionCache进行数据缓存,提高性能
  2. 依赖注入 - 通过[FromServices]特性按需注入服务
  3. 路由配置 - 使用[Route]特性定义友好的URL
  4. 异步编程 - 所有IO操作都使用async/await模式
  5. SEO优化 - 支持sitemap、robots.txt、RSS等SEO功能
  6. 内容类型支持 - 支持HTML、JSON、XML、纯文本等多种响应格式

这个控制器是一个典型的现代ASP.NET Core应用程序的首页控制器,集成了内容管理、用户认证、缓存优化、SEO支持等多种功能。

评论加载中...