live-forum/server/webapi/LiveForum/LiveForum.Service/Posts/PostReplyIntervalService.cs
2026-03-24 11:27:37 +08:00

140 lines
4.8 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using FreeSql;
using LiveForum.IService.Posts;
using LiveForum.Model;
using System;
using System.Threading.Tasks;
namespace LiveForum.Service.Posts
{
/// <summary>
/// 发帖/回复时间间隔校验服务实现
/// </summary>
public class PostReplyIntervalService : IPostReplyIntervalService
{
private readonly IBaseRepository<T_PostReplyIntervals> _intervalsRepository;
private readonly IBaseRepository<T_Users> _usersRepository;
private readonly IBaseRepository<T_Posts> _postsRepository;
private readonly IBaseRepository<T_Comments> _commentsRepository;
/// <summary>
/// 默认间隔值未配置时使用0 表示不限制
/// </summary>
private const int DEFAULT_INTERVAL = 0;
/// <summary>
/// 构造函数
/// </summary>
public PostReplyIntervalService(
IBaseRepository<T_PostReplyIntervals> intervalsRepository,
IBaseRepository<T_Users> usersRepository,
IBaseRepository<T_Posts> postsRepository,
IBaseRepository<T_Comments> commentsRepository)
{
_intervalsRepository = intervalsRepository;
_usersRepository = usersRepository;
_postsRepository = postsRepository;
_commentsRepository = commentsRepository;
}
/// <summary>
/// 获取用户的发帖间隔配置(秒)
/// </summary>
public async Task<int> GetPostIntervalAsync(long userId)
{
var user = await _usersRepository.Select
.Where(x => x.Id == userId)
.FirstAsync();
if (user?.CertifiedType == null || user.CertifiedType <= 0)
return DEFAULT_INTERVAL;
var config = await _intervalsRepository.Select
.Where(x => x.CertificationTypeId == user.CertifiedType.Value)
.FirstAsync();
return config?.PostInterval ?? DEFAULT_INTERVAL;
}
/// <summary>
/// 获取用户的回复间隔配置(秒)
/// </summary>
public async Task<int> GetReplyIntervalAsync(long userId)
{
var user = await _usersRepository.Select
.Where(x => x.Id == userId)
.FirstAsync();
if (user?.CertifiedType == null || user.CertifiedType <= 0)
return DEFAULT_INTERVAL;
var config = await _intervalsRepository.Select
.Where(x => x.CertificationTypeId == user.CertifiedType.Value)
.FirstAsync();
return config?.ReplyInterval ?? DEFAULT_INTERVAL;
}
/// <summary>
/// 获取用户最近一次成功发帖时间
/// </summary>
public async Task<DateTime?> GetLastPostTimeAsync(long userId)
{
var lastPost = await _postsRepository.Select
.Where(x => x.UserId == userId && !x.IsDeleted)
.OrderByDescending(x => x.CreatedAt)
.FirstAsync();
return lastPost?.CreatedAt;
}
/// <summary>
/// 获取用户最近一次成功回复时间
/// </summary>
public async Task<DateTime?> GetLastCommentTimeAsync(long userId)
{
var lastComment = await _commentsRepository.Select
.Where(x => x.UserId == userId && !x.IsDeleted)
.OrderByDescending(x => x.CreatedAt)
.FirstAsync();
return lastComment?.CreatedAt;
}
/// <summary>
/// 校验发帖间隔,返回 null 表示通过,否则返回剩余秒数
/// </summary>
public async Task<int?> CheckPostIntervalAsync(long userId)
{
var interval = await GetPostIntervalAsync(userId);
if (interval <= 0) return null; // 不限制
var lastTime = await GetLastPostTimeAsync(userId);
if (lastTime == null) return null; // 从未发帖
var elapsed = (DateTime.Now - lastTime.Value).TotalSeconds;
if (elapsed >= interval) return null; // 已满足间隔
return (int)Math.Ceiling(interval - elapsed); // 返回剩余秒数
}
/// <summary>
/// 校验回复间隔,返回 null 表示通过,否则返回剩余秒数
/// </summary>
public async Task<int?> CheckReplyIntervalAsync(long userId)
{
var interval = await GetReplyIntervalAsync(userId);
if (interval <= 0) return null; // 不限制
var lastTime = await GetLastCommentTimeAsync(userId);
if (lastTime == null) return null; // 从未回复
var elapsed = (DateTime.Now - lastTime.Value).TotalSeconds;
if (elapsed >= interval) return null; // 已满足间隔
return (int)Math.Ceiling(interval - elapsed); // 返回剩余秒数
}
}
}