mirror of
https://gitee.com/xiarenalofs/squad-rain-ops-mini.git
synced 2026-08-07 22:05:45 +08:00
208 lines
9.6 KiB
C#
208 lines
9.6 KiB
C#
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Http;
|
|
using SqlSugar;
|
|
using RainOpsMini.Helpers;
|
|
using RainOpsMini.Models;
|
|
using RainOpsMini.Services;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System;
|
|
using System.IO;
|
|
using RainOpsMini.Models;
|
|
|
|
namespace RainOpsMini.Apis
|
|
{
|
|
public static class VipApi
|
|
{
|
|
public static void MapVipApis(this IEndpointRouteBuilder app)
|
|
{
|
|
// VIP Management APIs
|
|
app.MapGet("/api/vip", (HttpContext ctx) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "vips.view") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
return Results.Json(VipStorage.GetAll());
|
|
});
|
|
|
|
app.MapPost("/api/vip", (VipMember member, HttpContext ctx) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "vips.add") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
if (string.IsNullOrWhiteSpace(member.SteamId)) return Results.BadRequest(new { error = "SteamID 不能为空" });
|
|
if (VipStorage.GetBySteamId(member.SteamId) != null) return Results.BadRequest(new { error = "该 SteamID 已存在" });
|
|
|
|
// Validate Group
|
|
if (member.Group != "VIP_RainOpsMini" && member.Group != "SVIP_RainOpsMini")
|
|
{
|
|
return Results.BadRequest(new { error = "无效的会员组" });
|
|
}
|
|
|
|
member.CreatedAt = DateTime.Now;
|
|
VipStorage.Add(member);
|
|
return Results.Ok();
|
|
});
|
|
|
|
app.MapPut("/api/vip", (VipMember member, HttpContext ctx) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "vips.edit") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
if (string.IsNullOrWhiteSpace(member.SteamId)) return Results.BadRequest(new { error = "SteamID 不能为空" });
|
|
|
|
var existing = VipStorage.GetBySteamId(member.SteamId);
|
|
if (existing == null) return Results.NotFound(new { error = "会员不存在" });
|
|
|
|
// Validate Group
|
|
if (member.Group != "VIP_RainOpsMini" && member.Group != "SVIP_RainOpsMini")
|
|
{
|
|
return Results.BadRequest(new { error = "无效的会员组" });
|
|
}
|
|
|
|
VipStorage.Update(member);
|
|
return Results.Ok();
|
|
});
|
|
|
|
app.MapDelete("/api/vip/{steamId}", (string steamId, HttpContext ctx) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "vips.delete") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
VipStorage.Remove(steamId);
|
|
return Results.Ok();
|
|
});
|
|
|
|
app.MapPost("/api/vip/sync", (HttpContext ctx) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "vips.edit") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
try
|
|
{
|
|
string cfgPath = Path.Combine(Directory.GetCurrentDirectory(), "SquadGame", "ServerConfig", "Admins.cfg");
|
|
// Ensure directory exists just in case
|
|
Directory.CreateDirectory(Path.GetDirectoryName(cfgPath)!);
|
|
|
|
if (!File.Exists(cfgPath))
|
|
{
|
|
File.WriteAllText(cfgPath, "// Created by RainOpsMini\n");
|
|
}
|
|
|
|
VipStorage.SyncToAdminConfig(cfgPath);
|
|
return Results.Ok();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return Results.BadRequest(new { error = "写入配置文件失败: " + ex.Message });
|
|
}
|
|
});
|
|
|
|
// Points Management APIs
|
|
app.MapGet("/api/points", async (HttpContext ctx, int? page, int? pageSize, string? search) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "points.view") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
int p = page ?? 1;
|
|
int ps = pageSize ?? 20;
|
|
|
|
using var db = DbHelper.GetInstance();
|
|
var query = db.Queryable<UserIntegral>();
|
|
|
|
if (!string.IsNullOrWhiteSpace(search))
|
|
{
|
|
query = query.Where(u => u.SteamId.Contains(search));
|
|
}
|
|
|
|
int total = await query.CountAsync();
|
|
var list = await query.OrderBy(u => u.LastUpdated, OrderByType.Desc)
|
|
.ToPageListAsync(p, ps);
|
|
|
|
return Results.Ok(new { total, list });
|
|
});
|
|
|
|
app.MapPost("/api/points/update", async (HttpContext ctx, UserIntegral req) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "points.edit") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
if (string.IsNullOrWhiteSpace(req.SteamId)) return Results.BadRequest(new { error = "SteamID 不能为空" });
|
|
|
|
using var db = DbHelper.GetInstance();
|
|
var existing = await db.Queryable<UserIntegral>().FirstAsync(u => u.SteamId == req.SteamId);
|
|
|
|
if (existing == null)
|
|
{
|
|
req.LastUpdated = DateTime.UtcNow;
|
|
await db.Insertable(req).ExecuteCommandAsync();
|
|
}
|
|
else
|
|
{
|
|
existing.Points = req.Points;
|
|
existing.LastUpdated = DateTime.UtcNow;
|
|
await db.Updateable(existing).ExecuteCommandAsync();
|
|
}
|
|
|
|
return Results.Ok();
|
|
});
|
|
|
|
// CDK Management APIs
|
|
app.MapPost("/api/cdk/generate", async (HttpContext ctx, GenerateCdkRequest req) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "cdks.add") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
if (req.Count <= 0 || req.Count > 100) return Results.BadRequest(new { error = "数量必须在 1-100 之间" });
|
|
if (req.DurationDays <= 0) return Results.BadRequest(new { error = "时长必须大于 0" });
|
|
if (req.Type != "VIP" && req.Type != "SVIP") return Results.BadRequest(new { error = "类型必须是 VIP 或 SVIP" });
|
|
|
|
string creator = ctx.User.Identity?.Name ?? "Admin";
|
|
var list = await CdkService.GenerateCdksAsync(req.Type, req.DurationDays, req.Count, req.Reason, creator);
|
|
|
|
return Results.Ok(new { count = list.Count, keys = list.Select(c => c.Code).ToList() });
|
|
});
|
|
|
|
app.MapGet("/api/cdk/list", async (HttpContext ctx, int? page, int? pageSize, string? type, string? status, string? search) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "cdks.view") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
int p = page ?? 1;
|
|
int ps = pageSize ?? 20;
|
|
|
|
using var db = DbHelper.GetInstance();
|
|
var query = db.Queryable<CdkInfo>();
|
|
|
|
if (!string.IsNullOrWhiteSpace(type)) query = query.Where(c => c.Type == type);
|
|
if (!string.IsNullOrWhiteSpace(status)) query = query.Where(c => c.Status == status);
|
|
if (!string.IsNullOrWhiteSpace(search))
|
|
{
|
|
query = query.Where(c => c.Code.Contains(search) || c.Reason.Contains(search) || c.Creator.Contains(search) || c.RedeemedBy.Contains(search));
|
|
}
|
|
|
|
int total = await query.CountAsync();
|
|
var list = await query.OrderBy(c => c.CreatedAt, OrderByType.Desc)
|
|
.ToPageListAsync(p, ps);
|
|
|
|
return Results.Ok(new { total, list });
|
|
});
|
|
|
|
app.MapPost("/api/cdk/delete", async (DeleteCdkRequest req, HttpContext ctx) =>
|
|
{
|
|
if (!ctx.User.HasClaim("Permission", "cdks.delete") && !ctx.User.HasClaim("Permission", "all") && ctx.User.FindFirst("IsSuperAdmin")?.Value != "true") return Results.Unauthorized();
|
|
|
|
if (req.Codes == null || req.Codes.Count == 0) return Results.BadRequest(new { error = "No codes provided" });
|
|
|
|
using var db = DbHelper.GetInstance();
|
|
await db.Deleteable<CdkInfo>().Where(c => req.Codes.Contains(c.Code)).ExecuteCommandAsync();
|
|
|
|
return Results.Ok();
|
|
});
|
|
|
|
app.MapPost("/api/cdk/redeem", async (RedeemCdkRequest req) =>
|
|
{
|
|
// Public endpoint, no auth required (or maybe simple rate limit?)
|
|
var result = await CdkService.RedeemCdkAsync(req.Code, req.SteamId);
|
|
if (result.success)
|
|
{
|
|
return Results.Ok(new { message = result.message });
|
|
}
|
|
else
|
|
{
|
|
return Results.BadRequest(new { error = result.message });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|