AcaMate_API/Program/V1/Controllers/PushController.cs

299 lines
12 KiB
C#

using AcaMate.Common.Models;
using AcaMate.V1.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Update.Internal;
using AcaMate.Common.Data;
using AcaMate.V1.Services;
using Microsoft.AspNetCore.Http.HttpResults;
namespace AcaMate.V1.Controllers;
[ApiController]
[Route("/api/v1/in/push")]
[ApiExplorerSettings(GroupName = "공통")]
public class PushController : ControllerBase
{
private readonly ILogger<PushController> _logger;
private readonly IPushQueue _pushQueue;
private readonly AppDbContext _dbContext;
private readonly IRepositoryService _repositoryService;
public PushController(ILogger<PushController> logger, IPushQueue pushQueue, AppDbContext dbContext, IRepositoryService repositoryService)
{
_logger = logger;
_pushQueue = pushQueue;
_dbContext = dbContext;
_repositoryService = repositoryService;
}
[HttpGet()]
[CustomOperation("푸시 확인", "저장된 양식을 확인 할 수 있다.", "푸시")]
public async Task<IActionResult> GetPush(string bid, string? pid, string? category)
{
if (!(await _dbContext.Academy.AnyAsync(a=>a.bid == bid)))
return Ok(APIResponse.Send("100", "존재하지 않는 BID", Empty));
List<DBPayload> pushData = new List<DBPayload>();
if (pid == null && category == null)
{
pushData = await _dbContext.DBPayload
.Where(p => p.bid == bid)
.ToListAsync();
}
else if (pid != null && category == null)
{
pushData = await _dbContext.DBPayload
.Where(p => p.bid == bid && p.pid == pid)
.ToListAsync();
}
else if (pid == null && category != null)
{
pushData = await _dbContext.DBPayload
.Where(p => p.bid == bid && p.category == category)
.ToListAsync();
}
else //if (pid != null && category != null)
{
pushData = await _dbContext.DBPayload
.Where(p => p.bid == bid && p.pid == pid && p.category == category)
.ToListAsync();
}
try
{
if (pushData.Count > 0)
{
return Ok(APIResponse.Send("000", "정상", pushData));
}
return Ok(APIResponse.Send("001", "PUSH 데이터가 없음", Empty));
}
catch (Exception ex)
{
_logger.LogError($"[푸시] {ex.Message}");
return StatusCode(500, APIResponse.UnknownError());
}
}
/// <summary>
/// Sends a push notification to the specified device token with the provided payload.
/// </summary>
///
/// <returns>An IActionResult indicating the result of the operation.</returns>
/// <response code="200">Push notification sent successfully.</response>
/// <response code="400">Invalid input parameters.</response>
/// <response code="500">Internal server error occurred.</response>
/// <response code="999">Service unavailable.</response>
[HttpPost("send")]
[CustomOperation("푸시전송", "저장된 양식으로, 사용자에게 푸시를 전송한다.", "푸시")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(APIResponseStatus<object>))]
public async Task<IActionResult> SendPush([FromBody] PushRequest pushRequest)
{
if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError());
try
{
var payload = await _dbContext.DBPayload
.Where(p => p.pid == pushRequest.pid && p.bid == pushRequest.bid )
.Select(p => new Payload
{
aps = new Aps
{
alert = new Alert { title = p.title, body = p.body, subtitle = p.subtitle ?? "" },
category = p.category
},
pid = pushRequest.pid,
bid = pushRequest.bid,
content = p.content ?? "",
})
.FirstOrDefaultAsync();
await Task.Run(async () =>
{
foreach (var uid in pushRequest.uids)
{
if (
await _dbContext.UserAcademy
.Where(ua => ua.uid == uid && ua.bid == pushRequest.bid)
.AnyAsync()
)
{
var badge = await _dbContext.PushCabinet
.Where(c => c.uid == uid
&& c.bid == pushRequest.bid
&& c.pid != pushRequest.pid
&& c.check_yn == false )
.CountAsync();
var pushToken = await _dbContext.User
.Where(u => u.uid == uid)
.Select(u => u.push_token)
.FirstOrDefaultAsync() ?? "";
var pushCabinet = new PushCabinet
{
uid = uid,
bid = pushRequest.bid,
pid = pushRequest.pid,
send_date = DateTime.Now,
};
if (payload != null) payload.aps.badge = badge + 1;
var pushData = new PushData
{
pushToken = pushToken,
payload = payload ?? throw new PushInvalidException("payload is NULL")
};
await _repositoryService.SaveDataFK<PushCabinet>(pushCabinet);
_pushQueue.Enqueue(pushData);
}
}
});
return Ok(APIResponse.Send("000", "정상", Empty));
}
catch (PushInvalidException ex)
{
_logger.LogError(ex.Message);
return Ok(APIResponse.Send("001", "푸시 송신: 푸시 전송 중 문제 발생",Empty));
}
catch (Exception ex)
{
_logger.LogError($"[푸시] {ex.Message}");
return StatusCode(500, APIResponse.UnknownError());
}
}
[HttpPost("set")]
[CustomOperation("푸시내용 변경", "저장된 양식을 변경한다.", "푸시")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(APIResponseStatus<object>))]
public async Task<IActionResult> SetPush([FromBody] DBPayload request)
{
if (!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError());
try
{
var dbPayload = await _dbContext.DBPayload
.FirstOrDefaultAsync(p => p.pid == request.pid && p.bid == request.bid);
if (dbPayload != null)
{
if (dbPayload.title != request.title && request.title != "") dbPayload.title = request.title;
if (dbPayload.body != request.body && request.body != "") dbPayload.body = request.body;
if (dbPayload.subtitle != request.subtitle) dbPayload.subtitle = request.subtitle;
if (dbPayload.alert_yn != request.alert_yn) dbPayload.alert_yn = request.alert_yn;
if (dbPayload.category != request.category && request.category != "") dbPayload.category = request.category;
if (dbPayload.content != request.content) dbPayload.content = request.content;
// if (await _repositoryService.SaveData<DBPayload, string>(dbPayload, p => p.pid))
if (await _repositoryService.SaveDataFK<DBPayload>(dbPayload))
return Ok(APIResponse.Send("000", "PUSH 정보 변경 완료", Empty));
}
return Ok(APIResponse.Send("100", "PID, BID 또는 Cabinet 오류", Empty));
}
catch (Exception ex)
{
_logger.LogError($"[푸시] {ex.Message}");
return StatusCode(500, APIResponse.UnknownError());
}
}
[HttpPost("create")]
[CustomOperation("푸시생성", "새로운 푸시 양식을 생성한다.", "푸시")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(APIResponseStatus<object>))]
public async Task<IActionResult> CreatePush(string token, string refresh, [FromBody] CreatePush createPush)
{
if (string.IsNullOrEmpty(token) || string.IsNullOrEmpty(refresh)) return BadRequest(APIResponse.InvalidInputError());
if(!ModelState.IsValid) return BadRequest(APIResponse.InvalidInputError());
var validateToken = await _repositoryService.ValidateToken(token, refresh);
var uid = validateToken.uid;
Func<string, int, string> randomLetter = (letters, count) => new string(Enumerable.Range(0, count).Select(_ => letters[new Random().Next(letters.Length)]).ToArray());
var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var digits = "0123456789";
var frontLetters = $"{randomLetter(letters, 1)}{randomLetter(digits, 1)}{randomLetter(letters, 1)}";
var afterLetters = $"{randomLetter(letters, 1)}{randomLetter(digits, 1)}{randomLetter(letters, 1)}";
try
{
if (await _dbContext.Academy.AnyAsync(a => a.bid == createPush.bid))
{
DBPayload payload = new DBPayload
{
bid = createPush.bid,
pid = $"AP{DateTime.Now:yyyyMMdd}{frontLetters}{DateTime.Now:HHmmss}{afterLetters}",
title = createPush.title,
subtitle = createPush.subtitle,
body = createPush.body,
alert_yn = createPush.alert_yn,
category = createPush.category,
content = createPush.content,
};
if (await _repositoryService.SaveDataFK<DBPayload>(payload))
{
var logPush = new LogPush
{
bid = payload.bid,
pid = payload.pid,
create_uid = uid,
create_date = DateTime.Now,
log = $"[CREATE] {payload.pid} 최초 생성 - {uid}"
};
// 로그를 이제 만들어서 추가를 해야 합니다.
_dbContext.Set<LogPush>().Add(logPush);
await _dbContext.SaveChangesAsync();
return Ok(APIResponse.Send("000", "정상, push 저장 완료", Empty));
}
}
return Ok(APIResponse.Send("100", "학원 정보(BID) 확인 불가", Empty));
}
catch (TokenException tokenEx)
{
_logger.LogInformation($"[푸시 생성] : {tokenEx}");
return Ok(APIResponse.Send("001", "[푸시 생성] : 토큰에 문제가 있음",Empty));
}
catch (RefreshRevokeException refreshEx)
{
_logger.LogInformation($"[푸시 생성] : {refreshEx}");
return Ok(APIResponse.Send("001", "[푸시 생성] : 폐기된 리프레시 토큰",Empty));
}
catch (Exception ex)
{
_logger.LogError($"[푸시] {ex.Message}");
return StatusCode(500, APIResponse.UnknownError());
}
}
[HttpDelete("delete")]
[CustomOperation("푸시삭제", "저장된 푸시 양식을 삭제 한다.", "푸시")]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(APIResponseStatus<object>))]
public async Task<IActionResult> DeletePush(string bid, string pid)
{
return Ok("good");
}
}// END PUSH CONTROLLER