Files
ScratchingPost/Controllers/ApiController.cs
T

166 lines
5.6 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NoticeBoard.Data;
using Ical.Net;
using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes;
namespace NoticeBoard.Controllers;
[Authorize]
public class ApiController : Controller
{
private readonly IWebHostEnvironment _env;
private readonly IConfiguration _config;
private readonly IHttpClientFactory _httpClientFactory;
public ApiController(IWebHostEnvironment env, IConfiguration config, IHttpClientFactory httpClientFactory)
{
_env = env;
_config = config;
_httpClientFactory = httpClientFactory;
}
[HttpPost]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest(new { error = "No file provided." });
var maxSize = _config.GetValue<int>("MaxUploadSizeMB", 20) * 1024 * 1024;
if (file.Length > maxSize)
return BadRequest(new { error = $"File too large. Maximum {maxSize / 1024 / 1024}MB." });
var allowedExts = new[] { ".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico" };
var ext = Path.GetExtension(file.FileName).ToLower();
if (!allowedExts.Contains(ext))
return BadRequest(new { error = "File type not allowed. Use: " + string.Join(", ", allowedExts) });
var uploadsPath = Path.Combine(_env.WebRootPath, "uploads");
if (!Directory.Exists(uploadsPath))
Directory.CreateDirectory(uploadsPath);
var fileName = $"{DateTime.UtcNow:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}{ext}";
var filePath = Path.Combine(uploadsPath, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
return Json(new { location = $"/uploads/{fileName}" });
}
[HttpPost]
public async Task<IActionResult> UploadFile(IFormFile file)
{
if (file == null || file.Length == 0)
return BadRequest(new { error = "No file provided." });
var uploadsPath = Path.Combine(_env.WebRootPath, "uploads");
if (!Directory.Exists(uploadsPath))
Directory.CreateDirectory(uploadsPath);
var ext = Path.GetExtension(file.FileName).ToLower();
var fileName = $"{DateTime.UtcNow:yyyyMMdd_HHmmss}_{Guid.NewGuid():N}{ext}";
var filePath = Path.Combine(uploadsPath, fileName);
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
return Json(new { url = $"/uploads/{fileName}", name = file.FileName, size = file.Length });
}
[HttpGet]
public IActionResult ListUploads()
{
var uploadsPath = Path.Combine(_env.WebRootPath, "uploads");
if (!Directory.Exists(uploadsPath))
return Json(new { files = Array.Empty<object>() });
var imageExts = new[] { ".jpg", ".jpeg", ".png", ".gif", ".webp", ".svg", ".bmp", ".ico" };
var files = Directory.GetFiles(uploadsPath)
.Select(f => new FileInfo(f))
.Where(f => imageExts.Contains(f.Extension.ToLower()))
.OrderByDescending(f => f.CreationTimeUtc)
.Select(f => new
{
title = f.Name,
value = $"/uploads/{f.Name}"
});
return Json(files);
}
[HttpPost]
public IActionResult DeleteUpload([FromBody] DeleteFileRequest request)
{
if (string.IsNullOrEmpty(request?.FileName))
return BadRequest();
var filePath = Path.Combine(_env.WebRootPath, "uploads", Path.GetFileName(request.FileName));
if (System.IO.File.Exists(filePath))
{
System.IO.File.Delete(filePath);
return Ok();
}
return NotFound();
}
[AllowAnonymous]
[HttpGet]
public async Task<IActionResult> ParseIcs(string url)
{
if (string.IsNullOrWhiteSpace(url))
return BadRequest(new { error = "No URL provided." });
try
{
string icsContent;
if (url.StartsWith("/uploads/"))
{
var filePath = Path.Combine(_env.WebRootPath, url.TrimStart('/'));
if (!System.IO.File.Exists(filePath))
return NotFound(new { error = "ICS file not found." });
icsContent = await System.IO.File.ReadAllTextAsync(filePath);
}
else
{
var client = _httpClientFactory.CreateClient();
client.Timeout = TimeSpan.FromSeconds(15);
icsContent = await client.GetStringAsync(url);
}
var calendar = Calendar.Load(icsContent);
var now = DateTime.Now;
var upcoming = calendar.Events
.Where(e => e.DtEnd != null ? e.DtEnd.AsSystemLocal >= now : e.DtStart.AsSystemLocal >= now.AddDays(-1))
.OrderBy(e => e.DtStart.AsSystemLocal)
.Take(20)
.Select(e => new
{
summary = e.Summary,
description = e.Description,
location = e.Location,
start = e.DtStart?.AsSystemLocal.ToString("yyyy-MM-dd HH:mm"),
end = e.DtEnd?.AsSystemLocal.ToString("yyyy-MM-dd HH:mm"),
allDay = e.IsAllDay
});
return Json(new { events = upcoming });
}
catch (Exception ex)
{
return BadRequest(new { error = $"Failed to parse ICS: {ex.Message}" });
}
}
}
public class DeleteFileRequest
{
public string? FileName { get; set; }
}