module Router (dispatch) where
import Data.Functor ((<&>))
import Data.Result
import Effectful
import Effectful.Fail (Fail)
import Network.Wai (Request (..))
import Puppy.Context
import Puppy.Database (DB)
import Puppy.Files (Files, readFavicon)
import Puppy.Logging
import Puppy.Protocol.ActivityPub (ActivityPub)
import Puppy.Protocol.ActivityStreams (Id(..))
import qualified API.ActivityPub
import qualified API.WebFinger
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
dispatch
:: (
DB :> es,
Fail :> es,
Files :> es,
Log :> es,
ActivityPub :> es,
ServerInfo :> es
) => Request
-> LBS.ByteString
-> Eff es Result
dispatch req body = do
target <- localUrl (T.decodeUtf8 req.rawPathInfo)
let method = req.requestMethod
path = req.pathInfo
info (T.unwords ["Handling", T.decodeUtf8 method, "'/" <> T.intercalate "/" path <> "'"])
case (method, path) of
("GET", [".well-known", "webfinger"]) ->
API.WebFinger.handleQuery req
("GET", ["ap", "a", actorName])
| actorName == "server" -> API.ActivityPub.serveServerActor
| otherwise -> API.ActivityPub.serveObject (Id target)
("GET", ["ap", "o", _]) ->
API.ActivityPub.serveObject (Id target)
("POST", ["ap", "a", actorName, "inbox"]) ->
API.ActivityPub.handleInbox actorName body
("GET", []) ->
return (Bytes { contentType = "text/plain", body = "Hello :)" })
("GET", ["favicon.ico"]) ->
readFavicon <&> Bytes "image/png"
_ -> do
info "Rejected: unknown path"
return (Error { statusCode = 404, errorMessage = "Unknown path" })