Skip to content

Commit

Permalink
feat: add followers and following to merchant actor
Browse files Browse the repository at this point in the history
  • Loading branch information
maybeanerd committed Jun 27, 2024
1 parent bdf80f8 commit 1a3680c
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import type { ActivityPubActorObject } from '@/modules/crossroads/activitypub/ac
import { crossroadsBasePath } from '@/config/apiPaths';
import { contentTypeActivityStreams } from '@/modules/crossroads/activitypub/utils/contentType';
import { OutboxDto } from '@/modules/crossroads/activitypub/dto/outbox.dto';
import { FollowerDto } from '@/modules/crossroads/activitypub/dto/followers.dto';

@Controller({ path: crossroadsBasePath })
export class ActivityPubController {
Expand Down Expand Up @@ -59,6 +60,24 @@ export class ActivityPubController {
return outbox;
}

@Get('/followers')
@Header('content-type', contentTypeActivityStreams)
async getFollowers(): Promise<FollowerDto> {
// TODO pagination
const followers = await this.activityPubService.getFollowersCollection();

return followers;
}

@Get('/following')
@Header('content-type', contentTypeActivityStreams)
async getFollowing(): Promise<FollowerDto> {
// TODO pagination
const following = await this.activityPubService.getFollowingCollection();

return following;
}

@Post('/inbox')
@Header('content-type', contentTypeActivityStreams)
async postToInbox(@Body() body: unknown): Promise<void> {
Expand Down
64 changes: 62 additions & 2 deletions backend/src/modules/crossroads/activitypub/activityPub.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import {
getUsernameFromWebfingerSubject,
mapActorToWebfingerResponse,
} from '@/modules/crossroads/activitypub/webfinger';
import type { APActivity, APObject, APRoot } from 'activitypub-types';
import type { APActivity, APActor, APObject, APRoot } from 'activitypub-types';
import { drizz } from 'db';
import { and, asc, eq, inArray, isNotNull } from 'drizzle-orm';
import { and, asc, eq, inArray, isNotNull, desc } from 'drizzle-orm';
import {
ActivityPubActivity,
ActivityPubActor,
Expand All @@ -24,6 +24,7 @@ import {
activityPubActivityQueue,
activityPubActor,
activityPubObject,
storedTreaty,
} from 'db/schema';
import { SupportedObjectType } from '@/modules/crossroads/activitypub/object';
import { SupportedActivityType } from '@/modules/crossroads/activitypub/activity';
Expand Down Expand Up @@ -57,6 +58,8 @@ import { GameContent } from 'db/schemas/ActivityPubObject.schema';
import { contentTypeActivityStreams } from '@/modules/crossroads/activitypub/utils/contentType';
import { createSignedRequestConfig } from '@/modules/crossroads/activitypub/utils/signing';
import { OutboxDto } from '@/modules/crossroads/activitypub/dto/outbox.dto';
import { FollowerDto } from '@/modules/crossroads/activitypub/dto/followers.dto';
import { TreatyStatus } from '@/modules/treaty/types/treatyStatus';

type GameActivityObject = APRoot<APObject> & {
gameContent: GameContent;
Expand All @@ -82,6 +85,16 @@ function mapActivityPubObjectToDto(
};
}

function mapActivityPubActorToFollowerDto(
actor: ActivityPubActor,
): Partial<APRoot<APActor>> {
return {
'@context': 'https://www.w3.org/ns/activitystreams',
id: actor.id,
type: actor.type,
};
}

function mapActivityPubActivityToDto(
activity: ActivityPubActivity,
): APRoot<APActivity & { object: APRoot<APActivity> }> | null {
Expand Down Expand Up @@ -692,6 +705,53 @@ export class ActivityPubService {
return followers;
}

async getFollowersCollection(): Promise<FollowerDto> {
const followers = await drizz.query.activityPubActor.findMany({
where: (actor) => eq(actor.isFollowingThisServer, true),
// TODO store and order by follow date
orderBy: (actor) => asc(actor.id),
});

return {
'@context': 'https://www.w3.org/ns/activitystreams',
summary: 'Followers',
type: 'OrderedCollection',
totalItems: followers.length,
orderedItems: followers.map(mapActivityPubActorToFollowerDto),
};
}

async getFollowingCollection(): Promise<FollowerDto> {
const followedActors = await drizz
.select()
.from(storedTreaty)
.innerJoin(
activityPubActor,
eq(storedTreaty.activityPubActorId, activityPubActor.id),
)
.where(
inArray(storedTreaty.status, [
// All statuses that indicate we are following them
TreatyStatus.Signed,
TreatyStatus.Requested,
TreatyStatus.Rejected,
]),
)
.orderBy(desc(storedTreaty.createdOn));

const following = followedActors.map(
({ activityPubActor: actor }) => actor,
);

return {
'@context': 'https://www.w3.org/ns/activitystreams',
summary: 'Following',
type: 'OrderedCollection',
totalItems: following.length,
orderedItems: following.map(mapActivityPubActorToFollowerDto),
};
}

async createNoteObject(
content: string,
gameContent: GameContent,
Expand Down
4 changes: 4 additions & 0 deletions backend/src/modules/crossroads/activitypub/actor/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {
import {
getActorPublicKeyUrl,
getActorUrl,
getFollowersUrl,
getFollowingUrl,
getInboxUrl,
getOutboxUrl,
} from '@/modules/crossroads/activitypub/utils/apUrl';
Expand All @@ -30,6 +32,8 @@ async function getActorFromId(
preferredUsername: username ?? id,
inbox: getInboxUrl().toString(),
outbox: getOutboxUrl().toString(),
followers: getFollowersUrl().toString(),
following: getFollowingUrl().toString(),

publicKey: {
id: getActorPublicKeyUrl(id).toString(),
Expand Down
20 changes: 20 additions & 0 deletions backend/src/modules/crossroads/activitypub/dto/followers.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { APActor, APRoot } from 'activitypub-types';
import { IsArray, IsNumber, IsString, Min } from 'class-validator';

export class FollowerDto {
@IsString()
'@context': 'https://www.w3.org/ns/activitystreams';

@IsString()
'summary': string;

@IsString()
'type': 'OrderedCollection';

@IsNumber()
@Min(0)
'totalItems': number;

@IsArray()
'orderedItems': Array<Partial<APRoot<APActor>>>;
}
8 changes: 8 additions & 0 deletions backend/src/modules/crossroads/activitypub/utils/apUrl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ export function getInboxUrl(): URL {
export function getOutboxUrl(): URL {
return new URL(`${activityPubBaseUrl}/outbox`);
}

export function getFollowersUrl(): URL {
return new URL(`${activityPubBaseUrl}/followers`);
}

export function getFollowingUrl(): URL {
return new URL(`${activityPubBaseUrl}/following`);
}

0 comments on commit 1a3680c

Please sign in to comment.