76 lines
No EOL
2.6 KiB
C#
76 lines
No EOL
2.6 KiB
C#
using Iceshrimp.Backend.Core.Database;
|
|
using Iceshrimp.Backend.Core.Database.Tables;
|
|
using Iceshrimp.Backend.Core.Extensions;
|
|
using Iceshrimp.Backend.Core.Helpers;
|
|
using Iceshrimp.Backend.Core.Middleware;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Iceshrimp.Backend.Core.Services;
|
|
|
|
public class RelayService(
|
|
DatabaseContext db,
|
|
SystemUserService systemUserSvc,
|
|
ActivityPub.ActivityRenderer activityRenderer,
|
|
ActivityPub.ActivityDeliverService deliverSvc,
|
|
ActivityPub.UserRenderer userRenderer
|
|
) : IScopedService
|
|
{
|
|
public async Task SubscribeToRelayAsync(string uri)
|
|
{
|
|
uri = new Uri(uri).AbsoluteUri;
|
|
if (await db.Relays.AnyAsync(p => p.Inbox == uri)) return;
|
|
|
|
var relay = new Relay
|
|
{
|
|
Id = IdHelpers.GenerateSnowflakeId(),
|
|
Inbox = uri,
|
|
Status = Relay.RelayStatus.Requesting
|
|
};
|
|
|
|
db.Add(relay);
|
|
await db.SaveChangesAsync();
|
|
|
|
var actor = await systemUserSvc.GetRelayActorAsync();
|
|
var activity = activityRenderer.RenderFollow(actor, relay);
|
|
await deliverSvc.DeliverToAsync(activity, actor, uri);
|
|
}
|
|
|
|
public async Task UnsubscribeFromRelayAsync(Relay relay)
|
|
{
|
|
var actor = await systemUserSvc.GetRelayActorAsync();
|
|
var follow = activityRenderer.RenderFollow(actor, relay);
|
|
var activity = activityRenderer.RenderUndo(userRenderer.RenderLite(actor), follow);
|
|
await deliverSvc.DeliverToAsync(activity, actor, relay.Inbox);
|
|
|
|
db.Remove(relay);
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
public async Task HandleAcceptAsync(User actor, string id)
|
|
{
|
|
// @formatter:off
|
|
if (await db.Relays.FirstOrDefaultAsync(p => p.Id == id) is not { } relay)
|
|
throw GracefulException.UnprocessableEntity($"Relay with id {id} was not found");
|
|
if (relay.Inbox != new Uri(actor.Inbox ?? throw new Exception("Relay actor must have an inbox")).AbsoluteUri)
|
|
throw GracefulException.UnprocessableEntity($"Relay inbox ({relay.Inbox}) does not match relay actor inbox ({actor.Inbox})");
|
|
// @formatter:on
|
|
|
|
relay.Status = Relay.RelayStatus.Accepted;
|
|
actor.IsRelayActor = true;
|
|
await db.SaveChangesAsync();
|
|
}
|
|
|
|
public async Task HandleRejectAsync(User actor, string id)
|
|
{
|
|
// @formatter:off
|
|
if (db.Relays.FirstOrDefault(p => p.Id == id) is not { } relay)
|
|
throw GracefulException.UnprocessableEntity($"Relay with id {id} was not found");
|
|
if (relay.Inbox != new Uri(actor.Inbox ?? throw new Exception("Relay actor must have an inbox")).AbsoluteUri)
|
|
throw GracefulException.UnprocessableEntity($"Relay inbox ({relay.Inbox}) does not match relay actor inbox ({actor.Inbox})");
|
|
// @formatter:on
|
|
|
|
relay.Status = Relay.RelayStatus.Rejected;
|
|
actor.IsRelayActor = true;
|
|
await db.SaveChangesAsync();
|
|
}
|
|
} |