Files
QMAX/server/QMax.Api/Controllers/MaxController.cs
T
2026-07-03 22:39:48 +03:00

92 lines
3.3 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using QMax.Api.Configuration;
using QMax.Api.Contracts;
using QMax.Api.Data;
using QMax.Api.Data.Entities;
using QMax.Api.Infrastructure.Max;
using QMax.Api.Services;
namespace QMax.Api.Controllers;
[ApiController]
[Authorize]
[Route("api/max")]
public sealed class MaxController(
IMaxBridgeClient maxBridge,
MaxBridgeSyncService syncService,
QMaxDbContext db,
IOptions<QMaxOptions> options) : ControllerBase
{
private readonly QMaxOptions _options = options.Value;
[HttpGet("status")]
public async Task<ActionResult<MaxBridgeStatusDto>> Status(CancellationToken cancellationToken)
{
var status = await maxBridge.GetStatusAsync(cancellationToken);
await SaveStateAsync(status, cancellationToken);
return ToDto(status);
}
[HttpPost("login/start")]
public async Task<ActionResult<MaxBridgeStatusDto>> BeginLogin(BeginMaxLoginRequest request, CancellationToken cancellationToken)
{
var phone = string.IsNullOrWhiteSpace(request.PhoneNumber) ? _options.MaxPhoneNumber : request.PhoneNumber;
if (string.IsNullOrWhiteSpace(phone))
{
return BadRequest("Phone number is required.");
}
var status = await maxBridge.BeginPhoneLoginAsync(phone, cancellationToken);
await SaveStateAsync(status, cancellationToken);
return ToDto(status);
}
[HttpPost("login/code")]
public async Task<ActionResult<MaxBridgeStatusDto>> SubmitCode(SubmitMaxCodeRequest request, CancellationToken cancellationToken)
{
var status = await maxBridge.SubmitLoginCodeAsync(request.Code, cancellationToken);
await SaveStateAsync(status, cancellationToken);
return ToDto(status);
}
[HttpGet("browser/snapshot")]
public async Task<ActionResult<MaxBrowserSnapshotDto>> Snapshot(CancellationToken cancellationToken)
{
var snapshot = await maxBridge.GetSnapshotAsync(cancellationToken);
return new MaxBrowserSnapshotDto(snapshot.Url, snapshot.Title, snapshot.BodyText, snapshot.ScreenshotPngBase64, snapshot.CapturedAt);
}
[HttpPost("sync")]
public async Task<ActionResult<object>> Sync(CancellationToken cancellationToken)
{
var changed = await syncService.SyncOnceAsync(cancellationToken);
return new { changed };
}
private async Task SaveStateAsync(MaxBridgeStatus status, CancellationToken cancellationToken)
{
var state = await db.MaxAccountStates.FirstOrDefaultAsync(x => x.Id == 1, cancellationToken);
if (state is null)
{
state = new MaxAccountState { Id = 1 };
db.MaxAccountStates.Add(state);
}
state.PhoneNumber = _options.MaxPhoneNumber;
state.Status = status.Status;
state.IsAuthorized = status.IsAuthorized;
state.LastUrl = status.Url;
state.LastError = status.LastError;
state.UpdatedAt = DateTimeOffset.UtcNow;
await db.SaveChangesAsync(cancellationToken);
}
private static MaxBridgeStatusDto ToDto(MaxBridgeStatus status)
{
return new MaxBridgeStatusDto(status.Mode, status.IsAuthorized, status.LoginStage, status.Status, status.Url, status.Title, status.LastError, status.UpdatedAt);
}
}