@@ -13,17 +13,19 @@ import {
13
13
import { Temporal } from '@js-temporal/polyfill' ;
14
14
import type { Context } from 'hono' ;
15
15
import { v4 as uuidv4 } from 'uuid' ;
16
+ import z from 'zod' ;
17
+
18
+ import type { AccountService } from './account/account.service' ;
19
+ import { mapActorToExternalAccountData } from './account/utils' ;
16
20
import { type HonoContextVariables , fedify } from './app' ;
17
21
import { ACTOR_DEFAULT_HANDLE } from './constants' ;
18
22
import { buildActivity } from './helpers/activitypub/activity' ;
23
+ import { updateSiteActor } from './helpers/activitypub/actor' ;
24
+ import { getSiteSettings } from './helpers/ghost' ;
19
25
import { escapeHtml } from './helpers/html' ;
20
26
import { getUserData } from './helpers/user' ;
21
27
import { addToList , removeFromList } from './kv-helpers' ;
22
28
import { lookupActor , lookupObject } from './lookup-helpers' ;
23
-
24
- import z from 'zod' ;
25
- import { updateSiteActor } from './helpers/activitypub/actor' ;
26
- import { getSiteSettings } from './helpers/ghost' ;
27
29
import type { SiteService } from './site/site.service' ;
28
30
29
31
export async function unlikeAction (
@@ -302,61 +304,95 @@ export async function replyAction(
302
304
} ) ;
303
305
}
304
306
305
- export async function followAction (
306
- ctx : Context < { Variables : HonoContextVariables } > ,
307
- ) {
308
- const handle = ctx . req . param ( 'handle' ) ;
309
- const apCtx = fedify . createContext ( ctx . req . raw as Request , {
310
- db : ctx . get ( 'db' ) ,
311
- globaldb : ctx . get ( 'globaldb' ) ,
312
- logger : ctx . get ( 'logger' ) ,
313
- } ) ;
314
- const actorToFollow = await lookupObject ( apCtx , handle ) ;
315
- if ( ! isActor ( actorToFollow ) ) {
316
- // Not Found?
317
- return new Response ( null , {
318
- status : 404 ,
307
+ export function createFollowActionHandler ( accountService : AccountService ) {
308
+ return async function followAction (
309
+ ctx : Context < { Variables : HonoContextVariables } > ,
310
+ ) {
311
+ const handle = ctx . req . param ( 'handle' ) ;
312
+ const apCtx = fedify . createContext ( ctx . req . raw as Request , {
313
+ db : ctx . get ( 'db' ) ,
314
+ globaldb : ctx . get ( 'globaldb' ) ,
315
+ logger : ctx . get ( 'logger' ) ,
319
316
} ) ;
320
- }
317
+ const actorToFollow = await lookupObject ( apCtx , handle ) ;
321
318
322
- const actor = await apCtx . getActor ( ACTOR_DEFAULT_HANDLE ) ; // TODO This should be the actor making the request
319
+ if ( ! isActor ( actorToFollow ) ) {
320
+ return new Response ( null , {
321
+ status : 404 ,
322
+ } ) ;
323
+ }
323
324
324
- if ( actorToFollow . id ! . href === actor ! . id ! . href ) {
325
- return new Response ( null , {
326
- status : 400 ,
325
+ const actor = await apCtx . getActor ( ACTOR_DEFAULT_HANDLE ) ; // TODO This should be the actor making the request
326
+
327
+ if ( actorToFollow . id ! . href === actor ! . id ! . href ) {
328
+ return new Response ( null , {
329
+ status : 400 ,
330
+ } ) ;
331
+ }
332
+
333
+ const followerAccount = await accountService . getAccountByApId (
334
+ actor ! . id ! . href ,
335
+ ) ;
336
+
337
+ if ( ! followerAccount ) {
338
+ return new Response ( null , {
339
+ status : 404 ,
340
+ } ) ;
341
+ }
342
+
343
+ let followeeAccount = await accountService . getAccountByApId (
344
+ actorToFollow . id ! . href ,
345
+ ) ;
346
+ if ( ! followeeAccount ) {
347
+ followeeAccount = await accountService . createExternalAccount (
348
+ await mapActorToExternalAccountData ( actorToFollow ) ,
349
+ ) ;
350
+ }
351
+
352
+ console . log ( followerAccount ) ;
353
+ console . log ( followeeAccount ) ;
354
+
355
+ if (
356
+ await accountService . checkIfAccountIsFollowing (
357
+ followerAccount ,
358
+ followeeAccount ,
359
+ )
360
+ ) {
361
+ return new Response ( null , {
362
+ status : 409 ,
363
+ } ) ;
364
+ }
365
+
366
+ return ;
367
+
368
+ const followId = apCtx . getObjectUri ( Follow , {
369
+ id : uuidv4 ( ) ,
327
370
} ) ;
328
- }
329
371
330
- const following = ( await ctx . get ( 'db' ) . get < string [ ] > ( [ 'following' ] ) ) || [ ] ;
331
- if ( following . includes ( actorToFollow . id ! . href ) ) {
332
- return new Response ( null , {
333
- status : 409 ,
372
+ const follow = new Follow ( {
373
+ id : followId ,
374
+ actor : actor ,
375
+ object : actorToFollow ,
334
376
} ) ;
335
- }
336
377
337
- const followId = apCtx . getObjectUri ( Follow , {
338
- id : uuidv4 ( ) ,
339
- } ) ;
340
- const follow = new Follow ( {
341
- id : followId ,
342
- actor : actor ,
343
- object : actorToFollow ,
344
- } ) ;
345
- const followJson = await follow . toJsonLd ( ) ;
346
- ctx . get ( 'globaldb' ) . set ( [ follow . id ! . href ] , followJson ) ;
378
+ const followJson = await follow . toJsonLd ( ) ;
347
379
348
- await apCtx . sendActivity (
349
- { handle : ACTOR_DEFAULT_HANDLE } ,
350
- actorToFollow ,
351
- follow ,
352
- ) ;
353
- // We return the actor because the serialisation of the object property is not working as expected
354
- return new Response ( JSON . stringify ( await actorToFollow . toJsonLd ( ) ) , {
355
- headers : {
356
- 'Content-Type' : 'application/activity+json' ,
357
- } ,
358
- status : 200 ,
359
- } ) ;
380
+ ctx . get ( 'globaldb' ) . set ( [ follow . id ! . href ] , followJson ) ;
381
+
382
+ await apCtx . sendActivity (
383
+ { handle : ACTOR_DEFAULT_HANDLE } ,
384
+ actorToFollow ,
385
+ follow ,
386
+ ) ;
387
+
388
+ // We return the actor because the serialisation of the object property is not working as expected
389
+ return new Response ( JSON . stringify ( await actorToFollow . toJsonLd ( ) ) , {
390
+ headers : {
391
+ 'Content-Type' : 'application/activity+json' ,
392
+ } ,
393
+ status : 200 ,
394
+ } ) ;
395
+ } ;
360
396
}
361
397
362
398
export const getSiteDataHandler =
0 commit comments