Render in advance and store comment content as HTML alongside Markdown source
This commit is contained in:
parent
facf4d7f3e
commit
c7dccbb7fe
11 changed files with 116 additions and 20 deletions
|
@ -322,6 +322,7 @@ RemoteDiscussion
|
||||||
Message
|
Message
|
||||||
created UTCTime
|
created UTCTime
|
||||||
source Text -- Pandoc Markdown
|
source Text -- Pandoc Markdown
|
||||||
|
content Text -- HTML
|
||||||
parent MessageId Maybe
|
parent MessageId Maybe
|
||||||
root DiscussionId
|
root DiscussionId
|
||||||
|
|
||||||
|
|
8
migrations/2019_06_02.model
Normal file
8
migrations/2019_06_02.model
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Discussion
|
||||||
|
|
||||||
|
Message
|
||||||
|
created UTCTime
|
||||||
|
source Text -- Pandoc Markdown
|
||||||
|
content Text -- HTML
|
||||||
|
parent MessageId Maybe
|
||||||
|
root DiscussionId
|
|
@ -608,7 +608,7 @@ handleSharerInbox now shrRecip (Right iidSender) raw activity =
|
||||||
CreateActivity (Create note) -> handleNote note
|
CreateActivity (Create note) -> handleNote note
|
||||||
_ -> return "Unsupported activity type"
|
_ -> return "Unsupported activity type"
|
||||||
where
|
where
|
||||||
handleNote (Note mluNote _ _ muParent muContext mpublished content) = do
|
handleNote (Note mluNote _ _ muParent muContext mpublished _ _) = do
|
||||||
_luNote <- fromMaybeE mluNote "Note without note id"
|
_luNote <- fromMaybeE mluNote "Note without note id"
|
||||||
_published <- fromMaybeE mpublished "Note without 'published' field"
|
_published <- fromMaybeE mpublished "Note without 'published' field"
|
||||||
uContext <- fromMaybeE muContext "Note without context"
|
uContext <- fromMaybeE muContext "Note without context"
|
||||||
|
@ -702,7 +702,7 @@ handleProjectInbox now shrRecip prjRecip iidSender hSender raidSender body raw a
|
||||||
handleNote (activityAudience activity) note
|
handleNote (activityAudience activity) note
|
||||||
_ -> return "Unsupported activity type"
|
_ -> return "Unsupported activity type"
|
||||||
where
|
where
|
||||||
handleNote audience (Note mluNote _ _ muParent muCtx mpub content) = do
|
handleNote audience (Note mluNote _ _ muParent muCtx mpub src content) = do
|
||||||
luNote <- fromMaybeE mluNote "Note without note id"
|
luNote <- fromMaybeE mluNote "Note without note id"
|
||||||
published <- fromMaybeE mpub "Note without 'published' field"
|
published <- fromMaybeE mpub "Note without 'published' field"
|
||||||
uContext <- fromMaybeE muCtx "Note without context"
|
uContext <- fromMaybeE muCtx "Note without context"
|
||||||
|
@ -812,7 +812,8 @@ handleProjectInbox now shrRecip prjRecip iidSender hSender raidSender body raw a
|
||||||
}
|
}
|
||||||
mid <- insert Message
|
mid <- insert Message
|
||||||
{ messageCreated = published
|
{ messageCreated = published
|
||||||
, messageSource = content
|
, messageSource = src
|
||||||
|
, messageContent = content
|
||||||
, messageParent =
|
, messageParent =
|
||||||
case meparent of
|
case meparent of
|
||||||
Just (Left midParent) -> Just midParent
|
Just (Left midParent) -> Just midParent
|
||||||
|
@ -1060,7 +1061,7 @@ data Recip
|
||||||
-- a comment on a local ticket, or a comment on some remote context. Return an
|
-- a comment on a local ticket, or a comment on some remote context. Return an
|
||||||
-- error message if the Note is rejected, otherwise the new 'LocalMessageId'.
|
-- error message if the Note is rejected, otherwise the new 'LocalMessageId'.
|
||||||
handleOutboxNote :: Text -> Note -> Handler (Either Text LocalMessageId)
|
handleOutboxNote :: Text -> Note -> Handler (Either Text LocalMessageId)
|
||||||
handleOutboxNote host (Note mluNote luAttrib aud muParent muContext mpublished content) = runExceptT $ do
|
handleOutboxNote host (Note mluNote luAttrib aud muParent muContext mpublished source content) = runExceptT $ do
|
||||||
verifyHostLocal host "Attributed to non-local actor"
|
verifyHostLocal host "Attributed to non-local actor"
|
||||||
verifyNothing mluNote "Note specifies an id"
|
verifyNothing mluNote "Note specifies an id"
|
||||||
verifyNothing mpublished "Note specifies published"
|
verifyNothing mpublished "Note specifies published"
|
||||||
|
@ -1131,7 +1132,7 @@ handleOutboxNote host (Note mluNote luAttrib aud muParent muContext mpublished c
|
||||||
throwE "Remote parent belongs to a different discussion"
|
throwE "Remote parent belongs to a different discussion"
|
||||||
return mid
|
return mid
|
||||||
return (did, meparent, Nothing)
|
return (did, meparent, Nothing)
|
||||||
(lmid, obid, doc) <- lift $ insertMessage luAttrib shrUser pid uContext did muParent meparent content
|
(lmid, obid, doc) <- lift $ insertMessage luAttrib shrUser pid uContext did muParent meparent source content
|
||||||
moreRemotes <- deliverLocal pid obid localRecips mcollections
|
moreRemotes <- deliverLocal pid obid localRecips mcollections
|
||||||
unless (federation || null moreRemotes) $
|
unless (federation || null moreRemotes) $
|
||||||
throwE "Federation disabled but remote collection members found"
|
throwE "Federation disabled but remote collection members found"
|
||||||
|
@ -1322,12 +1323,14 @@ handleOutboxNote host (Note mluNote luAttrib aud muParent muContext mpublished c
|
||||||
-> Maybe FedURI
|
-> Maybe FedURI
|
||||||
-> Maybe (Either MessageId FedURI)
|
-> Maybe (Either MessageId FedURI)
|
||||||
-> Text
|
-> Text
|
||||||
|
-> Text
|
||||||
-> AppDB (LocalMessageId, OutboxItemId, Doc Activity)
|
-> AppDB (LocalMessageId, OutboxItemId, Doc Activity)
|
||||||
insertMessage luAttrib shrUser pid uContext did muParent meparent content = do
|
insertMessage luAttrib shrUser pid uContext did muParent meparent source content = do
|
||||||
now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
mid <- insert Message
|
mid <- insert Message
|
||||||
{ messageCreated = now
|
{ messageCreated = now
|
||||||
, messageSource = content
|
, messageSource = source
|
||||||
|
, messageContent = content
|
||||||
, messageParent =
|
, messageParent =
|
||||||
case meparent of
|
case meparent of
|
||||||
Just (Left midParent) -> Just midParent
|
Just (Left midParent) -> Just midParent
|
||||||
|
|
|
@ -42,6 +42,8 @@ import Yesod.Form.Functions (runFormPost)
|
||||||
import Yesod.Form.Types (FormResult (..))
|
import Yesod.Form.Types (FormResult (..))
|
||||||
import Yesod.Persist.Core (runDB, get404, getBy404)
|
import Yesod.Persist.Core (runDB, get404, getBy404)
|
||||||
|
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
import Data.Aeson.Encode.Pretty.ToEncoding
|
import Data.Aeson.Encode.Pretty.ToEncoding
|
||||||
import Database.Persist.JSON
|
import Database.Persist.JSON
|
||||||
import Network.FedURI
|
import Network.FedURI
|
||||||
|
@ -59,6 +61,7 @@ import Vervis.Federation
|
||||||
import Vervis.Foundation
|
import Vervis.Foundation
|
||||||
import Vervis.Model
|
import Vervis.Model
|
||||||
import Vervis.Model.Ident
|
import Vervis.Model.Ident
|
||||||
|
import Vervis.Render
|
||||||
import Vervis.Settings
|
import Vervis.Settings
|
||||||
import Vervis.Widget.Discussion
|
import Vervis.Widget.Discussion
|
||||||
|
|
||||||
|
@ -164,7 +167,8 @@ getDiscussionMessage shr lmid = do
|
||||||
, noteReplyTo = Just $ fromMaybe uContext muParent
|
, noteReplyTo = Just $ fromMaybe uContext muParent
|
||||||
, noteContext = Just uContext
|
, noteContext = Just uContext
|
||||||
, notePublished = Just $ messageCreated m
|
, notePublished = Just $ messageCreated m
|
||||||
, noteContent = messageSource m
|
, noteSource = messageSource m
|
||||||
|
, noteContent = messageContent m
|
||||||
}
|
}
|
||||||
selectRep $ do
|
selectRep $ do
|
||||||
provideAP $ pure doc
|
provideAP $ pure doc
|
||||||
|
@ -200,6 +204,8 @@ postTopReply hDest recipsA recipsC context replyP after = do
|
||||||
shrAuthor <- do
|
shrAuthor <- do
|
||||||
Entity _ p <- requireVerifiedAuth
|
Entity _ p <- requireVerifiedAuth
|
||||||
lift $ runDB $ sharerIdent <$> get404 (personIdent p)
|
lift $ runDB $ sharerIdent <$> get404 (personIdent p)
|
||||||
|
let msg' = T.filter (/= '\r') msg
|
||||||
|
contentHtml <- ExceptT . pure $ renderPandocMarkdown msg'
|
||||||
let (hLocal, luAuthor) = f2l $ encodeRouteFed $ SharerR shrAuthor
|
let (hLocal, luAuthor) = f2l $ encodeRouteFed $ SharerR shrAuthor
|
||||||
uContext = encodeRecipRoute context
|
uContext = encodeRecipRoute context
|
||||||
recips = recipsA ++ recipsC
|
recips = recipsA ++ recipsC
|
||||||
|
@ -217,7 +223,8 @@ postTopReply hDest recipsA recipsC context replyP after = do
|
||||||
, noteReplyTo = Just uContext
|
, noteReplyTo = Just uContext
|
||||||
, noteContext = Just uContext
|
, noteContext = Just uContext
|
||||||
, notePublished = Nothing
|
, notePublished = Nothing
|
||||||
, noteContent = msg
|
, noteSource = msg'
|
||||||
|
, noteContent = contentHtml
|
||||||
}
|
}
|
||||||
ExceptT $ handleOutboxNote hLocal note
|
ExceptT $ handleOutboxNote hLocal note
|
||||||
case elmid of
|
case elmid of
|
||||||
|
@ -280,6 +287,8 @@ postReply hDest recipsA recipsC context replyG replyP after getdid midParent = d
|
||||||
i <- getJust $ remoteMessageInstance rm
|
i <- getJust $ remoteMessageInstance rm
|
||||||
return $ l2f (instanceHost i) (remoteMessageIdent rm)
|
return $ l2f (instanceHost i) (remoteMessageIdent rm)
|
||||||
return (shr, parent)
|
return (shr, parent)
|
||||||
|
let msg' = T.filter (/= '\r') msg
|
||||||
|
contentHtml <- ExceptT . pure $ renderPandocMarkdown msg'
|
||||||
let (hLocal, luAuthor) = f2l $ encodeRouteFed $ SharerR shrAuthor
|
let (hLocal, luAuthor) = f2l $ encodeRouteFed $ SharerR shrAuthor
|
||||||
uContext = encodeRecipRoute context
|
uContext = encodeRecipRoute context
|
||||||
recips = recipsA ++ recipsC
|
recips = recipsA ++ recipsC
|
||||||
|
@ -297,7 +306,8 @@ postReply hDest recipsA recipsC context replyG replyP after getdid midParent = d
|
||||||
, noteReplyTo = Just uParent
|
, noteReplyTo = Just uParent
|
||||||
, noteContext = Just uContext
|
, noteContext = Just uContext
|
||||||
, notePublished = Nothing
|
, notePublished = Nothing
|
||||||
, noteContent = msg
|
, noteSource = msg'
|
||||||
|
, noteContent = contentHtml
|
||||||
}
|
}
|
||||||
ExceptT $ handleOutboxNote hLocal note
|
ExceptT $ handleOutboxNote hLocal note
|
||||||
case elmid of
|
case elmid of
|
||||||
|
|
|
@ -79,7 +79,7 @@ import Yesod.Persist.Core
|
||||||
import qualified Data.ByteString.Char8 as BC (unpack)
|
import qualified Data.ByteString.Char8 as BC (unpack)
|
||||||
import qualified Data.CaseInsensitive as CI (mk)
|
import qualified Data.CaseInsensitive as CI (mk)
|
||||||
import qualified Data.HashMap.Strict as M (lookup, insert, adjust, fromList)
|
import qualified Data.HashMap.Strict as M (lookup, insert, adjust, fromList)
|
||||||
import qualified Data.Text as T (pack, unpack, concat)
|
import qualified Data.Text as T
|
||||||
import qualified Data.Text.Lazy as TL (toStrict)
|
import qualified Data.Text.Lazy as TL (toStrict)
|
||||||
import qualified Data.Text.Lazy.Builder as TLB
|
import qualified Data.Text.Lazy.Builder as TLB
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
|
@ -115,6 +115,7 @@ import Vervis.Model
|
||||||
import Vervis.Model.Ident
|
import Vervis.Model.Ident
|
||||||
import Vervis.Paginate
|
import Vervis.Paginate
|
||||||
import Vervis.RemoteActorStore
|
import Vervis.RemoteActorStore
|
||||||
|
import Vervis.Render
|
||||||
import Vervis.Settings
|
import Vervis.Settings
|
||||||
|
|
||||||
getInboxR :: Handler Html
|
getInboxR :: Handler Html
|
||||||
|
@ -438,6 +439,8 @@ postOutboxR shrAuthor = do
|
||||||
FormSuccess r -> return r
|
FormSuccess r -> return r
|
||||||
encodeRouteFed <- getEncodeRouteHome
|
encodeRouteFed <- getEncodeRouteHome
|
||||||
encodeRouteLocal <- getEncodeRouteLocal
|
encodeRouteLocal <- getEncodeRouteLocal
|
||||||
|
let msg' = T.filter (/= '\r') msg
|
||||||
|
contentHtml <- ExceptT . pure $ renderPandocMarkdown msg'
|
||||||
let encodeRecipRoute = l2f hTicket . encodeRouteLocal
|
let encodeRecipRoute = l2f hTicket . encodeRouteLocal
|
||||||
uTicket = encodeRecipRoute $ TicketR shrTicket prj num
|
uTicket = encodeRecipRoute $ TicketR shrTicket prj num
|
||||||
(hLocal, luAuthor) = f2l $ encodeRouteFed $ SharerR shrAuthor
|
(hLocal, luAuthor) = f2l $ encodeRouteFed $ SharerR shrAuthor
|
||||||
|
@ -460,7 +463,8 @@ postOutboxR shrAuthor = do
|
||||||
, noteReplyTo = Just $ fromMaybe uTicket muParent
|
, noteReplyTo = Just $ fromMaybe uTicket muParent
|
||||||
, noteContext = Just uTicket
|
, noteContext = Just uTicket
|
||||||
, notePublished = Nothing
|
, notePublished = Nothing
|
||||||
, noteContent = msg
|
, noteSource = msg'
|
||||||
|
, noteContent = contentHtml
|
||||||
}
|
}
|
||||||
ExceptT $ handleOutboxNote hLocal note
|
ExceptT $ handleOutboxNote hLocal note
|
||||||
case elmid of
|
case elmid of
|
||||||
|
|
|
@ -21,6 +21,7 @@ where
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
import Control.Applicative
|
import Control.Applicative
|
||||||
|
import Control.Exception
|
||||||
import Control.Monad (unless)
|
import Control.Monad (unless)
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
import Control.Monad.Trans.Class (lift)
|
import Control.Monad.Trans.Class (lift)
|
||||||
|
@ -65,6 +66,7 @@ import Database.Persist.Local
|
||||||
import Vervis.Model.Ident
|
import Vervis.Model.Ident
|
||||||
import Vervis.Foundation (Route (..))
|
import Vervis.Foundation (Route (..))
|
||||||
import Vervis.Migration.Model
|
import Vervis.Migration.Model
|
||||||
|
import Vervis.Render
|
||||||
|
|
||||||
instance PersistDefault ByteString where
|
instance PersistDefault ByteString where
|
||||||
pdef = def
|
pdef = def
|
||||||
|
@ -424,6 +426,12 @@ changes hLocal ctx =
|
||||||
l2f (instance201905Host i)
|
l2f (instance201905Host i)
|
||||||
(remoteMessage201905Ident rmP)
|
(remoteMessage201905Ident rmP)
|
||||||
|
|
||||||
|
let msg = T.filter (/= '\r') $ message201905Content m
|
||||||
|
contentHtml <-
|
||||||
|
case renderPandocMarkdown msg of
|
||||||
|
Left e -> error $ T.unpack e
|
||||||
|
Right t -> return t
|
||||||
|
|
||||||
let aud = Audience recips [] [] [] [] []
|
let aud = Audience recips [] [] [] [] []
|
||||||
|
|
||||||
luAttrib = LocalURI ("/s/" <> shr2text shr) ""
|
luAttrib = LocalURI ("/s/" <> shr2text shr) ""
|
||||||
|
@ -439,7 +447,8 @@ changes hLocal ctx =
|
||||||
, noteReplyTo = Just $ fromMaybe uContext muParent
|
, noteReplyTo = Just $ fromMaybe uContext muParent
|
||||||
, noteContext = Just uContext
|
, noteContext = Just uContext
|
||||||
, notePublished = Just $ message201905Created m
|
, notePublished = Just $ message201905Created m
|
||||||
, noteContent = message201905Content m
|
, noteSource = msg
|
||||||
|
, noteContent = contentHtml
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -488,6 +497,20 @@ changes hLocal ctx =
|
||||||
, renameUnique "RoleAccess" "UniqueProjectAccess" "UniqueRoleAccess"
|
, renameUnique "RoleAccess" "UniqueProjectAccess" "UniqueRoleAccess"
|
||||||
-- 85
|
-- 85
|
||||||
, renameField "Message" "content" "source"
|
, renameField "Message" "content" "source"
|
||||||
|
-- 86
|
||||||
|
, addFieldPrimRequired "Message" ("" :: Text) "content"
|
||||||
|
-- 87
|
||||||
|
, unchecked $ lift $ do
|
||||||
|
msgs <- selectList ([] :: [Filter Message201906]) []
|
||||||
|
for_ msgs $ \ (Entity mid m) ->
|
||||||
|
let source = T.filter (/= '\r') $ message201906Source m
|
||||||
|
in case renderPandocMarkdown $ message201906Source m of
|
||||||
|
Left err -> liftIO $ throwIO $ userError $ T.unpack err
|
||||||
|
Right content ->
|
||||||
|
update mid
|
||||||
|
[ Message201906Source =. source
|
||||||
|
, Message201906Content =. content
|
||||||
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
migrateDB :: MonadIO m => Text -> HashidsContext -> ReaderT SqlBackend m (Either Text (Int, Int))
|
migrateDB :: MonadIO m => Text -> HashidsContext -> ReaderT SqlBackend m (Either Text (Int, Int))
|
||||||
|
|
|
@ -53,6 +53,8 @@ module Vervis.Migration.Model
|
||||||
, Instance201905Generic (..)
|
, Instance201905Generic (..)
|
||||||
, RemoteDiscussion201905Generic (..)
|
, RemoteDiscussion201905Generic (..)
|
||||||
, RemoteMessage201905Generic (..)
|
, RemoteMessage201905Generic (..)
|
||||||
|
, Message201906Generic (..)
|
||||||
|
, Message201906
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
|
@ -136,3 +138,6 @@ model_2019_05_17 = $(schema "2019_05_17")
|
||||||
|
|
||||||
makeEntitiesMigration "201905"
|
makeEntitiesMigration "201905"
|
||||||
$(modelFile "migrations/2019_05_24.model")
|
$(modelFile "migrations/2019_05_24.model")
|
||||||
|
|
||||||
|
makeEntitiesMigration "201906"
|
||||||
|
$(modelFile "migrations/2019_06_02.model")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{- This file is part of Vervis.
|
{- This file is part of Vervis.
|
||||||
-
|
-
|
||||||
- Written in 2016, 2018 by fr33domlover <fr33domlover@riseup.net>.
|
- Written in 2016, 2018, 2019 by fr33domlover <fr33domlover@riseup.net>.
|
||||||
-
|
-
|
||||||
- ♡ Copying is an act of love. Please copy, reuse and share.
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
||||||
-
|
-
|
||||||
|
@ -39,11 +39,13 @@
|
||||||
module Vervis.Render
|
module Vervis.Render
|
||||||
( renderSourceT
|
( renderSourceT
|
||||||
, renderSourceBL
|
, renderSourceBL
|
||||||
|
, renderPandocMarkdown
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
|
import Control.Exception
|
||||||
import Control.Monad.Catch (throwM)
|
import Control.Monad.Catch (throwM)
|
||||||
import Control.Monad.Logger (logDebug, logWarn)
|
import Control.Monad.Logger (logDebug, logWarn)
|
||||||
import Data.Foldable (for_)
|
import Data.Foldable (for_)
|
||||||
|
@ -230,3 +232,23 @@ renderSource mt contentB contentTL contentT =
|
||||||
Haskell -> code L.Haskell.lexer
|
Haskell -> code L.Haskell.lexer
|
||||||
-- * Misc
|
-- * Misc
|
||||||
_ -> plain
|
_ -> plain
|
||||||
|
|
||||||
|
renderPandocMarkdown :: Text -> Either Text Text
|
||||||
|
renderPandocMarkdown input =
|
||||||
|
case parse input of
|
||||||
|
Left err ->
|
||||||
|
Left $
|
||||||
|
"Failed to parse Markdown: " <> T.pack (displayException err)
|
||||||
|
Right doc ->
|
||||||
|
case render doc of
|
||||||
|
Left err ->
|
||||||
|
Left $
|
||||||
|
"Failed to render Markdown: " <>
|
||||||
|
T.pack (displayException err)
|
||||||
|
Right output -> Right output
|
||||||
|
where
|
||||||
|
parse = runPure . readMarkdown readerOptions
|
||||||
|
render
|
||||||
|
= fmap (sanitizeBalance . TL.toStrict . renderHtml)
|
||||||
|
. runPure
|
||||||
|
. writeHtml5 writerOptions
|
||||||
|
|
|
@ -26,7 +26,7 @@ import Data.Text (Text)
|
||||||
import Data.Time.Clock (UTCTime, diffUTCTime, getCurrentTime)
|
import Data.Time.Clock (UTCTime, diffUTCTime, getCurrentTime)
|
||||||
import Data.Tree (Tree (..))
|
import Data.Tree (Tree (..))
|
||||||
import Database.Persist.Types (Entity (..))
|
import Database.Persist.Types (Entity (..))
|
||||||
import Yesod.Core (Route)
|
import Yesod.Core
|
||||||
import Yesod.Core.Handler (newIdent)
|
import Yesod.Core.Handler (newIdent)
|
||||||
import Yesod.Core.Widget
|
import Yesod.Core.Widget
|
||||||
|
|
||||||
|
@ -61,7 +61,8 @@ messageW now (MessageTreeNode msgid msg author) reply = do
|
||||||
intervalToEventTime .
|
intervalToEventTime .
|
||||||
FriendlyConvert .
|
FriendlyConvert .
|
||||||
diffUTCTime now
|
diffUTCTime now
|
||||||
showContent = renderSourceT Markdown . T.filter (/= '\r')
|
showContent :: Text -> Widget
|
||||||
|
showContent = toWidget . preEscapedToMarkup
|
||||||
$(widgetFile "discussion/widget/message")
|
$(widgetFile "discussion/widget/message")
|
||||||
|
|
||||||
messageTreeW
|
messageTreeW
|
||||||
|
|
|
@ -100,6 +100,7 @@ import Network.HTTP.Client.Conduit.ActivityPub (httpAPEither)
|
||||||
import Network.HTTP.Simple (JSONException)
|
import Network.HTTP.Simple (JSONException)
|
||||||
import Network.HTTP.Types.Header (HeaderName, hContentType)
|
import Network.HTTP.Types.Header (HeaderName, hContentType)
|
||||||
import Network.URI
|
import Network.URI
|
||||||
|
import Text.HTML.SanitizeXSS
|
||||||
import Yesod.Core.Content (ContentType)
|
import Yesod.Core.Content (ContentType)
|
||||||
import Yesod.Core.Handler (ProvidedRep, provideRepType)
|
import Yesod.Core.Handler (ProvidedRep, provideRepType)
|
||||||
|
|
||||||
|
@ -507,6 +508,7 @@ data Note = Note
|
||||||
, noteReplyTo :: Maybe FedURI
|
, noteReplyTo :: Maybe FedURI
|
||||||
, noteContext :: Maybe FedURI
|
, noteContext :: Maybe FedURI
|
||||||
, notePublished :: Maybe UTCTime
|
, notePublished :: Maybe UTCTime
|
||||||
|
, noteSource :: Text
|
||||||
, noteContent :: Text
|
, noteContent :: Text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -527,7 +529,18 @@ instance ActivityPub Note where
|
||||||
jsonldContext _ = ContextAS2
|
jsonldContext _ = ContextAS2
|
||||||
parseObject o = do
|
parseObject o = do
|
||||||
typ <- o .: "type"
|
typ <- o .: "type"
|
||||||
unless (typ == ("Note" :: Text)) $ fail "type isn't Note"
|
unless (typ == ("Note" :: Text)) $
|
||||||
|
fail "type isn't Note"
|
||||||
|
|
||||||
|
mediaType <- o .: "mediaType"
|
||||||
|
unless (mediaType == ("text/html" :: Text)) $
|
||||||
|
fail "mediaType isn't HTML"
|
||||||
|
|
||||||
|
source <- o .: "source"
|
||||||
|
sourceType <- source .: "mediaType"
|
||||||
|
unless (sourceType == ("text/markdown; variant=Pandoc" :: Text)) $
|
||||||
|
fail "source mediaType isn't Pandoc Markdown"
|
||||||
|
|
||||||
(h, attrib) <- f2l <$> o .: "attributedTo"
|
(h, attrib) <- f2l <$> o .: "attributedTo"
|
||||||
fmap (h,) $
|
fmap (h,) $
|
||||||
Note
|
Note
|
||||||
|
@ -537,8 +550,9 @@ instance ActivityPub Note where
|
||||||
<*> o .:? "inReplyTo"
|
<*> o .:? "inReplyTo"
|
||||||
<*> o .:? "context"
|
<*> o .:? "context"
|
||||||
<*> o .:? "published"
|
<*> o .:? "published"
|
||||||
<*> o .: "content"
|
<*> source .: "content"
|
||||||
toSeries host (Note mid attrib aud mreply mcontext mpublished content)
|
<*> (sanitizeBalance <$> o .: "content")
|
||||||
|
toSeries host (Note mid attrib aud mreply mcontext mpublished src content)
|
||||||
= "type" .= ("Note" :: Text)
|
= "type" .= ("Note" :: Text)
|
||||||
<> "id" .=? (l2f host <$> mid)
|
<> "id" .=? (l2f host <$> mid)
|
||||||
<> "attributedTo" .= l2f host attrib
|
<> "attributedTo" .= l2f host attrib
|
||||||
|
@ -546,7 +560,12 @@ instance ActivityPub Note where
|
||||||
<> "inReplyTo" .=? mreply
|
<> "inReplyTo" .=? mreply
|
||||||
<> "context" .=? mcontext
|
<> "context" .=? mcontext
|
||||||
<> "published" .=? mpublished
|
<> "published" .=? mpublished
|
||||||
|
<> "source" .= object
|
||||||
|
[ "content" .= src
|
||||||
|
, "mediaType" .= ("text/markdown; variant=Pandoc" :: Text)
|
||||||
|
]
|
||||||
<> "content" .= content
|
<> "content" .= content
|
||||||
|
<> "mediaType" .= ("text/html" :: Text)
|
||||||
|
|
||||||
{-
|
{-
|
||||||
parseNote :: Value -> Parser (Text, (Note, LocalURI))
|
parseNote :: Value -> Parser (Text, (Note, LocalURI))
|
||||||
|
|
|
@ -22,6 +22,6 @@ $# <http://creativecommons.org/publicdomain/zero/1.0/>.
|
||||||
<a href="#{renderFedURI $ l2f h luMsg}"}>
|
<a href="#{renderFedURI $ l2f h luMsg}"}>
|
||||||
#{showTime $ messageCreated msg}
|
#{showTime $ messageCreated msg}
|
||||||
<div>
|
<div>
|
||||||
^{showContent $ messageSource msg}
|
^{showContent $ messageContent msg}
|
||||||
<div>
|
<div>
|
||||||
<a href=@{reply msgid}>reply
|
<a href=@{reply msgid}>reply
|
||||||
|
|
Loading…
Reference in a new issue