网站首页 网站源码
using System.Net.Http;
using System.Net.Http.Json;
using System.ServiceModel.Syndication;
using System.Xml;
using AngleSharp;
using AngleSharp.Html;
using Dpz.Core.Authenticator;
using Dpz.Core.EnumLibrary;
using Dpz.Core.Service.V4.Services;
using Dpz.Core.Web.Cache;
using Dpz.Core.Web.Library.Api;
using Dpz.Core.Web.Library.Hub;
using Dpz.Core.Web.Models;
using Microsoft.AspNetCore.SignalR;
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);
}
[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");
return Content("");
}
public async Task<IActionResult> Demo3([FromServices] IHubContext<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]
public async Task<IActionResult> Login(string fromUrl = "/")
{
if (await HttpContext.GetUserInfo() != null)
{
return Redirect("/");
}
return View(model: fromUrl);
}
[CacheOutput(ServerTimeSpan = ExpirationTime.Month), 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");
if (!string.IsNullOrEmpty(version))
{
var request = new HttpRequestMessage(
HttpMethod.Get,
"https://cdn.dpangzi.com/spec.json"
);
var response = await client.SendAsync(request);
var list = await response.Content.ReadFromJsonAsync<List<CommonMarkExample>>();
return View(viewName: "CommonMark", model: list);
}
{
var request = new HttpRequestMessage(
HttpMethod.Get,
"https://cdn.dpangzi.com/markdown-guide.md"
);
var response = await client.SendAsync(request);
var markdown = await response.Content.ReadAsStringAsync();
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);
}
[Route("timeline")]
[HttpGet]
public async Task<IActionResult> Timeline([FromServices] ITimelineService timelineService)
{
ViewBag.Menu = MenuItem.Timeline;
this.SetTitle("时间轴");
var list = await timelineService.GetTimelinesAsync("pengqian");
return View(list);
}
[Route("{account}/timeline.html")]
public async Task<IActionResult> Timeline2(
[FromServices] ITimelineService timelineService,
string account
)
{
ViewBag.Menu = MenuItem.Timeline;
this.SetTitle($"{account} - 时间轴");
var list = await timelineService.GetTimelinesAsync(account);
return View("Timeline", 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
}
/// <summary>
/// 绑定双因素验证
/// </summary>
/// <returns></returns>
[HttpGet]
[CheckAuthorize]
[Route("two-factor.html")]
public async Task<IActionResult> BindTwoFactor(
[FromServices] IUserTwoFactorService userTwoFactorService,
string fromUrl = "/"
)
{
var userInfo = User.GetStrictIdentity();
var (key, isBind) = await userTwoFactorService.GetKeyAsync(userInfo.Id);
if (isBind)
{
return Redirect(fromUrl);
}
var twoFactorAuthenticator = new TwoFactorAuthenticator();
var setupInfo = twoFactorAuthenticator.GenerateSetupCode(
issuer: "叫我阿胖",
accountTitleNoSpaces: userInfo.Id,
accountSecretKey: key,
secretIsBase32: false
);
TempData["FromUrl"] = fromUrl;
return View(setupInfo);
}
[ValidateAntiForgeryToken]
[CheckAuthorize]
[HttpPost]
[Route("handel-bind-two-factor")]
public async Task<IActionResult> HandleBindTwoFactor(
[FromServices] IUserTwoFactorService userTwoFactorService,
string pinCode,
string fromUrl = "/"
)
{
var userInfo = User.GetStrictIdentity();
var (key, isBind) = await userTwoFactorService.GetKeyAsync(userInfo.Id);
if (isBind)
{
return Redirect(fromUrl);
}
var twoFactorAuthenticator = new TwoFactorAuthenticator();
var keyBuffer = Encoding.UTF8.GetBytes(key);
var keyBase32 = Base32Encoding.ToString(keyBuffer);
var twoFactorResult = twoFactorAuthenticator.ValidateTwoFactorPIN(keyBase32, pinCode, true);
if (!twoFactorResult)
{
TempData["Msg"] = "PIN码验证失败";
return RedirectToAction("BindTwoFactor", new { fromUrl });
}
await userTwoFactorService.BindAsync(userInfo.Id);
return Redirect(fromUrl);
}
[HttpPost]
[CheckAuthorize]
[Route("unbind-two-factor")]
public async Task<IActionResult> UnbindTwoFactor(
[FromServices] IUserTwoFactorService userTwoFactorService,
string pinCode
)
{
var userInfo = User.GetStrictIdentity();
var (key, isBind) = await userTwoFactorService.GetKeyAsync(userInfo.Id);
if (!isBind)
{
return Json(new ResultInfo("未绑定双因素验证"));
}
var twoFactorAuthenticator = new TwoFactorAuthenticator();
var keyBuffer = Encoding.UTF8.GetBytes(key);
var keyBase32 = Base32Encoding.ToString(keyBuffer);
var twoFactorResult = twoFactorAuthenticator.ValidateTwoFactorPIN(keyBase32, pinCode, true);
if (!twoFactorResult)
{
return Json(new ResultInfo("PIN码验证错误!"));
}
await userTwoFactorService.UnbindAsync(userInfo.Id);
return Json(new ResultInfo(true));
}
[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("time")]
public IActionResult GetTime()
{
Response.Headers.TryAdd("x-server-name", Environment.MachineName);
return Content(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
[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);
}
}
上述代码是一个 ASP.NET Core MVC 控制器类 HomeController
的实现,主要用于处理与网站首页及相关功能的请求。以下是对代码中各个部分的功能的详细解释:
public HomeController(
IBingWallpaper bingWallpaper,
IConfiguration configuration,
IHybridCachingProvider cachingProvider
)
IBingWallpaper
(用于获取 Bing 壁纸)、IConfiguration
(用于访问应用程序配置)、IHybridCachingProvider
(用于缓存服务)。public async Task<IActionResult> Index([FromServices] IHomeCacheService cacheService)
IHomeCacheService
获取缓存数据并返回视图。[Route(("news.html"))]
public async Task<IActionResult> News([FromServices] IHomeCacheService cacheService, string mode = "")
mode
参数为 "content",则返回新闻标题的列表;否则返回完整的新闻视图。public async Task<IActionResult> TodayNews([FromServices] IHomeCacheService cacheService)
[HttpGet, Route("datetime")]
public async Task<IActionResult> Date()
在 #if DEBUG
指令下,包含了一些调试用的方法,如 Demo
, Demo2
, Demo3
, Demo4
,用于测试和调试目的。
[HttpGet]
public async Task<IActionResult> Login(string fromUrl = "/")
[CacheOutput(ServerTimeSpan = ExpirationTime.Month), Route("markdown-guide.html")]
public async Task<IActionResult> Markdown([FromServices] IHttpClientFactory httpClientFactory, string version = "")
[Route("act/{id}")]
public async Task<IActionResult> Activity([FromServices] IDynamicPageService dynamicPageService, string id = "")
[Route("timeline")]
public async Task<IActionResult> Timeline([FromServices] ITimelineService timelineService)
public async Task<IActionResult> Wallpaper(bool clear = false)
[Route("friends.html")]
public async Task<IActionResult> Friends([FromServices] IAppOptionService service)
[Route("feed.rss")]
public async Task<IActionResult> Rss([FromServices] IArticleService articleService)
整体来看,HomeController
负责处理与网站首页及相关功能的请求,包括新闻、动态页面、时间轴、壁纸、友情链接、RSS 订阅等。它利用依赖注入的方式获取所需的服务,并通过异步方法处理请求,返回相应的视图或数据。