2019-04-26 12:23:49 +09:00
|
|
|
{- This file is part of Vervis.
|
|
|
|
-
|
|
|
|
- Written in 2019 by fr33domlover <fr33domlover@riseup.net>.
|
|
|
|
-
|
|
|
|
- ♡ Copying is an act of love. Please copy, reuse and share.
|
|
|
|
-
|
|
|
|
- The author(s) have dedicated all copyright and related and neighboring
|
|
|
|
- rights to this software to the public domain worldwide. This software is
|
|
|
|
- distributed without any warranty.
|
|
|
|
-
|
|
|
|
- You should have received a copy of the CC0 Public Domain Dedication along
|
|
|
|
- with this software. If not, see
|
|
|
|
- <http://creativecommons.org/publicdomain/zero/1.0/>.
|
|
|
|
-}
|
|
|
|
|
|
|
|
module Yesod.ActivityPub
|
|
|
|
( YesodActivityPub (..)
|
2019-05-04 06:04:53 +09:00
|
|
|
, deliverActivity
|
|
|
|
, forwardActivity
|
2019-06-04 06:52:34 +09:00
|
|
|
, provideHtmlAndAP
|
2019-06-07 13:26:32 +09:00
|
|
|
, provideHtmlAndAP'
|
2019-04-26 12:23:49 +09:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Prelude
|
|
|
|
|
2019-05-11 05:38:55 +09:00
|
|
|
import Control.Exception
|
|
|
|
import Control.Monad.Logger.CallStack
|
2019-04-26 12:23:49 +09:00
|
|
|
import Data.ByteString (ByteString)
|
2019-06-04 07:22:32 +09:00
|
|
|
import Data.Foldable
|
2019-04-26 12:23:49 +09:00
|
|
|
import Data.List.NonEmpty (NonEmpty)
|
|
|
|
import Data.Text (Text)
|
2019-05-11 05:38:55 +09:00
|
|
|
import Network.HTTP.Client
|
|
|
|
import Network.HTTP.Types.Header
|
|
|
|
import Yesod.Core hiding (logError, logDebug)
|
2019-04-26 12:23:49 +09:00
|
|
|
|
2019-05-04 06:04:53 +09:00
|
|
|
import qualified Data.ByteString.Lazy as BL
|
2019-05-11 05:38:55 +09:00
|
|
|
import qualified Data.Text as T
|
2019-05-04 06:04:53 +09:00
|
|
|
|
2019-04-26 12:23:49 +09:00
|
|
|
import Network.HTTP.Signature
|
|
|
|
|
2019-06-04 06:52:34 +09:00
|
|
|
import Data.Aeson.Encode.Pretty.ToEncoding
|
2019-04-26 12:23:49 +09:00
|
|
|
import Network.FedURI
|
|
|
|
import Web.ActivityPub
|
|
|
|
import Yesod.MonadSite
|
|
|
|
|
|
|
|
class Yesod site => YesodActivityPub site where
|
2019-06-04 06:52:34 +09:00
|
|
|
siteInstanceHost :: site -> Text
|
2019-05-04 06:04:53 +09:00
|
|
|
sitePostSignedHeaders :: site -> NonEmpty HeaderName
|
|
|
|
siteGetHttpSign :: (MonadSite m, SiteEnv m ~ site)
|
|
|
|
=> m (KeyId, ByteString -> Signature)
|
|
|
|
{-
|
|
|
|
siteSigVerRequiredHeaders :: site -> [HeaderName]
|
|
|
|
siteSigVerWantedHeaders :: site -> [HeaderName]
|
|
|
|
siteSigVerSeconds :: site -> Int
|
|
|
|
-}
|
2019-04-26 12:23:49 +09:00
|
|
|
|
2019-05-04 06:04:53 +09:00
|
|
|
deliverActivity
|
2019-04-26 12:23:49 +09:00
|
|
|
:: ( MonadSite m
|
|
|
|
, SiteEnv m ~ site
|
|
|
|
, HasHttpManager site
|
|
|
|
, YesodActivityPub site
|
|
|
|
)
|
|
|
|
=> FedURI
|
2019-05-04 06:04:53 +09:00
|
|
|
-> Maybe FedURI
|
2019-04-26 12:23:49 +09:00
|
|
|
-> Doc Activity
|
|
|
|
-> m (Either APPostError (Response ()))
|
2019-05-04 06:04:53 +09:00
|
|
|
deliverActivity inbox mfwd doc@(Doc hAct activity) = do
|
2019-04-26 12:23:49 +09:00
|
|
|
manager <- asksSite getHttpManager
|
|
|
|
headers <- asksSite sitePostSignedHeaders
|
|
|
|
(keyid, sign) <- siteGetHttpSign
|
|
|
|
let sender = renderFedURI $ l2f hAct (activityActor activity)
|
2019-05-11 05:38:55 +09:00
|
|
|
result <-
|
|
|
|
httpPostAP manager inbox headers keyid sign sender (Left <$> mfwd) doc
|
|
|
|
case result of
|
|
|
|
Left err ->
|
|
|
|
logError $ T.concat
|
|
|
|
[ "deliverActivity to inbox <", renderFedURI inbox
|
|
|
|
, "> error: ", T.pack $ displayException err
|
|
|
|
]
|
|
|
|
Right resp ->
|
|
|
|
logDebug $ T.concat
|
|
|
|
[ "deliverActivity to inbox <", renderFedURI inbox
|
|
|
|
, "> success: ", T.pack $ show $ responseStatus resp
|
|
|
|
]
|
|
|
|
return result
|
2019-05-04 06:04:53 +09:00
|
|
|
|
|
|
|
forwardActivity
|
|
|
|
:: ( MonadSite m
|
|
|
|
, SiteEnv m ~ site
|
|
|
|
, HasHttpManager site
|
|
|
|
, YesodActivityPub site
|
|
|
|
)
|
|
|
|
=> FedURI
|
|
|
|
-> ByteString
|
|
|
|
-> Route site
|
|
|
|
-> BL.ByteString
|
|
|
|
-> m (Either APPostError (Response ()))
|
|
|
|
forwardActivity inbox sig rSender body = do
|
|
|
|
manager <- asksSite getHttpManager
|
|
|
|
headers <- asksSite sitePostSignedHeaders
|
|
|
|
(keyid, sign) <- siteGetHttpSign
|
|
|
|
renderUrl <- askUrlRender
|
|
|
|
let sender = renderUrl rSender
|
2019-05-11 05:38:55 +09:00
|
|
|
result <-
|
|
|
|
httpPostAPBytes manager inbox headers keyid sign sender (Just $ Right sig) body
|
|
|
|
case result of
|
|
|
|
Left err ->
|
|
|
|
logError $ T.concat
|
|
|
|
[ "forwardActivity to inbox <", renderFedURI inbox
|
|
|
|
, "> error: ", T.pack $ displayException err
|
|
|
|
]
|
|
|
|
Right resp ->
|
|
|
|
logDebug $ T.concat
|
|
|
|
[ "forwardActivity to inbox <", renderFedURI inbox
|
|
|
|
, "> success: ", T.pack $ show $ responseStatus resp
|
|
|
|
]
|
|
|
|
return result
|
2019-06-04 06:52:34 +09:00
|
|
|
|
|
|
|
provideHtmlAndAP
|
|
|
|
:: (YesodActivityPub site, ActivityPub a)
|
|
|
|
=> a -> WidgetFor site () -> HandlerFor site TypedContent
|
|
|
|
provideHtmlAndAP object widget = do
|
|
|
|
host <- getsYesod siteInstanceHost
|
2019-06-07 13:26:32 +09:00
|
|
|
provideHtmlAndAP' host object widget
|
|
|
|
|
|
|
|
provideHtmlAndAP'
|
|
|
|
:: (YesodActivityPub site, ActivityPub a)
|
|
|
|
=> Text -> a -> WidgetFor site () -> HandlerFor site TypedContent
|
|
|
|
provideHtmlAndAP' host object widget = selectRep $ do
|
2019-06-04 06:52:34 +09:00
|
|
|
let doc = Doc host object
|
2019-06-07 13:26:32 +09:00
|
|
|
provideAP $ pure doc
|
|
|
|
provideRep $ do
|
|
|
|
mval <- lookupGetParam "prettyjson"
|
|
|
|
defaultLayout $
|
|
|
|
case mval of
|
|
|
|
Just "true" ->
|
|
|
|
[whamlet|
|
|
|
|
<div><pre>#{encodePrettyToLazyText doc}
|
|
|
|
|]
|
|
|
|
_ -> do
|
|
|
|
widget
|
|
|
|
mroute <- getCurrentRoute
|
|
|
|
for_ mroute $ \ route -> do
|
|
|
|
params <- reqGetParams <$> getRequest
|
|
|
|
let pj = ("prettyjson", "true")
|
2019-06-04 06:52:34 +09:00
|
|
|
[whamlet|
|
2019-06-07 13:26:32 +09:00
|
|
|
<div>
|
|
|
|
<a href=@?{(route, pj : params)}>
|
|
|
|
[See JSON]
|
2019-06-04 06:52:34 +09:00
|
|
|
|]
|