you're telling me a puppy coded this??
module API.ActivityPub where

import Data.Functor ((<&>))
import Data.Result
import Data.Text (Text)
import Effectful
import Effectful.Fail
import Puppy.Context
import Puppy.Database (DB)
import Puppy.Logging
import Puppy.Protocol.ActivityStreams (Id (..))
import qualified Data.Aeson as JSON
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text.Encoding as T
import qualified Puppy.Database as DB
import qualified Puppy.Protocol.ActivityPub as AP
import qualified Puppy.Protocol.ActivityStreams as AS

serveObject :: (DB :> es) => Id -> Eff es Result
serveObject objectId = DB.getObjectById objectId
  <&> maybe (Error 404 "No such object") fixup
  where
    fixup = AS.object (Value . fmap (.id)) Value Value

handleInbox
  :: (
    AP.ActivityPub :> es,
    DB :> es,
    Fail :> es,
    Log :> es,
    ServerInfo :> es
  ) => Text
    -> LBS.ByteString
    -> Eff es Result
handleInbox actorName body = scope "handleInbox" $ do
  -- TODO: verify that the activity actually involves the actor
  Id actorId <- localActorId actorName
  debug ("Processing: " <> T.decodeUtf8 (LBS.toStrict body))
  debug ("Targeted: " <> actorId)
  case JSON.decode body of
    Just json -> do
      activity <- AP.dereference json
      DB.getChannelByActorId (Id actorId) >>= \case
        Just channel -> do
          AP.perform activity channel
          debug "Submitted activity for execution"
          return Empty
        Nothing -> return (Error 404 "Targeted actor does not exist")
    Nothing -> return (Error 400 "Could not decode payload")

serveServerActor
  :: (ServerInfo :> es)
  => Eff es Result
serveServerActor = Value <$> serverActor