use duplicate record fields

This commit is contained in:
me 2024-12-17 10:46:59 +02:00
parent 3034f194c7
commit a36f3a2bed
5 changed files with 78 additions and 93 deletions

View file

@ -52,6 +52,7 @@ library
GeneralizedNewtypeDeriving GeneralizedNewtypeDeriving
DeriveAnyClass DeriveAnyClass
DerivingStrategies DerivingStrategies
DuplicateRecordFields
executable fedi executable fedi
import: warnings import: warnings

View file

@ -8,7 +8,7 @@ import Data.Time (UTCTime)
data Activity data Activity
= Create = Create
{ createId :: ActivityUrl { id :: ActivityUrl
, actor :: ActorId , actor :: ActorId
, object :: Object , object :: Object
} }
@ -20,13 +20,13 @@ data Object
data Note data Note
= Note = Note
{ noteId :: NoteId { id :: NoteId
, notePublished :: UTCTime , published :: UTCTime
, noteActor :: ActorId , actor :: ActorId
, noteContent :: T.Text , content :: T.Text
, noteName :: Maybe String , name :: Maybe String
, noteUrl :: Maybe Url , url :: Maybe Url
, noteReplies :: Collection Unordered Note , replies :: Collection Unordered Note
} }
type NoteId = Url type NoteId = Url
@ -35,29 +35,30 @@ type Following = [Actor]
type Inbox = Collection Ordered Activity type Inbox = Collection Ordered Activity
type Outbox = Collection Unordered Activity type Outbox = Collection Unordered Activity
type OutboxPage = Collection Unordered Activity
data Ordered data Ordered
data Unordered data Unordered
data Collection order a data Collection order a
= Collection = Collection
{ collectionSummary :: String { summary :: String
, collectionItems :: [a] , items :: [a]
} }
instance A.ToJSON Note where instance A.ToJSON Note where
toJSON note = toJSON note =
A.object $ A.object $
[ "type" A..= ("Note" :: String) [ "type" A..= ("Note" :: String)
, "id" A..= note.noteId , "id" A..= note.id
, "published" A..= note.notePublished , "published" A..= note.published
, "attributedTo" A..= note.noteActor , "attributedTo" A..= note.actor
, "content" A..= note.noteContent , "content" A..= note.content
, "name" A..= note.noteName , "name" A..= note.name
, "replies" A..= note.noteReplies , "replies" A..= note.replies
] ]
<> [ "name" A..= name | Just name <- [note.noteName] ] <> [ "name" A..= name | Just name <- [note.name] ]
<> [ "url" A..= url | Just url <- [note.noteUrl] ] <> [ "url" A..= url | Just url <- [note.url] ]
instance A.ToJSON Object where instance A.ToJSON Object where
toJSON = \case toJSON = \case
@ -71,7 +72,7 @@ instance A.ToJSON Activity where
[ "https://www.w3.org/ns/activitystreams" :: String [ "https://www.w3.org/ns/activitystreams" :: String
] ]
, "type" A..= ("Create" :: String) , "type" A..= ("Create" :: String)
, "id" A..= create.createId , "id" A..= create.id
, "actor" A..= create.actor , "actor" A..= create.actor
, "object" A..= create.object , "object" A..= create.object
] ]
@ -83,9 +84,9 @@ instance A.ToJSON a => A.ToJSON (Collection Ordered a) where
[ "https://www.w3.org/ns/activitystreams" :: String [ "https://www.w3.org/ns/activitystreams" :: String
] ]
, "type" A..= ("OrderedCollection" :: String) , "type" A..= ("OrderedCollection" :: String)
, "summary" A..= collection.collectionSummary , "summary" A..= collection.summary
, "totalItems" A..= length collection.collectionItems , "totalItems" A..= length collection.items
, "orderedItems" A..= collection.collectionItems , "orderedItems" A..= collection.items
] ]
instance A.ToJSON a => A.ToJSON (Collection Unordered a) where instance A.ToJSON a => A.ToJSON (Collection Unordered a) where
@ -95,24 +96,7 @@ instance A.ToJSON a => A.ToJSON (Collection Unordered a) where
[ "https://www.w3.org/ns/activitystreams" :: String [ "https://www.w3.org/ns/activitystreams" :: String
] ]
, "type" A..= ("Collection" :: String) , "type" A..= ("Collection" :: String)
, "summary" A..= collection.collectionSummary , "summary" A..= collection.summary
, "totalItems" A..= length collection.collectionItems , "totalItems" A..= length collection.items
, "items" A..= collection.collectionItems , "items" A..= collection.items
] ]
{-
"@context": "https://www.w3.org/ns/activitystreams",
"summary": "Sally's notes",
"type": "OrderedCollection",
"totalItems": 2,
"orderedItems": [
{
"type": "Note",
"name": "A Simple Note"
},
{
"type": "Note",
"name": "Another Simple Note"
}
]
-}

