@@ -10,9 +10,9 @@ import {
10
10
getUsernameFromWebfingerSubject ,
11
11
mapActorToWebfingerResponse ,
12
12
} from '@/modules/crossroads/activitypub/webfinger' ;
13
- import type { APActivity , APObject , APRoot } from 'activitypub-types' ;
13
+ import type { APActivity , APActor , APObject , APRoot } from 'activitypub-types' ;
14
14
import { drizz } from 'db' ;
15
- import { and , asc , eq , inArray , isNotNull } from 'drizzle-orm' ;
15
+ import { and , asc , eq , inArray , isNotNull , desc } from 'drizzle-orm' ;
16
16
import {
17
17
ActivityPubActivity ,
18
18
ActivityPubActor ,
@@ -24,6 +24,7 @@ import {
24
24
activityPubActivityQueue ,
25
25
activityPubActor ,
26
26
activityPubObject ,
27
+ storedTreaty ,
27
28
} from 'db/schema' ;
28
29
import { SupportedObjectType } from '@/modules/crossroads/activitypub/object' ;
29
30
import { SupportedActivityType } from '@/modules/crossroads/activitypub/activity' ;
@@ -57,6 +58,8 @@ import { GameContent } from 'db/schemas/ActivityPubObject.schema';
57
58
import { contentTypeActivityStreams } from '@/modules/crossroads/activitypub/utils/contentType' ;
58
59
import { createSignedRequestConfig } from '@/modules/crossroads/activitypub/utils/signing' ;
59
60
import { OutboxDto } from '@/modules/crossroads/activitypub/dto/outbox.dto' ;
61
+ import { FollowerDto } from '@/modules/crossroads/activitypub/dto/followers.dto' ;
62
+ import { TreatyStatus } from '@/modules/treaty/types/treatyStatus' ;
60
63
61
64
type GameActivityObject = APRoot < APObject > & {
62
65
gameContent : GameContent ;
@@ -82,6 +85,16 @@ function mapActivityPubObjectToDto(
82
85
} ;
83
86
}
84
87
88
+ function mapActivityPubActorToFollowerDto (
89
+ actor : ActivityPubActor ,
90
+ ) : Partial < APRoot < APActor > > {
91
+ return {
92
+ '@context' : 'https://www.w3.org/ns/activitystreams' ,
93
+ id : actor . id ,
94
+ type : actor . type ,
95
+ } ;
96
+ }
97
+
85
98
function mapActivityPubActivityToDto (
86
99
activity : ActivityPubActivity ,
87
100
) : APRoot < APActivity & { object : APRoot < APActivity > } > | null {
@@ -692,6 +705,53 @@ export class ActivityPubService {
692
705
return followers ;
693
706
}
694
707
708
+ async getFollowersCollection ( ) : Promise < FollowerDto > {
709
+ const followers = await drizz . query . activityPubActor . findMany ( {
710
+ where : ( actor ) => eq ( actor . isFollowingThisServer , true ) ,
711
+ // TODO store and order by follow date
712
+ orderBy : ( actor ) => asc ( actor . id ) ,
713
+ } ) ;
714
+
715
+ return {
716
+ '@context' : 'https://www.w3.org/ns/activitystreams' ,
717
+ summary : 'Followers' ,
718
+ type : 'OrderedCollection' ,
719
+ totalItems : followers . length ,
720
+ orderedItems : followers . map ( mapActivityPubActorToFollowerDto ) ,
721
+ } ;
722
+ }
723
+
724
+ async getFollowingCollection ( ) : Promise < FollowerDto > {
725
+ const followedActors = await drizz
726
+ . select ( )
727
+ . from ( storedTreaty )
728
+ . innerJoin (
729
+ activityPubActor ,
730
+ eq ( storedTreaty . activityPubActorId , activityPubActor . id ) ,
731
+ )
732
+ . where (
733
+ inArray ( storedTreaty . status , [
734
+ // All statuses that indicate we are following them
735
+ TreatyStatus . Signed ,
736
+ TreatyStatus . Requested ,
737
+ TreatyStatus . Rejected ,
738
+ ] ) ,
739
+ )
740
+ . orderBy ( desc ( storedTreaty . createdOn ) ) ;
741
+
742
+ const following = followedActors . map (
743
+ ( { activityPubActor : actor } ) => actor ,
744
+ ) ;
745
+
746
+ return {
747
+ '@context' : 'https://www.w3.org/ns/activitystreams' ,
748
+ summary : 'Following' ,
749
+ type : 'OrderedCollection' ,
750
+ totalItems : following . length ,
751
+ orderedItems : following . map ( mapActivityPubActorToFollowerDto ) ,
752
+ } ;
753
+ }
754
+
695
755
async createNoteObject (
696
756
content : string ,
697
757
gameContent : GameContent ,
0 commit comments