move project
This commit is contained in:
241
Controllers/HomeController.cs
Normal file
241
Controllers/HomeController.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Db.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using TagVid.Helpers;
|
||||
using TagVid.Models;
|
||||
|
||||
namespace TagVid.Controllers;
|
||||
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
private readonly AdapterContext _adapterContext;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger, AdapterContext adapterContext)
|
||||
{
|
||||
_logger = logger;
|
||||
_adapterContext = adapterContext;
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Index()
|
||||
{
|
||||
// check if the video path was set
|
||||
var pathSettings = await _adapterContext.GetSettingAsync<string>(SettingName.VideoPath);
|
||||
if (string.IsNullOrEmpty(pathSettings))
|
||||
{
|
||||
_logger.LogWarning("Video path is not set. Please configure the video path in settings.");
|
||||
return RedirectToAction("Settings", "Home");
|
||||
}
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Route("Home/Index/{id}")]
|
||||
public async Task<IActionResult> Index(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Settings()
|
||||
{
|
||||
var vm = new SettingsViewModel
|
||||
{
|
||||
VideoPath = await _adapterContext.GetSettingAsync<string>(SettingName.VideoPath)
|
||||
};
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Settings(SettingsViewModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Validate the video path
|
||||
if (string.IsNullOrWhiteSpace(model.VideoPath))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.VideoPath), "Video path cannot be empty.");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Check if the path exists
|
||||
if (!Directory.Exists(model.VideoPath))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.VideoPath), "The specified video path does not exist.");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Check if the path is a directory
|
||||
if (!System.IO.File.GetAttributes(model.VideoPath).HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
ModelState.AddModelError(nameof(model.VideoPath), "The specified path must be a directory.");
|
||||
return View(model);
|
||||
}
|
||||
|
||||
// Save settings to the database
|
||||
await _adapterContext.SetSettingAsync(SettingName.VideoPath, model.VideoPath);
|
||||
return View(model);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Upload(IFormFile videoFile)
|
||||
{
|
||||
_logger.LogInformation("Upload called with file: {FileName}", videoFile?.Name);
|
||||
if (videoFile == null || videoFile.Length == 0)
|
||||
{
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
// Validate the video file
|
||||
// no size limit for now, but could be added later
|
||||
|
||||
if (!videoFile.ContentType.StartsWith("video/"))
|
||||
{
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
// Save the video file to the configured path
|
||||
var videoPath = await _adapterContext.GetSettingAsync<string>(SettingName.VideoPath);
|
||||
var ext = Path.GetExtension(videoFile.FileName);
|
||||
|
||||
if (string.IsNullOrEmpty(videoPath) || !Directory.Exists(videoPath))
|
||||
{
|
||||
return RedirectToAction("Settings");
|
||||
}
|
||||
|
||||
// asp.net docu suggests not using .FileName due to security reasons
|
||||
var id = Guid.NewGuid().ToString();
|
||||
|
||||
var filePath = Path.Combine(videoPath, $"{id}{ext}");
|
||||
using (var stream = new FileStream(filePath, FileMode.Create))
|
||||
{
|
||||
await videoFile.CopyToAsync(stream);
|
||||
}
|
||||
|
||||
var data = await new FFProbeHelper<HomeController>(_logger).GetVideoMetadataAsync(filePath);
|
||||
|
||||
var video = new Video
|
||||
{
|
||||
Id = id,
|
||||
Duration = data?.Duration ?? TimeSpan.Zero,
|
||||
Width = data?.Width ?? 0,
|
||||
Height = data?.Height ?? 0,
|
||||
Extension = ext,
|
||||
VideoTags = []
|
||||
};
|
||||
|
||||
_adapterContext.Videos.Add(video);
|
||||
await _adapterContext.SaveChangesAsync();
|
||||
|
||||
// redirect to the video details page
|
||||
return RedirectToAction("Details", "Home", new { id = video.Id });
|
||||
}
|
||||
|
||||
public async Task<IActionResult> Details(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var video = await _adapterContext.Videos
|
||||
.Include(v => v.VideoTags)
|
||||
.ThenInclude(vt => vt.Tag)
|
||||
.FirstOrDefaultAsync(v => v.Id == id);
|
||||
|
||||
if (video == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var vm = new DetailsViewModel
|
||||
{
|
||||
VideoId = id,
|
||||
Title = video?.Title ?? string.Empty,
|
||||
Tags = video?.VideoTags.Select(vt => vt.Tag.Name).ToList() ?? []
|
||||
};
|
||||
|
||||
return View(vm);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Details(DetailsViewModel videoModel)
|
||||
{
|
||||
if (string.IsNullOrEmpty(videoModel.VideoId))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
var existingVideo = await _adapterContext.Videos
|
||||
.Include(v => v.VideoTags)
|
||||
.ThenInclude(vt => vt.Tag)
|
||||
.FirstOrDefaultAsync(v => v.Id == videoModel.VideoId);
|
||||
|
||||
if (existingVideo == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
|
||||
// Update video title
|
||||
existingVideo.Title = videoModel.Title;
|
||||
// Update tags
|
||||
existingVideo.VideoTags.Clear();
|
||||
foreach (var tagName in videoModel.Tags)
|
||||
{
|
||||
var tag = await _adapterContext.Tags.FirstOrDefaultAsync(t => t.Name == tagName);
|
||||
if (tag == null)
|
||||
{
|
||||
tag = new Tag { Name = tagName };
|
||||
_adapterContext.Tags.Add(tag);
|
||||
}
|
||||
existingVideo.VideoTags.Add(new VideoTag { Video = existingVideo, Tag = tag });
|
||||
}
|
||||
_adapterContext.Videos.Update(existingVideo);
|
||||
await _adapterContext.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction("Details", new { id = videoModel.VideoId });
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public async Task<IActionResult> Delete(string id)
|
||||
{
|
||||
if (string.IsNullOrEmpty(id))
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
var video = await _adapterContext.Videos.FindAsync(id);
|
||||
if (video == null)
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
// Delete the video file from the file system
|
||||
var videoPath = await _adapterContext.GetSettingAsync<string>(SettingName.VideoPath);
|
||||
if (!string.IsNullOrEmpty(videoPath))
|
||||
{
|
||||
var filePath = Path.Combine(videoPath, $"{video.Id}{video.Extension}");
|
||||
if (System.IO.File.Exists(filePath))
|
||||
{
|
||||
System.IO.File.Delete(filePath);
|
||||
}
|
||||
}
|
||||
// Remove the video from the database
|
||||
_adapterContext.Videos.Remove(video);
|
||||
await _adapterContext.SaveChangesAsync();
|
||||
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
public IActionResult Error()
|
||||
{
|
||||
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user