View file

@ -5,12 +5,12 @@ import Fedi.Types
data Actor data Actor
= Actor = Actor
{ actorId :: Url { id :: Url
, actorName :: String , name :: String
, actorPreferredUsername :: String , preferredUsername :: String
, actorSummary :: String , summary :: String
, actorIcon :: Url , icon :: Url
, actorPublicKey :: PublicKey , publicKey :: PublicKey
} }
deriving Show deriving Show
@ -22,9 +22,9 @@ data ActorType
data PublicKey data PublicKey
= PublicKey = PublicKey
{ pkId :: Url { id :: Url
, pkOwner :: Url , owner :: Url
, pkPublicKeyPem :: Pem , publicKeyPem :: Pem
} }
deriving Show deriving Show
@ -34,16 +34,16 @@ makeActor details =
url = "https://" <> details.domain url = "https://" <> details.domain
actorUrl = url <> "/" <> details.username actorUrl = url <> "/" <> details.username
in Actor in Actor
{ actorId = actorUrl { id = actorUrl
, actorName = details.name , name = details.name
, actorPreferredUsername = details.username , preferredUsername = details.username
, actorSummary = details.summary , summary = details.summary
, actorIcon = details.icon , icon = details.icon
, actorPublicKey = , publicKey =
PublicKey PublicKey
{ pkId = actorUrl <> "#main-key" { id = actorUrl <> "#main-key"
, pkOwner = actorUrl , owner = actorUrl
, pkPublicKeyPem = details.publicPem , publicKeyPem = details.publicPem
} }
} }
@ -54,19 +54,19 @@ instance A.ToJSON Actor where
[ "https://www.w3.org/ns/activitystreams" :: String [ "https://www.w3.org/ns/activitystreams" :: String
, "https://w3id.org/security/v1" , "https://w3id.org/security/v1"
] ]
, "id" A..= actor.actorId , "id" A..= actor.id
, "type" A..= Person , "type" A..= Person
, "name" A..= actor.actorName , "name" A..= actor.name
, "preferredUsername" A..= actor.actorPreferredUsername , "preferredUsername" A..= actor.preferredUsername
, "summary" A..= actor.actorSummary , "summary" A..= actor.summary
, "icon" A..= A.object , "icon" A..= A.object
[ "type" A..= ("Image" :: String) [ "type" A..= ("Image" :: String)
, "mediaType" A..= ("image/png" :: String) , "mediaType" A..= ("image/png" :: String)
, "url" A..= actor.actorIcon , "url" A..= actor.icon
] ]
, "inbox" A..= (actor.actorId <> "/inbox") , "inbox" A..= (actor.id <> "/inbox")
, "outbox" A..= (actor.actorId <> "/outbox") , "outbox" A..= (actor.id <> "/outbox")
, "publicKey" A..= actor.actorPublicKey , "publicKey" A..= actor.publicKey
] ]
instance A.ToJSON ActorType where instance A.ToJSON ActorType where
@ -75,7 +75,7 @@ instance A.ToJSON ActorType where
instance A.ToJSON PublicKey where instance A.ToJSON PublicKey where
toJSON pk = toJSON pk =
A.object A.object
[ "id" A..= pk.pkId [ "id" A..= pk.id
, "owner" A..= pk.pkOwner , "owner" A..= pk.owner
, "publicKeyPem" A..= pk.pkPublicKeyPem , "publicKeyPem" A..= pk.publicKeyPem
] ]

