using System.Net;
using collAnon.Client.Services;
using decePubClient.Extensions;
using decePubClient.Models;
using PrivaPub.ClientModels;
using PrivaPub.ClientModels.Group;
namespace decePubClient.Services
{
/// The persona's communities and circles (/clientapi/group): made, joined by invitation, edited and left;
/// for their owners and moderators, who is in them and who asks to join.
public class GroupService(IHttpService httpService, ILoggingService logger, CoalescingStringLocalizer localizer)
{
/// The persona's groups, communities first; empty on failure.
public async Task> List(string personaId, CancellationToken cancellationToken = default)
{
if (personaId is null)
return [];
using var response = await httpService.Get(APIs.ClientApi.GET_Groups, [$"avatarId={Uri.EscapeDataString(personaId)}"],
cancellationToken: cancellationToken);
if (!response.IsSuccessStatusCode)
{
var result = await response.Content.ReadWebResult(response.StatusCode, localizer, cancellationToken);
if (result.StatusCode is not (int)HttpStatusCode.Gone)
await logger.ProcessWarning(result.ToString(localizer), $"{nameof(GroupService)}.{nameof(List)}", cancellationToken);
return [];
}
var groups = await response.DefaultReadFromJsonAsync>(cancellationToken) ?? [];
return [.. groups.OrderByDescending(g => g.IsCommunity).ThenBy(g => g.Name ?? g.UserName)];
}
/// Makes a community or a circle owned by the persona; Data is the ViewGroup.
public Task Insert(InsertGroupForm form, CancellationToken cancellationToken = default) =>
GroupResult(APIs.ClientApi.POST_InsertGroup, form, cancellationToken);
/// Changes a group the persona runs; Data is the ViewGroup.
public Task Update(UpdateGroupForm form, CancellationToken cancellationToken = default) =>
GroupResult(APIs.ClientApi.POST_UpdateGroup, form, cancellationToken);
/// Joins a group by its invitation (and its password, when it has one); Data is the ViewGroup.
public Task Join(JoinGroupForm form, CancellationToken cancellationToken = default) =>
GroupResult(APIs.ClientApi.POST_JoinGroup, form, cancellationToken);
public Task Leave(string personaId, string groupId, CancellationToken cancellationToken = default) =>
Membership(APIs.ClientApi.POST_LeaveGroup, personaId, groupId, null, cancellationToken);
/// Lets in someone who asked to join a group the persona runs.
public Task Approve(string personaId, string groupId, string actorUri, CancellationToken cancellationToken = default) =>
Membership(APIs.ClientApi.POST_ApproveGroupMember, personaId, groupId, actorUri, cancellationToken);
/// Declines a request to join; the asker's server is told.
public Task Reject(string personaId, string groupId, string actorUri, CancellationToken cancellationToken = default) =>
Membership(APIs.ClientApi.POST_RejectGroupMember, personaId, groupId, actorUri, cancellationToken);
/// Takes a member out of a group the persona runs.
public Task Remove(string personaId, string groupId, string actorUri, CancellationToken cancellationToken = default) =>
Membership(APIs.ClientApi.POST_RemoveGroupMember, personaId, groupId, actorUri, cancellationToken);
/// Who is in a group the persona runs, and who asks to join; empty on failure.
public async Task> Members(string personaId, string groupId, CancellationToken cancellationToken = default)
{
using var response = await httpService.Get(APIs.ClientApi.GET_GroupMembers,
[$"avatarId={Uri.EscapeDataString(personaId)}", $"groupId={Uri.EscapeDataString(groupId)}"], cancellationToken: cancellationToken);
if (!response.IsSuccessStatusCode)
{
var result = await response.Content.ReadWebResult(response.StatusCode, localizer, cancellationToken);
await logger.ProcessWarning(result.ToString(localizer), $"{nameof(GroupService)}.{nameof(Members)}", cancellationToken);
return [];
}
return await response.DefaultReadFromJsonAsync>(cancellationToken) ?? [];
}
async Task GroupResult(string route, object form, CancellationToken cancellationToken)
{
using var response = await httpService.Post(route, form, cancellationToken: cancellationToken);
if (!response.IsSuccessStatusCode)
return await response.Content.ReadWebResult(response.StatusCode, localizer, cancellationToken);
return new WebResult { Data = await response.DefaultReadFromJsonAsync(cancellationToken) };
}
async Task Membership(string route, string personaId, string groupId, string actorUri, CancellationToken cancellationToken)
{
using var response = await httpService.Post(route, new GroupMembershipForm { AvatarId = personaId, GroupId = groupId, MemberActorURI = actorUri },
cancellationToken: cancellationToken);
if (!response.IsSuccessStatusCode)
return await response.Content.ReadWebResult(response.StatusCode, localizer, cancellationToken);
return new WebResult();
}
}
}