96 lines
3.5 KiB
C#
96 lines
3.5 KiB
C#
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.SignalR;
|
|
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.Hubs;
|
|
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,
|
|
IHubContext<QMaxHub> hubContext,
|
|
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);
|
|
await hubContext.Clients.All.SendAsync("MaxStatusChanged", ToDto(status), 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);
|
|
}
|
|
}
|