From a0bdd57e83fa902eeb7845556393be64fa31cd8b Mon Sep 17 00:00:00 2001 From: me Date: Tue, 17 Dec 2024 10:46:59 +0200 Subject: [PATCH] introduce outbox page --- app/Main.hs | 4 ++-- src/Fedi/Activity.hs | 25 ++++++++++++++++++++++++- src/Fedi/Routes.hs | 39 ++++++++++++++++++++++++++++++++++----- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/app/Main.hs b/app/Main.hs index 2321f01..a5f464a 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -41,8 +41,8 @@ mkFediApp :: IO Twain.Application mkFediApp = do detailsFile <- lookupEnv "FEDI_DETAILS" <&> maybe (error "missing FEDI_DETAILS") id - details <- A.decodeFileStrict detailsFile - <&> maybe (error $ "could not read file '" <> detailsFile <> "'.") id + details <- A.eitherDecodeFileStrict detailsFile + <&> either (\err -> error $ "could not read file '" <> detailsFile <> "'.\n" <> err) id pure $ foldr ($) (Twain.notFound $ Twain.send $ Twain.text "Error: not found.") diff --git a/src/Fedi/Activity.hs b/src/Fedi/Activity.hs index 0efd5a9..6b3c856 100644 --- a/src/Fedi/Activity.hs +++ b/src/Fedi/Activity.hs @@ -1,5 +1,6 @@ module Fedi.Activity where +import Data.Maybe (listToMaybe) import Data.Aeson qualified as A import Data.Text qualified as T import Fedi.Types @@ -35,11 +36,18 @@ type Following = [Actor] type Inbox = Collection Ordered Activity type Outbox = Collection Unordered Activity -type OutboxPage = Collection Unordered Activity +type OutboxPage = OrderedCollectionPage Activity data Ordered data Unordered +data OrderedCollectionPage a + = OrderedCollectionPage + { id :: Url + , partOf :: Url + , orderedItems :: [a] + } + data Collection order a = Collection { summary :: String @@ -87,6 +95,8 @@ instance A.ToJSON a => A.ToJSON (Collection Ordered a) where , "summary" A..= collection.summary , "totalItems" A..= length collection.items , "orderedItems" A..= collection.items + , "first" A..= listToMaybe (take 1 collection.items) + , "last" A..= listToMaybe (take 1 $ reverse collection.items) ] instance A.ToJSON a => A.ToJSON (Collection Unordered a) where @@ -99,4 +109,17 @@ instance A.ToJSON a => A.ToJSON (Collection Unordered a) where , "summary" A..= collection.summary , "totalItems" A..= length collection.items , "items" A..= collection.items + , "first" A..= listToMaybe (take 1 collection.items) + , "last" A..= listToMaybe (take 1 $ reverse collection.items) + ] + +instance A.ToJSON a => A.ToJSON (OrderedCollectionPage a) where + toJSON collection = + A.object + [ "@context" A..= + [ "https://www.w3.org/ns/activitystreams" :: String + ] + , "type" A..= ("OrderedCollectionPage" :: String) + , "partOf" A..= collection.partOf + , "orderedItems" A..= collection.orderedItems ] diff --git a/src/Fedi/Routes.hs b/src/Fedi/Routes.hs index 9e0bde4..fd3812e 100644 --- a/src/Fedi/Routes.hs +++ b/src/Fedi/Routes.hs @@ -18,7 +18,7 @@ routes details = handleUser details , Twain.get (matchOutbox details) do - handleOutbox details + handleOutbox details [] , Twain.get matchWebfinger do handleWebfinger details @@ -61,7 +61,36 @@ matchOutbox :: UserDetails -> Twain.PathPattern matchOutbox details = fromString ("/" <> details.username <> "/outbox") -handleOutbox :: UserDetails -> Twain.ResponderM b -handleOutbox details = do - let content = Collection { summary = details.username <> "'s notes", items = [] } :: Outbox - Twain.send $ jsonLD (A.encode content) +handleOutbox :: UserDetails -> [Activity] -> Twain.ResponderM b +handleOutbox details items = do + isPage <- Twain.queryParamMaybe "page" + let + outboxUrl = + "https://" + <> details.domain + <> "/" + <> details.username + <> "/outbox" + let + response = + case isPage of + Just True -> + let + content :: OutboxPage + content = + OrderedCollectionPage + { id = outboxUrl <> "?page=true" + , partOf = outboxUrl + , orderedItems = items + } + in A.encode content + _ -> + let + content :: Outbox + content = + Collection + { summary = details.username <> "'s notes" + , items = items + } + in A.encode content + Twain.send $ jsonLD response