Paste server written in Haskell. Fork of Hpaste, fully freedom and privacy respecting and generally improved. At the time of writing there's an instance at <http://paste.rel4tion.org>.
Clone
HTTPS:
git clone https://vervis.peers.community/repos/aoqmo
SSH:
git clone USERNAME@vervis.peers.community:aoqmo
Branches
Tags
Paste.hs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 | {-# OPTIONS -Wall -fno-warn-name-shadowing #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- | Paste controller.
module Hpaste.Controller.Paste
(handle
,pasteForm
,getPasteId
,getPasteIdKey
,withPasteKey)
where
import Hpaste.Types
import Hpaste.Controller.Cache (cache,resetCache)
import Hpaste.Model.Channel (getChannels)
import Hpaste.Model.Language (getLanguages)
import Hpaste.Model.Paste
import Hpaste.Model.Spam
import Hpaste.Types.Cache as Key
import Hpaste.View.Paste (pasteFormlet,page)
import Control.Applicative
import Control.Monad ((>=>))
import Control.Monad.IO
import Data.ByteString (ByteString)
import Data.ByteString.UTF8 (toString)
import Data.Maybe
import Data.Monoid.Operator ((++))
import Data.String (fromString)
import Data.Text (Text)
import Prelude hiding ((++))
import Safe
import Snap.App
import Text.Blaze.Html5 as H hiding (output)
import Text.Formlet
-- | Handle the paste page.
handle :: Bool -> HPCtrl ()
handle revision = do
pid <- getPasteId
justOrGoHome pid $ \(pid) -> do
html <- cache (if revision then Key.Revision pid else Key.Paste pid) $ do
getPrivate <- getParam "show_private"
paste <- model $ if isJust getPrivate
then getPrivatePasteById (pid)
else getPasteById (pid)
case paste of
Nothing -> return Nothing
Just paste -> do
hints <- model $ getHints (pasteId paste)
annotations <- model $ getAnnotations (pid)
revisions <- model $ getRevisions (pid)
ahints <- model $ mapM (getHints.pasteId) annotations
rhints <- model $ mapM (getHints.pasteId) revisions
chans <- model $ getChannels
langs <- model $ getLanguages
return $ Just $ page PastePage {
ppChans = chans
, ppLangs = langs
, ppAnnotations = annotations
, ppRevisions = revisions
, ppHints = hints
, ppPaste = paste
, ppAnnotationHints = ahints
, ppRevisionsHints = rhints
, ppRevision = revision
}
justOrGoHome html outputText
-- | Control paste annotating / submission.
pasteForm :: [Channel] -> [Language] -> Maybe Text -> Maybe Paste -> Maybe Paste -> HPCtrl Html
pasteForm channels languages defChan annotatePaste editPaste = do
params <- getParams
submittedPrivate <- isJust <$> getParam "private"
submittedPublic <- isJust <$> getParam "public"
revisions <- maybe (return []) (model . getRevisions) (fmap pasteId (annotatePaste <|> editPaste))
let formlet = PasteFormlet {
pfSubmitted = submittedPrivate || submittedPublic
, pfErrors = []
, pfParams = params
, pfChannels = channels
, pfLanguages = languages
, pfDefChan = defChan
, pfAnnotatePaste = annotatePaste
, pfEditPaste = editPaste
, pfContent = fmap pastePaste (listToMaybe revisions)
}
(getValue,_) = pasteFormlet formlet
value = formletValue getValue params
errors = either id (const []) value
(_,html) = pasteFormlet formlet { pfErrors = errors }
val = either (const Nothing) Just $ value
case val of
Nothing -> return ()
Just PasteSubmit{pasteSubmitSpamTrap=Just{}} -> goHome
Just paste -> do
spamrating <- model $ spamRating paste
if spamrating >= spamMaxLevel
then goSpamBlocked
else do
resetCache Key.Home
maybe (return ()) (resetCache . Key.Paste) $ pasteSubmitId paste
pid <- model $ createPaste languages channels paste spamrating submittedPublic
maybe (return ()) redirectToPaste pid
return html
-- | Go back to the home page with a spam indication.
goSpamBlocked :: HPCtrl ()
goSpamBlocked = redirect "/spam"
-- | Redirect to the paste's page.
redirectToPaste :: PasteId -> HPCtrl ()
redirectToPaste (PasteId pid) =
redirect $ "/" ++ fromString (show pid)
-- | Get the paste id.
getPasteId :: HPCtrl (Maybe PasteId)
getPasteId = (fmap toString >=> (fmap PasteId . readMay)) <$> getParam "id"
-- | Get the paste id by a key.
getPasteIdKey :: ByteString -> HPCtrl (Maybe PasteId)
getPasteIdKey key = (fmap toString >=> (fmap PasteId . readMay)) <$> getParam key
-- | With the
withPasteKey :: ByteString -> (Paste -> HPCtrl a) -> HPCtrl ()
withPasteKey key with = do
pid <- getPasteIdKey key
justOrGoHome pid $ \(pid ) -> do
paste <- model $ getPasteById pid
justOrGoHome paste $ \paste -> do
_ <- with paste
return ()
|