View file

@ -49,7 +49,7 @@ handleWebfinger :: UserDetails -> Twain.ResponderM b
handleWebfinger details = do handleWebfinger details = do
resource <- Twain.param "resource" resource <- Twain.param "resource"
let webfinger = makeWebfinger details let webfinger = makeWebfinger details
if resource == ppSubject webfinger.wfSubject if resource == ppSubject webfinger.subject
then do then do
Twain.send $ jsonLD (A.encode webfinger) Twain.send $ jsonLD (A.encode webfinger)
else do else do
@ -63,5 +63,5 @@ matchOutbox details =
handleOutbox :: UserDetails -> Twain.ResponderM b handleOutbox :: UserDetails -> Twain.ResponderM b
handleOutbox details = do handleOutbox details = do
let content = Collection { collectionSummary = details.username <> "'s notes", collectionItems = [] } :: Outbox let content = Collection { summary = details.username <> "'s notes", items = [] } :: Outbox
Twain.send $ jsonLD (A.encode content) Twain.send $ jsonLD (A.encode content)

View file

@ -6,27 +6,27 @@ import Fedi.Types
data Webfinger data Webfinger
= Webfinger = Webfinger
{ wfSubject :: Subject { subject :: Subject
, wfLinks :: [Link] , links :: [Link]
} }
deriving Show deriving Show
data Subject data Subject
= Subject = Subject
{ subjectUsername :: Username { username :: Username
, subjectDomain :: Domain , domain :: Domain
} }
deriving Show deriving Show
ppSubject :: Subject -> String ppSubject :: Subject -> String
ppSubject subject = ppSubject subject =
"acct:" <> subject.subjectUsername <> "@" <> subject.subjectDomain "acct:" <> subject.username <> "@" <> subject.domain
data Link data Link
= Link = Link
{ linkRel :: Rel { rel :: Rel
, linkType :: LinkType , type_ :: LinkType
, linkHref :: Url , href :: Url
} }
deriving Show deriving Show
@ -36,15 +36,15 @@ makeWebfinger details =
url = "https://" <> details.domain url = "https://" <> details.domain
in in
Webfinger Webfinger
{ wfSubject = Subject { subject = Subject
{ subjectUsername = details.username { username = details.username
, subjectDomain = details.domain , domain = details.domain
} }
, wfLinks = , links =
[ Link [ Link
{ linkRel = Self { rel = Self
, linkType = ActivityJson , type_ = ActivityJson
, linkHref = url <> "/" <> details.username , href = url <> "/" <> details.username
} }
] ]
} }
@ -55,8 +55,8 @@ makeWebfinger details =
instance A.ToJSON Webfinger where instance A.ToJSON Webfinger where
toJSON webfinger = toJSON webfinger =
A.object A.object
[ "subject" A..= webfinger.wfSubject [ "subject" A..= webfinger.subject
, "links" A..= webfinger.wfLinks , "links" A..= webfinger.links
] ]
instance A.ToJSON Subject where instance A.ToJSON Subject where
@ -66,7 +66,7 @@ instance A.ToJSON Subject where
instance A.ToJSON Link where instance A.ToJSON Link where
toJSON link = toJSON link =
A.object A.object
[ "rel" A..= link.linkRel [ "rel" A..= link.rel
, "type" A..= link.linkType , "type" A..= link.type_
, "href" A..= link.linkHref , "href" A..= link.href
] ]