Add channel search and subscription

This commit is contained in:
sevenhill
2026-07-07 22:09:18 +03:00
parent b2766ebbe9
commit 0a42e6f860
14 changed files with 421 additions and 4 deletions
@@ -21,6 +21,7 @@ public sealed class MaxController(
MaxBridgeSyncService syncService,
QMaxDbContext db,
IHubContext<QMaxHub> hubContext,
ChatProjectionService projection,
IOptions<QMaxOptions> options) : ControllerBase
{
private readonly QMaxOptions _options = options.Value;
@@ -69,6 +70,51 @@ public sealed class MaxController(
return new { changed };
}
[HttpGet("channels/search")]
public async Task<ActionResult<IReadOnlyList<MaxChannelSearchResultDto>>> SearchChannels(
string q,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(q))
{
return Array.Empty<MaxChannelSearchResultDto>();
}
var results = await maxBridge.SearchChannelsAsync(q.Trim(), cancellationToken);
return results.Select(ToDto).ToArray();
}
[HttpPost("channels/subscribe")]
public async Task<ActionResult<ChatDto>> SubscribeChannel(
SubscribeMaxChannelRequest request,
CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(request.Link))
{
return BadRequest("Channel link is required.");
}
var update = await maxBridge.JoinChannelAsync(request.Link.Trim(), cancellationToken);
if (update is null)
{
return BadRequest("MAX did not return a channel for this link.");
}
await syncService.ApplyJoinedChannelAsync(update, cancellationToken);
var chat = await db.Chats.FirstOrDefaultAsync(
x => x.DeletedAt == null &&
(x.ExternalId == update.ExternalId ||
(!string.IsNullOrWhiteSpace(update.ChatUrl) && x.WebUrl == update.ChatUrl)),
cancellationToken);
if (chat is null)
{
return BadRequest("Channel was joined but was not saved in QMAX.");
}
await hubContext.Clients.All.SendAsync("ChatListInvalidated", cancellationToken);
return projection.ToDto(chat);
}
private async Task SaveStateAsync(MaxBridgeStatus status, CancellationToken cancellationToken)
{
var state = await db.MaxAccountStates.FirstOrDefaultAsync(x => x.Id == 1, cancellationToken);
@@ -92,4 +138,9 @@ public sealed class MaxController(
{
return new MaxBridgeStatusDto(status.Mode, status.IsAuthorized, status.LoginStage, status.Status, status.Url, status.Title, status.LastError, status.UpdatedAt);
}
private static MaxChannelSearchResultDto ToDto(MaxChannelSearchResult channel)
{
return new MaxChannelSearchResultDto(channel.ExternalId, channel.Title, channel.AvatarUrl, channel.ChatUrl, channel.IsSubscribed, channel.Description);
}
}