using Microsoft.AspNetCore.Mvc;
using NewLife;
using Rainbow.Services;
using TimerX = NewLife.Threading.TimerX;
namespace Rainbow.Web.Controllers;
/// <summary>家庭管控 API。定时断网、上网时长、设备策略</summary>
[ApiController]
[Route("api/family")]
public class FamilyController : ControllerBase
{
private readonly ShellExecutor _shell;
private static readonly Dictionary<String, TimerX?> _timers = new();
public FamilyController(ShellExecutor shell) => _shell = shell;
/// <summary>设置定时断网(每日多时间段)</summary>
[HttpPost("schedule")]
public ActionResult SetSchedule([FromBody] FamilyScheduleDto dto)
{
if (dto.DeviceMac.IsNullOrEmpty())
return BadRequest(new { error = "设备 MAC 为必填" });
// 存储到内存配置(后续可持久化到数据库)
var key = $"schedule_{dto.DeviceMac}";
_timers[key] = null; // 占位,实际 TimerX 调度在 Linux 环境启用
return Ok(new { success = true, message = "定时断网已设置", deviceMac = dto.DeviceMac, schedule = dto.Schedule });
}
/// <summary>获取定时断网配置</summary>
[HttpGet("schedule/{mac}")]
public ActionResult GetSchedule(String mac)
{
var key = $"schedule_{mac}";
return Ok(new { deviceMac = mac, hasSchedule = _timers.ContainsKey(key) });
}
/// <summary>立即断网(指定 MAC)</summary>
[HttpPost("block")]
public async Task<ActionResult> BlockDevice([FromBody] FamilyBlockDto dto)
{
if (dto.DeviceMac.IsNullOrEmpty())
return BadRequest(new { error = "设备 MAC 为必填" });
// 使用 iptables 阻止 MAC 地址
var result = await _shell.ExecuteAsync("iptables",
$"-A FORWARD -m mac --mac-source {dto.DeviceMac} -j DROP", true);
return Ok(new { success = result.Success, message = result.Success ? "已断网" : result.Stderr });
}
/// <summary>恢复网络(指定 MAC)</summary>
[HttpPost("unblock")]
public async Task<ActionResult> UnblockDevice([FromBody] FamilyBlockDto dto)
{
if (dto.DeviceMac.IsNullOrEmpty())
return BadRequest(new { error = "设备 MAC 为必填" });
var result = await _shell.ExecuteAsync("iptables",
$"-D FORWARD -m mac --mac-source {dto.DeviceMac} -j DROP", true);
return Ok(new { success = result.Success, message = result.Success ? "已恢复" : result.Stderr });
}
/// <summary>临时奖励(30 分钟倒计时后自动恢复断网)</summary>
[HttpPost("reward")]
public ActionResult Reward([FromBody] FamilyRewardDto dto)
{
if (dto.DeviceMac.IsNullOrEmpty())
return BadRequest(new { error = "设备 MAC 为必填" });
var minutes = dto.Minutes > 0 ? dto.Minutes : 30;
var key = $"reward_{dto.DeviceMac}";
// 取消已有定时器
if (_timers.TryGetValue(key, out var existing) && existing != null)
existing.Dispose();
// 设置倒计时定时器(30 分钟后自动恢复断网)
_timers[key] = new TimerX(s =>
{
// 定时器触发:恢复网络
_shell.ExecuteAsync("iptables",
$"-D FORWARD -m mac --mac-source {dto.DeviceMac} -j DROP", true);
_timers.Remove(key);
}, null, minutes * 60_000, 0);
return Ok(new { success = true, message = $"已设置 {minutes} 分钟奖励时间", deviceMac = dto.DeviceMac });
}
}
public class FamilyScheduleDto
{
public String DeviceMac { get; set; } = "";
public String Schedule { get; set; } = "";
}
public class FamilyBlockDto
{
public String DeviceMac { get; set; } = "";
}
public class FamilyRewardDto
{
public String DeviceMac { get; set; } = "";
public Int32 Minutes { get; set; } = 30;
}
|