293 lines
9.9 KiB
C#
293 lines
9.9 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using GreenHome.Application;
|
|
|
|
namespace GreenHome.Api.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/[controller]")]
|
|
public class DevicePostsController : ControllerBase
|
|
{
|
|
private readonly IDevicePostService _postService;
|
|
private readonly ILogger<DevicePostsController> _logger;
|
|
private readonly IWebHostEnvironment _environment;
|
|
|
|
public DevicePostsController(
|
|
IDevicePostService postService,
|
|
ILogger<DevicePostsController> logger,
|
|
IWebHostEnvironment environment)
|
|
{
|
|
_postService = postService;
|
|
_logger = logger;
|
|
_environment = environment;
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت پستهای گروه مجازی دستگاه (تایملاین)
|
|
/// </summary>
|
|
[HttpGet]
|
|
public async Task<ActionResult<PagedResult<DevicePostDto>>> GetPosts(
|
|
[FromQuery] int deviceId,
|
|
[FromQuery] int? authorUserId,
|
|
[FromQuery] int page = 1,
|
|
[FromQuery] int pageSize = 20,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var filter = new DevicePostFilter
|
|
{
|
|
DeviceId = deviceId,
|
|
AuthorUserId = authorUserId,
|
|
Page = page,
|
|
PageSize = pageSize
|
|
};
|
|
|
|
var result = await _postService.GetPostsAsync(filter, cancellationToken);
|
|
return Ok(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// دریافت جزئیات یک پست
|
|
/// </summary>
|
|
[HttpGet("{id}")]
|
|
public async Task<ActionResult<DevicePostDto>> GetPostById(int id, CancellationToken cancellationToken)
|
|
{
|
|
var result = await _postService.GetPostByIdAsync(id, cancellationToken);
|
|
if (result == null)
|
|
{
|
|
return NotFound(new { error = $"پست با شناسه {id} یافت نشد" });
|
|
}
|
|
return Ok(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// ایجاد پست جدید در گروه مجازی
|
|
/// </summary>
|
|
[HttpPost]
|
|
public async Task<ActionResult<int>> CreatePost(
|
|
CreateDevicePostRequest request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var id = await _postService.CreatePostAsync(request, cancellationToken);
|
|
return Ok(new { id, message = "پست با موفقیت ایجاد شد" });
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
return Unauthorized(new { error = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// ویرایش پست
|
|
/// </summary>
|
|
[HttpPut]
|
|
public async Task<ActionResult> UpdatePost(
|
|
UpdateDevicePostRequest request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
await _postService.UpdatePostAsync(request, cancellationToken);
|
|
return Ok(new { message = "پست با موفقیت ویرایش شد" });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return NotFound(new { error = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// حذف پست
|
|
/// </summary>
|
|
[HttpDelete("{id}")]
|
|
public async Task<ActionResult> DeletePost(int id, CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
await _postService.DeletePostAsync(id, cancellationToken);
|
|
return Ok(new { message = "پست با موفقیت حذف شد" });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return NotFound(new { error = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// آپلود تصویر برای پست
|
|
/// </summary>
|
|
[HttpPost("{postId}/images")]
|
|
[Consumes("multipart/form-data")]
|
|
public async Task<ActionResult<int>> UploadImage(
|
|
int postId,
|
|
[FromForm] IFormFile file,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
if (file == null || file.Length == 0)
|
|
{
|
|
return BadRequest(new { error = "فایل انتخاب نشده است" });
|
|
}
|
|
|
|
// Validate file type
|
|
var allowedTypes = new[] { "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp" };
|
|
if (!allowedTypes.Contains(file.ContentType.ToLower()))
|
|
{
|
|
return BadRequest(new { error = "فقط فایلهای تصویری مجاز هستند" });
|
|
}
|
|
|
|
// Validate file size (max 5MB)
|
|
if (file.Length > 5 * 1024 * 1024)
|
|
{
|
|
return BadRequest(new { error = "حجم فایل نباید بیشتر از 5 مگابایت باشد" });
|
|
}
|
|
|
|
// Create upload directory
|
|
var uploadsFolder = Path.Combine(_environment.WebRootPath ?? "wwwroot", "uploads", "posts");
|
|
Directory.CreateDirectory(uploadsFolder);
|
|
|
|
// Generate unique filename
|
|
var fileName = $"{Guid.NewGuid()}_{Path.GetFileName(file.FileName)}";
|
|
var filePath = Path.Combine(uploadsFolder, fileName);
|
|
|
|
// Save file
|
|
using (var stream = new FileStream(filePath, FileMode.Create))
|
|
{
|
|
await file.CopyToAsync(stream, cancellationToken);
|
|
}
|
|
|
|
// Save to database
|
|
var relativePath = $"/uploads/posts/{fileName}";
|
|
var imageId = await _postService.AddImageToPostAsync(
|
|
postId,
|
|
file.FileName,
|
|
relativePath,
|
|
file.ContentType,
|
|
file.Length,
|
|
cancellationToken);
|
|
|
|
_logger.LogInformation("Image uploaded for post {PostId}: {ImageId}", postId, imageId);
|
|
|
|
return Ok(new { imageId, filePath = relativePath, message = "تصویر با موفقیت آپلود شد" });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return NotFound(new { error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error uploading image for post {PostId}", postId);
|
|
return StatusCode(500, new { error = "خطا در آپلود تصویر" });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// حذف تصویر از پست
|
|
/// </summary>
|
|
[HttpDelete("images/{imageId}")]
|
|
public async Task<ActionResult> DeleteImage(int imageId, CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
await _postService.DeleteImageAsync(imageId, cancellationToken);
|
|
return Ok(new { message = "تصویر با موفقیت حذف شد" });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return NotFound(new { error = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// بررسی دسترسی کاربر به دستگاه
|
|
/// </summary>
|
|
[HttpGet("access/{userId}/{deviceId}")]
|
|
public async Task<ActionResult<bool>> CheckAccess(int userId, int deviceId, CancellationToken cancellationToken)
|
|
{
|
|
var hasAccess = await _postService.CanUserAccessDeviceAsync(userId, deviceId, cancellationToken);
|
|
return Ok(new { hasAccess });
|
|
}
|
|
|
|
/// <summary>
|
|
/// ایجاد پست اسنپشات وضعیت سنسورها و رلهها
|
|
/// </summary>
|
|
[HttpPost("sensor-snapshot")]
|
|
public async Task<ActionResult<int>> CreateSensorSnapshot(
|
|
CreateSensorSnapshotRequest request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
var id = await _postService.CreateSensorSnapshotAsync(request, cancellationToken);
|
|
return Ok(new { id, message = "وضعیت سنسورها و رلهها ارسال شد" });
|
|
}
|
|
catch (UnauthorizedAccessException ex)
|
|
{
|
|
return Unauthorized(new { error = ex.Message });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// آپلود فایل صوتی (ویس) برای پست
|
|
/// </summary>
|
|
[HttpPost("{postId}/voice")]
|
|
[Consumes("multipart/form-data")]
|
|
public async Task<ActionResult> UploadVoice(
|
|
int postId,
|
|
[FromForm] IFormFile file,
|
|
[FromForm] int? durationSeconds,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
if (file == null || file.Length == 0)
|
|
return BadRequest(new { error = "فایل انتخاب نشده است" });
|
|
|
|
var allowedTypes = new[]
|
|
{
|
|
"audio/webm", "audio/ogg", "audio/mp4", "audio/mpeg",
|
|
"audio/wav", "audio/x-wav", "audio/amr", "audio/aac", "audio/m4a"
|
|
};
|
|
if (!allowedTypes.Contains(file.ContentType.ToLower()))
|
|
return BadRequest(new { error = "فرمت فایل صوتی مجاز نیست" });
|
|
|
|
if (file.Length > 10 * 1024 * 1024)
|
|
return BadRequest(new { error = "حجم فایل صوتی نباید بیشتر از 10 مگابایت باشد" });
|
|
|
|
var uploadsFolder = Path.Combine(_environment.WebRootPath ?? "wwwroot", "uploads", "voice");
|
|
Directory.CreateDirectory(uploadsFolder);
|
|
|
|
var fileName = $"{Guid.NewGuid()}{Path.GetExtension(file.FileName)}";
|
|
var filePath = Path.Combine(uploadsFolder, fileName);
|
|
|
|
await using (var stream = new FileStream(filePath, FileMode.Create))
|
|
{
|
|
await file.CopyToAsync(stream, cancellationToken);
|
|
}
|
|
|
|
var relativePath = $"/uploads/voice/{fileName}";
|
|
await _postService.SetPostVoiceAsync(
|
|
postId,
|
|
file.FileName,
|
|
relativePath,
|
|
file.ContentType,
|
|
file.Length,
|
|
durationSeconds,
|
|
cancellationToken);
|
|
|
|
return Ok(new { filePath = relativePath, message = "ویس با موفقیت آپلود شد" });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return NotFound(new { error = ex.Message });
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error uploading voice for post {PostId}", postId);
|
|
return StatusCode(500, new { error = "خطا در آپلود ویس" });
|
|
}
|
|
}
|
|
}
|
|
|