hls lint
This commit is contained in:
parent
2f7db922fa
commit
30fa32897a
|
@ -12,7 +12,7 @@ getAddViewR = do
|
||||||
userId <- requireAuthId
|
userId <- requireAuthId
|
||||||
|
|
||||||
murl <- lookupGetParam "url"
|
murl <- lookupGetParam "url"
|
||||||
mformdb <- runDB (pure . fmap _toBookmarkForm =<< fetchBookmarkByUrl userId murl)
|
mformdb <- runDB (fmap _toBookmarkForm <$> fetchBookmarkByUrl userId murl)
|
||||||
formurl <- bookmarkFormUrl
|
formurl <- bookmarkFormUrl
|
||||||
|
|
||||||
let renderEl = "addForm" :: Text
|
let renderEl = "addForm" :: Text
|
||||||
|
@ -31,12 +31,12 @@ getAddViewR = do
|
||||||
bookmarkFormUrl :: Handler BookmarkForm
|
bookmarkFormUrl :: Handler BookmarkForm
|
||||||
bookmarkFormUrl = do
|
bookmarkFormUrl = do
|
||||||
Entity _ user <- requireAuth
|
Entity _ user <- requireAuth
|
||||||
url <- lookupGetParam "url" >>= pure . fromMaybe ""
|
url <- lookupGetParam "url" <&> fromMaybe ""
|
||||||
title <- lookupGetParam "title"
|
title <- lookupGetParam "title"
|
||||||
description <- lookupGetParam "description" >>= pure . fmap Textarea
|
description <- lookupGetParam "description" <&> fmap Textarea
|
||||||
tags <- lookupGetParam "tags"
|
tags <- lookupGetParam "tags"
|
||||||
private <- lookupGetParam "private" >>= pure . fmap parseChk <&> (<|> Just (userPrivateDefault user))
|
private <- lookupGetParam "private" <&> fmap parseChk <&> (<|> Just (userPrivateDefault user))
|
||||||
toread <- lookupGetParam "toread" >>= pure . fmap parseChk
|
toread <- lookupGetParam "toread" <&> fmap parseChk
|
||||||
pure $
|
pure $
|
||||||
BookmarkForm
|
BookmarkForm
|
||||||
{ _url = url
|
{ _url = url
|
||||||
|
|
|
@ -18,26 +18,26 @@ import Network.Wai (requestHeaderHost)
|
||||||
import qualified Network.Connection as NC
|
import qualified Network.Connection as NC
|
||||||
|
|
||||||
shouldArchiveBookmark :: User -> Key Bookmark -> Handler Bool
|
shouldArchiveBookmark :: User -> Key Bookmark -> Handler Bool
|
||||||
shouldArchiveBookmark user kbid = do
|
shouldArchiveBookmark user kbid =
|
||||||
runDB (get kbid) >>= \case
|
runDB (get kbid) >>= \case
|
||||||
Nothing -> pure False
|
Nothing -> pure False
|
||||||
|
|
||||||
Just bm -> do
|
Just bm -> do
|
||||||
pure $
|
pure $
|
||||||
(isNothing $ bookmarkArchiveHref bm) &&
|
isNothing (bookmarkArchiveHref bm) &&
|
||||||
(bookmarkShared bm)
|
bookmarkShared bm
|
||||||
&& not (_isArchiveBlacklisted bm)
|
&& not (_isArchiveBlacklisted bm)
|
||||||
&& userArchiveDefault user
|
&& userArchiveDefault user
|
||||||
|
|
||||||
getArchiveManager :: Handler Manager
|
getArchiveManager :: Handler Manager
|
||||||
getArchiveManager = do
|
getArchiveManager = do
|
||||||
appSettings <- pure . appSettings =<< getYesod
|
appSettings <- appSettings <$> getYesod
|
||||||
let mSocks =
|
let mSocks =
|
||||||
NC.SockSettingsSimple <$>
|
NC.SockSettingsSimple <$>
|
||||||
fmap unpack (appArchiveSocksProxyHost appSettings) <*>
|
fmap unpack (appArchiveSocksProxyHost appSettings) <*>
|
||||||
fmap toEnum (appArchiveSocksProxyPort appSettings)
|
fmap toEnum (appArchiveSocksProxyPort appSettings)
|
||||||
NH.newTlsManagerWith (NH.mkManagerSettings def mSocks)
|
NH.newTlsManagerWith (NH.mkManagerSettings def mSocks)
|
||||||
|
|
||||||
|
|
||||||
archiveBookmarkUrl :: Key Bookmark -> String -> Handler ()
|
archiveBookmarkUrl :: Key Bookmark -> String -> Handler ()
|
||||||
archiveBookmarkUrl kbid url =
|
archiveBookmarkUrl kbid url =
|
||||||
|
@ -55,13 +55,13 @@ archiveBookmarkUrl kbid url =
|
||||||
case status of
|
case status of
|
||||||
s | s == NH.status200 ->
|
s | s == NH.status200 ->
|
||||||
for_ (lookup "Refresh" headers >>= _parseRefreshHeaderUrl) updateArchiveUrl
|
for_ (lookup "Refresh" headers >>= _parseRefreshHeaderUrl) updateArchiveUrl
|
||||||
s | s == NH.status302 || s == NH.status307 ->
|
s | s == NH.status302 || s == NH.status307 ->
|
||||||
for_ (lookup "Location" headers) (updateArchiveUrl . decodeUtf8)
|
for_ (lookup "Location" headers) (updateArchiveUrl . decodeUtf8)
|
||||||
_ -> $(logError) (pack (show res)))
|
_ -> $(logError) (pack (show res)))
|
||||||
`catch` (\(e::SomeException) -> ($(logError) $ (pack.show) e) >> throwIO e)
|
`catch` (\(e::SomeException) -> ($(logError) $ (pack.show) e) >> throwIO e)
|
||||||
|
|
||||||
_isArchiveBlacklisted :: Bookmark -> Bool
|
_isArchiveBlacklisted :: Bookmark -> Bool
|
||||||
_isArchiveBlacklisted (Bookmark {..}) =
|
_isArchiveBlacklisted Bookmark {..} =
|
||||||
[ "hulu"
|
[ "hulu"
|
||||||
, "livestream"
|
, "livestream"
|
||||||
, "netflix"
|
, "netflix"
|
||||||
|
@ -77,13 +77,13 @@ _isArchiveBlacklisted (Bookmark {..}) =
|
||||||
_parseRefreshHeaderUrl :: ByteString -> Maybe Text
|
_parseRefreshHeaderUrl :: ByteString -> Maybe Text
|
||||||
_parseRefreshHeaderUrl h = do
|
_parseRefreshHeaderUrl h = do
|
||||||
let u = BS8.drop 1 $ BS8.dropWhile (/= '=') h
|
let u = BS8.drop 1 $ BS8.dropWhile (/= '=') h
|
||||||
if (not (null u))
|
if not (null u)
|
||||||
then Just $ decodeUtf8 u
|
then Just $ decodeUtf8 u
|
||||||
else Nothing
|
else Nothing
|
||||||
|
|
||||||
_fetchArchiveSubmitInfo :: Handler (Either String (String , String))
|
_fetchArchiveSubmitInfo :: Handler (Either String (String , String))
|
||||||
_fetchArchiveSubmitInfo = do
|
_fetchArchiveSubmitInfo = do
|
||||||
req <- buildRequest "https://archive.li/"
|
req <- buildRequest "https://archive.li/"
|
||||||
manager <- getArchiveManager
|
manager <- getArchiveManager
|
||||||
res <- liftIO $ NH.httpLbs req manager
|
res <- liftIO $ NH.httpLbs req manager
|
||||||
let body = LBS.toStrict (responseBody res)
|
let body = LBS.toStrict (responseBody res)
|
||||||
|
@ -92,13 +92,12 @@ _fetchArchiveSubmitInfo = do
|
||||||
if statusCode (responseStatus res) == 200
|
if statusCode (responseStatus res) == 200
|
||||||
then pure $ (,) <$> action <*> submitId
|
then pure $ (,) <$> action <*> submitId
|
||||||
else pure $ Left $ "Invalid statusCode: " <> show (responseStatus res)
|
else pure $ Left $ "Invalid statusCode: " <> show (responseStatus res)
|
||||||
|
|
||||||
|
|
||||||
_parseSubstring :: AP8.Parser ByteString -> AP8.Parser Char -> BS.ByteString -> Either String String
|
_parseSubstring :: AP8.Parser ByteString -> AP8.Parser Char -> BS.ByteString -> Either String String
|
||||||
_parseSubstring start inner res = do
|
_parseSubstring start inner = AP8.parseOnly (skipAnyTill start >> AP8.many1 inner)
|
||||||
(flip AP8.parseOnly) res (skipAnyTill start >> AP8.many1 inner)
|
|
||||||
where
|
where
|
||||||
skipAnyTill end = go where go = end *> pure () <|> AP8.anyChar *> go
|
skipAnyTill end = go where go = end $> () <|> AP8.anyChar *> go
|
||||||
|
|
||||||
|
|
||||||
fetchPageTitle :: String -> Handler (Either String Text)
|
fetchPageTitle :: String -> Handler (Either String Text)
|
||||||
|
@ -113,23 +112,23 @@ fetchPageTitle url =
|
||||||
pure (Left (show e)))
|
pure (Left (show e)))
|
||||||
where
|
where
|
||||||
parseTitle bs =
|
parseTitle bs =
|
||||||
(flip AP.parseOnly) bs do
|
flip AP.parseOnly bs do
|
||||||
_ <- skipAnyTill (AP.string "<title")
|
_ <- skipAnyTill (AP.string "<title")
|
||||||
_ <- skipAnyTill (AP.string ">")
|
_ <- skipAnyTill (AP.string ">")
|
||||||
let lt = toEnum (ord '<')
|
let lt = toEnum (ord '<')
|
||||||
AP.takeTill (== lt)
|
AP.takeTill (== lt)
|
||||||
decodeHtmlBs = toStrict . toLazyText . htmlEncodedText . decodeUtf8
|
decodeHtmlBs = toStrict . toLazyText . htmlEncodedText . decodeUtf8
|
||||||
skipAnyTill end = go where go = end *> pure () <|> AP.anyWord8 *> go
|
skipAnyTill end = go where go = end $> () <|> AP.anyWord8 *> go
|
||||||
|
|
||||||
_buildArchiveSubmitRequest :: (String, String) -> String -> Handler NH.Request
|
_buildArchiveSubmitRequest :: (String, String) -> String -> Handler NH.Request
|
||||||
_buildArchiveSubmitRequest (action, submitId) href = do
|
_buildArchiveSubmitRequest (action, submitId) href = do
|
||||||
req <- buildRequest ("POST " <> action)
|
req <- buildRequest ("POST " <> action)
|
||||||
pure $ req
|
pure $ req
|
||||||
{ NH.requestHeaders = ("Content-Type", "application/x-www-form-urlencoded") : NH.requestHeaders req
|
{ NH.requestHeaders = ("Content-Type", "application/x-www-form-urlencoded") : NH.requestHeaders req
|
||||||
, NH.requestBody =
|
, NH.requestBody =
|
||||||
NH.RequestBodyLBS $
|
NH.RequestBodyLBS $
|
||||||
WH.urlEncodeAsForm
|
WH.urlEncodeAsForm
|
||||||
(([("submitid", submitId), ("url", href)]) :: [(String, String)])
|
([("submitid", submitId), ("url", href)] :: [(String, String)])
|
||||||
, NH.redirectCount = 0
|
, NH.redirectCount = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +144,6 @@ buildRequest url = do
|
||||||
|
|
||||||
_archiveUserAgent :: Handler ByteString
|
_archiveUserAgent :: Handler ByteString
|
||||||
_archiveUserAgent = do
|
_archiveUserAgent = do
|
||||||
mHost <- pure . requestHeaderHost . reqWaiRequest =<< getRequest
|
mHost <- requestHeaderHost . reqWaiRequest <$> getRequest
|
||||||
pure $ ("espial-" <>) (maybe "" (BS8.takeWhile (/= ':')) mHost)
|
pure $ "espial-" <> maybe "" (BS8.takeWhile (/= ':')) mHost
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,7 @@ lookupPagingParams =
|
||||||
|
|
||||||
getUrlParam :: (Read a) => Text -> Handler (Maybe a)
|
getUrlParam :: (Read a) => Text -> Handler (Maybe a)
|
||||||
getUrlParam name = do
|
getUrlParam name = do
|
||||||
p <- fmap parseMaybe (lookupGetParam name)
|
fmap parseMaybe (lookupGetParam name)
|
||||||
pure p
|
|
||||||
where
|
where
|
||||||
parseMaybe x = readMaybe . unpack =<< x
|
parseMaybe x = readMaybe . unpack =<< x
|
||||||
|
|
||||||
|
@ -68,4 +67,4 @@ getTagCloudMode isowner tags = do
|
||||||
Just (TagCloudModeRelated e _) -> TagCloudModeTop e 200
|
Just (TagCloudModeRelated e _) -> TagCloudModeTop e 200
|
||||||
Just m -> m
|
Just m -> m
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,5 @@ module Handler.Docs where
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
getDocsSearchR :: Handler Html
|
getDocsSearchR :: Handler Html
|
||||||
getDocsSearchR = popupLayout $
|
getDocsSearchR = popupLayout
|
||||||
$(widgetFile "docs-search")
|
$(widgetFile "docs-search")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
|
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
module Handler.Notes where
|
module Handler.Notes where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
@ -16,8 +17,8 @@ getNotesR unamep@(UserNameP uname) = do
|
||||||
mquery <- lookupGetParam queryp
|
mquery <- lookupGetParam queryp
|
||||||
let limit = maybe 20 fromIntegral limit'
|
let limit = maybe 20 fromIntegral limit'
|
||||||
page = maybe 1 fromIntegral page'
|
page = maybe 1 fromIntegral page'
|
||||||
mqueryp = fmap (\q -> (queryp, q)) mquery
|
mqueryp = fmap (queryp,) mquery
|
||||||
isowner = maybe False (== uname) mauthuname
|
isowner = Just uname == mauthuname
|
||||||
(bcount, notes) <- runDB do
|
(bcount, notes) <- runDB do
|
||||||
Entity userId user <- getBy404 (UniqueUserName uname)
|
Entity userId user <- getBy404 (UniqueUserName uname)
|
||||||
let sharedp = if isowner then SharedAll else SharedPublic
|
let sharedp = if isowner then SharedAll else SharedPublic
|
||||||
|
@ -45,7 +46,7 @@ getNoteR :: UserNameP -> NtSlug -> Handler Html
|
||||||
getNoteR unamep@(UserNameP uname) slug = do
|
getNoteR unamep@(UserNameP uname) slug = do
|
||||||
mauthuname <- maybeAuthUsername
|
mauthuname <- maybeAuthUsername
|
||||||
let renderEl = "note" :: Text
|
let renderEl = "note" :: Text
|
||||||
isowner = maybe False (== uname) mauthuname
|
isowner = Just uname == mauthuname
|
||||||
note <-
|
note <-
|
||||||
runDB $
|
runDB $
|
||||||
do Entity userId user <- getBy404 (UniqueUserName uname)
|
do Entity userId user <- getBy404 (UniqueUserName uname)
|
||||||
|
@ -143,10 +144,10 @@ _toNote userId NoteForm {..} = do
|
||||||
, noteLength = length _text
|
, noteLength = length _text
|
||||||
, noteTitle = fromMaybe "" _title
|
, noteTitle = fromMaybe "" _title
|
||||||
, noteText = maybe "" unTextarea _text
|
, noteText = maybe "" unTextarea _text
|
||||||
, noteIsMarkdown = fromMaybe False _isMarkdown
|
, noteIsMarkdown = Just True == _isMarkdown
|
||||||
, noteShared = fromMaybe False _shared
|
, noteShared = Just True == _shared
|
||||||
, noteCreated = fromMaybe time (fmap unUTCTimeStr _created)
|
, noteCreated = maybe time unUTCTimeStr _created
|
||||||
, noteUpdated = fromMaybe time (fmap unUTCTimeStr _updated)
|
, noteUpdated = maybe time unUTCTimeStr _updated
|
||||||
}
|
}
|
||||||
|
|
||||||
noteToRssEntry :: UserNameP -> Entity Note -> FeedEntry (Route App)
|
noteToRssEntry :: UserNameP -> Entity Note -> FeedEntry (Route App)
|
||||||
|
@ -167,7 +168,7 @@ getNotesFeedR unamep@(UserNameP uname) = do
|
||||||
mquery <- lookupGetParam "query"
|
mquery <- lookupGetParam "query"
|
||||||
let limit = maybe 20 fromIntegral limit'
|
let limit = maybe 20 fromIntegral limit'
|
||||||
page = maybe 1 fromIntegral page'
|
page = maybe 1 fromIntegral page'
|
||||||
isowner = maybe False (== uname) mauthuname
|
isowner = Just uname == mauthuname
|
||||||
(_, notes) <- runDB do
|
(_, notes) <- runDB do
|
||||||
Entity userId user <- getBy404 (UniqueUserName uname)
|
Entity userId user <- getBy404 (UniqueUserName uname)
|
||||||
when (not isowner && userPrivacyLock user)
|
when (not isowner && userPrivacyLock user)
|
||||||
|
@ -176,7 +177,7 @@ getNotesFeedR unamep@(UserNameP uname) = do
|
||||||
let (descr :: Html) = toHtml $ H.text (uname <> " notes")
|
let (descr :: Html) = toHtml $ H.text (uname <> " notes")
|
||||||
entries = map (noteToRssEntry unamep) notes
|
entries = map (noteToRssEntry unamep) notes
|
||||||
updated <- case maximumMay (map feedEntryUpdated entries) of
|
updated <- case maximumMay (map feedEntryUpdated entries) of
|
||||||
Nothing -> liftIO $ getCurrentTime
|
Nothing -> liftIO getCurrentTime
|
||||||
Just m -> return m
|
Just m -> return m
|
||||||
rssFeed $
|
rssFeed $
|
||||||
Feed
|
Feed
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
|
{-# OPTIONS_GHC -fno-warn-unused-matches #-}
|
||||||
|
{-# LANGUAGE TupleSections #-}
|
||||||
module Handler.User where
|
module Handler.User where
|
||||||
|
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
@ -9,7 +10,7 @@ import Yesod.RssFeed
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
|
|
||||||
getUserR :: UserNameP -> Handler Html
|
getUserR :: UserNameP -> Handler Html
|
||||||
getUserR uname@(UserNameP name) = do
|
getUserR uname@(UserNameP name) =
|
||||||
_getUser uname SharedAll FilterAll (TagsP [])
|
_getUser uname SharedAll FilterAll (TagsP [])
|
||||||
|
|
||||||
getUserSharedR :: UserNameP -> SharedP -> Handler Html
|
getUserSharedR :: UserNameP -> SharedP -> Handler Html
|
||||||
|
@ -21,8 +22,7 @@ getUserFilterR uname filterp =
|
||||||
_getUser uname SharedAll filterp (TagsP [])
|
_getUser uname SharedAll filterp (TagsP [])
|
||||||
|
|
||||||
getUserTagsR :: UserNameP -> TagsP -> Handler Html
|
getUserTagsR :: UserNameP -> TagsP -> Handler Html
|
||||||
getUserTagsR uname pathtags =
|
getUserTagsR uname = _getUser uname SharedAll FilterAll
|
||||||
_getUser uname SharedAll FilterAll pathtags
|
|
||||||
|
|
||||||
_getUser :: UserNameP -> SharedP -> FilterP -> TagsP -> Handler Html
|
_getUser :: UserNameP -> SharedP -> FilterP -> TagsP -> Handler Html
|
||||||
_getUser unamep@(UserNameP uname) sharedp' filterp' (TagsP pathtags) = do
|
_getUser unamep@(UserNameP uname) sharedp' filterp' (TagsP pathtags) = do
|
||||||
|
@ -30,15 +30,15 @@ _getUser unamep@(UserNameP uname) sharedp' filterp' (TagsP pathtags) = do
|
||||||
(limit', page') <- lookupPagingParams
|
(limit', page') <- lookupPagingParams
|
||||||
let limit = maybe 120 fromIntegral limit'
|
let limit = maybe 120 fromIntegral limit'
|
||||||
page = maybe 1 fromIntegral page'
|
page = maybe 1 fromIntegral page'
|
||||||
isowner = maybe False (== uname) mauthuname
|
isowner = Just uname == mauthuname
|
||||||
sharedp = if isowner then sharedp' else SharedPublic
|
sharedp = if isowner then sharedp' else SharedPublic
|
||||||
filterp = case filterp' of
|
filterp = case filterp' of
|
||||||
FilterSingle _ -> filterp'
|
FilterSingle _ -> filterp'
|
||||||
_ -> if isowner then filterp' else FilterAll
|
_ -> if isowner then filterp' else FilterAll
|
||||||
isAll = filterp == FilterAll && sharedp == SharedAll && pathtags == []
|
isAll = filterp == FilterAll && sharedp == SharedAll && null pathtags
|
||||||
queryp = "query" :: Text
|
queryp = "query" :: Text
|
||||||
mquery <- lookupGetParam queryp
|
mquery <- lookupGetParam queryp
|
||||||
let mqueryp = fmap (\q -> (queryp, q)) mquery
|
let mqueryp = fmap (queryp,) mquery
|
||||||
(bcount, btmarks) <- runDB $ do
|
(bcount, btmarks) <- runDB $ do
|
||||||
Entity userId user <- getBy404 (UniqueUserName uname)
|
Entity userId user <- getBy404 (UniqueUserName uname)
|
||||||
when (not isowner && userPrivacyLock user)
|
when (not isowner && userPrivacyLock user)
|
||||||
|
@ -71,7 +71,7 @@ _getUser unamep@(UserNameP uname) sharedp' filterp' (TagsP pathtags) = do
|
||||||
|]
|
|]
|
||||||
|
|
||||||
-- Form
|
-- Form
|
||||||
|
|
||||||
postUserTagCloudR :: Handler ()
|
postUserTagCloudR :: Handler ()
|
||||||
postUserTagCloudR = do
|
postUserTagCloudR = do
|
||||||
userId <- requireAuthId
|
userId <- requireAuthId
|
||||||
|
@ -91,7 +91,7 @@ postUserTagCloudModeR = do
|
||||||
_updateTagCloudMode mode
|
_updateTagCloudMode mode
|
||||||
|
|
||||||
_updateTagCloudMode :: TagCloudMode -> Handler ()
|
_updateTagCloudMode :: TagCloudMode -> Handler ()
|
||||||
_updateTagCloudMode mode =
|
_updateTagCloudMode mode =
|
||||||
case mode of
|
case mode of
|
||||||
TagCloudModeTop _ _ -> setTagCloudMode mode
|
TagCloudModeTop _ _ -> setTagCloudMode mode
|
||||||
TagCloudModeLowerBound _ _ -> setTagCloudMode mode
|
TagCloudModeLowerBound _ _ -> setTagCloudMode mode
|
||||||
|
@ -99,7 +99,7 @@ _updateTagCloudMode mode =
|
||||||
TagCloudModeNone -> notFound
|
TagCloudModeNone -> notFound
|
||||||
|
|
||||||
bookmarkToRssEntry :: (Entity Bookmark, Maybe Text) -> FeedEntry Text
|
bookmarkToRssEntry :: (Entity Bookmark, Maybe Text) -> FeedEntry Text
|
||||||
bookmarkToRssEntry ((Entity entryId entry), tags) =
|
bookmarkToRssEntry (Entity entryId entry, tags) =
|
||||||
FeedEntry
|
FeedEntry
|
||||||
{ feedEntryLink = bookmarkHref entry
|
{ feedEntryLink = bookmarkHref entry
|
||||||
, feedEntryUpdated = bookmarkTime entry
|
, feedEntryUpdated = bookmarkTime entry
|
||||||
|
@ -116,7 +116,7 @@ getUserFeedR unamep@(UserNameP uname) = do
|
||||||
let limit = maybe 120 fromIntegral limit'
|
let limit = maybe 120 fromIntegral limit'
|
||||||
page = maybe 1 fromIntegral page'
|
page = maybe 1 fromIntegral page'
|
||||||
queryp = "query" :: Text
|
queryp = "query" :: Text
|
||||||
isowner = maybe False (== uname) mauthuname
|
isowner = Just uname == mauthuname
|
||||||
mquery <- lookupGetParam queryp
|
mquery <- lookupGetParam queryp
|
||||||
(_, btmarks) <- runDB $ do
|
(_, btmarks) <- runDB $ do
|
||||||
Entity userId user <- getBy404 (UniqueUserName uname)
|
Entity userId user <- getBy404 (UniqueUserName uname)
|
||||||
|
@ -126,7 +126,7 @@ getUserFeedR unamep@(UserNameP uname) = do
|
||||||
let (descr :: Html) = toHtml $ H.text ("Bookmarks saved by " <> uname)
|
let (descr :: Html) = toHtml $ H.text ("Bookmarks saved by " <> uname)
|
||||||
entries = map bookmarkToRssEntry btmarks
|
entries = map bookmarkToRssEntry btmarks
|
||||||
updated <- case maximumMay (map feedEntryUpdated entries) of
|
updated <- case maximumMay (map feedEntryUpdated entries) of
|
||||||
Nothing -> liftIO $ getCurrentTime
|
Nothing -> liftIO getCurrentTime
|
||||||
Just m -> return m
|
Just m -> return m
|
||||||
render <- getUrlRender
|
render <- getUrlRender
|
||||||
rssFeedText $
|
rssFeedText $
|
||||||
|
|
|
@ -48,13 +48,13 @@ aFormToMaybeGetSuccess
|
||||||
:: MonadHandler f
|
:: MonadHandler f
|
||||||
=> AForm f a -> f (Maybe a)
|
=> AForm f a -> f (Maybe a)
|
||||||
aFormToMaybeGetSuccess =
|
aFormToMaybeGetSuccess =
|
||||||
fmap maybeSuccess . fmap fst . runFormGet . const . fmap fst . aFormToForm
|
fmap (maybeSuccess . fst) . runFormGet . const . fmap fst . aFormToForm
|
||||||
|
|
||||||
aFormToMaybePostSuccess
|
aFormToMaybePostSuccess
|
||||||
:: MonadHandlerForm f
|
:: MonadHandlerForm f
|
||||||
=> AForm f a -> f (Maybe a)
|
=> AForm f a -> f (Maybe a)
|
||||||
aFormToMaybePostSuccess =
|
aFormToMaybePostSuccess =
|
||||||
fmap maybeSuccess . fmap fst . runFormPostNoToken . const . fmap fst . aFormToForm
|
fmap (maybeSuccess . fst) . runFormPostNoToken . const . fmap fst . aFormToForm
|
||||||
|
|
||||||
maybeSuccess :: FormResult a -> Maybe a
|
maybeSuccess :: FormResult a -> Maybe a
|
||||||
maybeSuccess (FormSuccess a) = Just a
|
maybeSuccess (FormSuccess a) = Just a
|
||||||
|
@ -83,4 +83,4 @@ attrs n f =
|
||||||
}
|
}
|
||||||
|
|
||||||
cls :: [Text] -> FieldSettings master -> FieldSettings master
|
cls :: [Text] -> FieldSettings master -> FieldSettings master
|
||||||
cls n = attrs [("class", intercalate " " n)]
|
cls n = attrs [("class", unwords n)]
|
||||||
|
|
154
src/Model.hs
154
src/Model.hs
|
@ -138,12 +138,12 @@ migrateIndexes =
|
||||||
, "CREATE INDEX IF NOT EXISTS idx_note_user_created ON note (user_id, created DESC)"
|
, "CREATE INDEX IF NOT EXISTS idx_note_user_created ON note (user_id, created DESC)"
|
||||||
]
|
]
|
||||||
|
|
||||||
sqlite_group_concat ::
|
sqliteGroupConcat ::
|
||||||
PersistField a
|
PersistField a
|
||||||
=> SqlExpr (Value a)
|
=> SqlExpr (Value a)
|
||||||
-> SqlExpr (Value a)
|
-> SqlExpr (Value a)
|
||||||
-> SqlExpr (Value Text)
|
-> SqlExpr (Value Text)
|
||||||
sqlite_group_concat expr sep = unsafeSqlFunction "GROUP_CONCAT" [expr, sep]
|
sqliteGroupConcat expr sep = unsafeSqlFunction "GROUP_CONCAT" [expr, sep]
|
||||||
|
|
||||||
authenticatePassword :: Text -> Text -> DB (Maybe (Entity User))
|
authenticatePassword :: Text -> Text -> DB (Maybe (Entity User))
|
||||||
authenticatePassword username password = do
|
authenticatePassword username password = do
|
||||||
|
@ -156,7 +156,7 @@ authenticatePassword username password = do
|
||||||
else return Nothing
|
else return Nothing
|
||||||
|
|
||||||
getUserByName :: UserNameP -> DB (Maybe (Entity User))
|
getUserByName :: UserNameP -> DB (Maybe (Entity User))
|
||||||
getUserByName (UserNameP uname) = do
|
getUserByName (UserNameP uname) =
|
||||||
selectFirst [UserName CP.==. uname] []
|
selectFirst [UserName CP.==. uname] []
|
||||||
|
|
||||||
-- returns a list of pair of bookmark with tags merged into a string
|
-- returns a list of pair of bookmark with tags merged into a string
|
||||||
|
@ -186,12 +186,12 @@ bookmarksTagsQuery userId sharedp filterp tags mquery limit' page =
|
||||||
where_ (t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId)
|
where_ (t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId)
|
||||||
groupBy (t ^. BookmarkTagBookmarkId)
|
groupBy (t ^. BookmarkTagBookmarkId)
|
||||||
orderBy [asc (t ^. BookmarkTagSeq)]
|
orderBy [asc (t ^. BookmarkTagSeq)]
|
||||||
pure $ sqlite_group_concat (t ^. BookmarkTagTag) (val " ")))
|
pure $ sqliteGroupConcat (t ^. BookmarkTagTag) (val " ")))
|
||||||
where
|
where
|
||||||
_whereClause b = do
|
_whereClause b = do
|
||||||
where_ $
|
where_ $
|
||||||
foldl (\expr tag ->
|
foldl (\expr tag ->
|
||||||
expr &&. (exists $ -- each tag becomes an exists constraint
|
expr &&. exists ( -- each tag becomes an exists constraint
|
||||||
from (table @BookmarkTag) >>= \t ->
|
from (table @BookmarkTag) >>= \t ->
|
||||||
where_ (t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId &&.
|
where_ (t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId &&.
|
||||||
(t ^. BookmarkTagTag `like` val tag))))
|
(t ^. BookmarkTagTag `like` val tag))))
|
||||||
|
@ -217,13 +217,12 @@ bookmarksTagsQuery userId sharedp filterp tags mquery limit' page =
|
||||||
wild s = (%) ++. val s ++. (%)
|
wild s = (%) ++. val s ++. (%)
|
||||||
toLikeB field s = b ^. field `like` wild s
|
toLikeB field s = b ^. field `like` wild s
|
||||||
p_allFields =
|
p_allFields =
|
||||||
(toLikeB BookmarkHref term) ||.
|
toLikeB BookmarkHref term ||.
|
||||||
(toLikeB BookmarkDescription term) ||.
|
toLikeB BookmarkDescription term ||.
|
||||||
(toLikeB BookmarkExtended term) ||.
|
toLikeB BookmarkExtended term ||.
|
||||||
(exists $ from (table @BookmarkTag) >>= \t -> where_ $
|
exists (from (table @BookmarkTag) >>= \t -> where_ $
|
||||||
(t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId) &&.
|
(t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId) &&.
|
||||||
(t ^. BookmarkTagTag `like` (wild term))
|
(t ^. BookmarkTagTag `like` wild term))
|
||||||
)
|
|
||||||
p_onefield = p_url <|> p_title <|> p_description <|> p_tags <|> p_after <|> p_before
|
p_onefield = p_url <|> p_title <|> p_description <|> p_tags <|> p_after <|> p_before
|
||||||
where
|
where
|
||||||
p_url = "url:" *> fmap (toLikeB BookmarkHref) P.takeText
|
p_url = "url:" *> fmap (toLikeB BookmarkHref) P.takeText
|
||||||
|
@ -248,8 +247,8 @@ allUserBookmarks user =
|
||||||
where_ (t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId)
|
where_ (t ^. BookmarkTagBookmarkId ==. b ^. BookmarkId)
|
||||||
groupBy (t ^. BookmarkTagBookmarkId)
|
groupBy (t ^. BookmarkTagBookmarkId)
|
||||||
orderBy [asc (t ^. BookmarkTagSeq)]
|
orderBy [asc (t ^. BookmarkTagSeq)]
|
||||||
pure $ sqlite_group_concat (t ^. BookmarkTagTag) (val " "))
|
pure $ sqliteGroupConcat (t ^. BookmarkTagTag) (val " "))
|
||||||
|
|
||||||
parseSearchQuery ::
|
parseSearchQuery ::
|
||||||
(Text -> SqlExpr (Value Bool))
|
(Text -> SqlExpr (Value Bool))
|
||||||
-> Text
|
-> Text
|
||||||
|
@ -294,7 +293,7 @@ getNoteList key mquery sharedp limit' page =
|
||||||
(select $ do
|
(select $ do
|
||||||
b <- from (table @Note)
|
b <- from (table @Note)
|
||||||
_whereClause b
|
_whereClause b
|
||||||
pure $ countRows)
|
pure countRows)
|
||||||
<*> (select $ do
|
<*> (select $ do
|
||||||
b <- from (table @Note)
|
b <- from (table @Note)
|
||||||
_whereClause b
|
_whereClause b
|
||||||
|
@ -304,7 +303,7 @@ getNoteList key mquery sharedp limit' page =
|
||||||
pure b)
|
pure b)
|
||||||
where
|
where
|
||||||
_whereClause b = do
|
_whereClause b = do
|
||||||
where_ $ (b ^. NoteUserId ==. val key)
|
where_ (b ^. NoteUserId ==. val key)
|
||||||
-- search
|
-- search
|
||||||
sequenceA_ (parseSearchQuery (toLikeExpr b) =<< mquery)
|
sequenceA_ (parseSearchQuery (toLikeExpr b) =<< mquery)
|
||||||
case sharedp of
|
case sharedp of
|
||||||
|
@ -333,7 +332,7 @@ mkBookmarkTags userId bookmarkId tags =
|
||||||
|
|
||||||
|
|
||||||
fileBookmarkToBookmark :: UserId -> FileBookmark -> IO Bookmark
|
fileBookmarkToBookmark :: UserId -> FileBookmark -> IO Bookmark
|
||||||
fileBookmarkToBookmark user (FileBookmark {..}) = do
|
fileBookmarkToBookmark user FileBookmark {..} = do
|
||||||
slug <- mkBmSlug
|
slug <- mkBmSlug
|
||||||
pure $
|
pure $
|
||||||
Bookmark
|
Bookmark
|
||||||
|
@ -345,12 +344,12 @@ fileBookmarkToBookmark user (FileBookmark {..}) = do
|
||||||
, bookmarkTime = fileBookmarkTime
|
, bookmarkTime = fileBookmarkTime
|
||||||
, bookmarkShared = fileBookmarkShared
|
, bookmarkShared = fileBookmarkShared
|
||||||
, bookmarkToRead = fileBookmarkToRead
|
, bookmarkToRead = fileBookmarkToRead
|
||||||
, bookmarkSelected = (fromMaybe False fileBookmarkSelected)
|
, bookmarkSelected = Just True == fileBookmarkSelected
|
||||||
, bookmarkArchiveHref = fileBookmarkArchiveHref
|
, bookmarkArchiveHref = fileBookmarkArchiveHref
|
||||||
}
|
}
|
||||||
|
|
||||||
bookmarkTofileBookmark :: Bookmark -> Text -> FileBookmark
|
bookmarkTofileBookmark :: Bookmark -> Text -> FileBookmark
|
||||||
bookmarkTofileBookmark (Bookmark {..}) tags =
|
bookmarkTofileBookmark Bookmark {..} tags =
|
||||||
FileBookmark
|
FileBookmark
|
||||||
{ fileBookmarkHref = bookmarkHref
|
{ fileBookmarkHref = bookmarkHref
|
||||||
, fileBookmarkDescription = bookmarkDescription
|
, fileBookmarkDescription = bookmarkDescription
|
||||||
|
@ -377,7 +376,7 @@ data FFBookmarkNode = FFBookmarkNode
|
||||||
, firefoxBookmarkTypeCode :: !Int
|
, firefoxBookmarkTypeCode :: !Int
|
||||||
, firefoxBookmarkUri :: !(Maybe Text)
|
, firefoxBookmarkUri :: !(Maybe Text)
|
||||||
} deriving (Show, Eq, Typeable, Ord)
|
} deriving (Show, Eq, Typeable, Ord)
|
||||||
|
|
||||||
instance FromJSON FFBookmarkNode where
|
instance FromJSON FFBookmarkNode where
|
||||||
parseJSON (Object o) =
|
parseJSON (Object o) =
|
||||||
FFBookmarkNode <$>
|
FFBookmarkNode <$>
|
||||||
|
@ -396,7 +395,7 @@ instance FromJSON FFBookmarkNode where
|
||||||
parseJSON _ = A.parseFail "bad parse"
|
parseJSON _ = A.parseFail "bad parse"
|
||||||
|
|
||||||
firefoxBookmarkNodeToBookmark :: UserId -> FFBookmarkNode -> IO [Bookmark]
|
firefoxBookmarkNodeToBookmark :: UserId -> FFBookmarkNode -> IO [Bookmark]
|
||||||
firefoxBookmarkNodeToBookmark user (FFBookmarkNode {..}) = do
|
firefoxBookmarkNodeToBookmark user FFBookmarkNode {..} =
|
||||||
case firefoxBookmarkTypeCode of
|
case firefoxBookmarkTypeCode of
|
||||||
1 -> do
|
1 -> do
|
||||||
slug <- mkBmSlug
|
slug <- mkBmSlug
|
||||||
|
@ -404,10 +403,10 @@ firefoxBookmarkNodeToBookmark user (FFBookmarkNode {..}) = do
|
||||||
[ Bookmark
|
[ Bookmark
|
||||||
{ bookmarkUserId = user
|
{ bookmarkUserId = user
|
||||||
, bookmarkSlug = slug
|
, bookmarkSlug = slug
|
||||||
, bookmarkHref = (fromMaybe "" firefoxBookmarkUri)
|
, bookmarkHref = fromMaybe "" firefoxBookmarkUri
|
||||||
, bookmarkDescription = firefoxBookmarkTitle
|
, bookmarkDescription = firefoxBookmarkTitle
|
||||||
, bookmarkExtended = ""
|
, bookmarkExtended = ""
|
||||||
, bookmarkTime = (TI.posixSecondsToUTCTime (firefoxBookmarkDateAdded / 1000000))
|
, bookmarkTime = TI.posixSecondsToUTCTime (firefoxBookmarkDateAdded / 1000000)
|
||||||
, bookmarkShared = True
|
, bookmarkShared = True
|
||||||
, bookmarkToRead = False
|
, bookmarkToRead = False
|
||||||
, bookmarkSelected = False
|
, bookmarkSelected = False
|
||||||
|
@ -421,7 +420,7 @@ firefoxBookmarkNodeToBookmark user (FFBookmarkNode {..}) = do
|
||||||
(fromMaybe [] firefoxBookmarkChildren)
|
(fromMaybe [] firefoxBookmarkChildren)
|
||||||
_ -> pure []
|
_ -> pure []
|
||||||
|
|
||||||
|
|
||||||
insertFileBookmarks :: Key User -> FilePath -> DB (Either String Int)
|
insertFileBookmarks :: Key User -> FilePath -> DB (Either String Int)
|
||||||
insertFileBookmarks userId bookmarkFile = do
|
insertFileBookmarks userId bookmarkFile = do
|
||||||
mfmarks <- liftIO $ readFileBookmarks bookmarkFile
|
mfmarks <- liftIO $ readFileBookmarks bookmarkFile
|
||||||
|
@ -430,16 +429,15 @@ insertFileBookmarks userId bookmarkFile = do
|
||||||
Right fmarks -> do
|
Right fmarks -> do
|
||||||
bmarks <- liftIO $ mapM (fileBookmarkToBookmark userId) fmarks
|
bmarks <- liftIO $ mapM (fileBookmarkToBookmark userId) fmarks
|
||||||
mbids <- mapM insertUnique bmarks
|
mbids <- mapM insertUnique bmarks
|
||||||
void $
|
mapM_ (void . insertUnique) $
|
||||||
mapM insertUnique $
|
|
||||||
concatMap (uncurry (mkBookmarkTags userId)) $
|
concatMap (uncurry (mkBookmarkTags userId)) $
|
||||||
catMaybes $
|
catMaybes $
|
||||||
zipWith
|
zipWith
|
||||||
(\mbid tags -> ((, tags) <$> mbid))
|
(\mbid tags -> (, tags) <$> mbid)
|
||||||
mbids
|
mbids
|
||||||
(extractTags <$> fmarks)
|
(extractTags <$> fmarks)
|
||||||
pure $ Right (length bmarks)
|
pure $ Right (length bmarks)
|
||||||
|
|
||||||
where
|
where
|
||||||
extractTags = words . fileBookmarkTags
|
extractTags = words . fileBookmarkTags
|
||||||
|
|
||||||
|
@ -450,20 +448,20 @@ insertFFBookmarks userId bookmarkFile = do
|
||||||
Left e -> pure $ Left e
|
Left e -> pure $ Left e
|
||||||
Right fmarks -> do
|
Right fmarks -> do
|
||||||
bmarks <- liftIO $ firefoxBookmarkNodeToBookmark userId fmarks
|
bmarks <- liftIO $ firefoxBookmarkNodeToBookmark userId fmarks
|
||||||
_ <- mapM insertUnique bmarks
|
mapM_ (void . insertUnique) bmarks
|
||||||
pure $ Right (length bmarks)
|
pure $ Right (length bmarks)
|
||||||
|
|
||||||
|
|
||||||
readFileBookmarks :: MonadIO m => FilePath -> m (Either String [FileBookmark])
|
readFileBookmarks :: MonadIO m => FilePath -> m (Either String [FileBookmark])
|
||||||
readFileBookmarks fpath =
|
readFileBookmarks fpath =
|
||||||
pure . A.eitherDecode' . fromStrict =<< readFile fpath
|
A.eitherDecode' . fromStrict <$> readFile fpath
|
||||||
|
|
||||||
readFFBookmarks :: MonadIO m => FilePath -> m (Either String FFBookmarkNode)
|
readFFBookmarks :: MonadIO m => FilePath -> m (Either String FFBookmarkNode)
|
||||||
readFFBookmarks fpath =
|
readFFBookmarks fpath =
|
||||||
pure . A.eitherDecode' . fromStrict =<< readFile fpath
|
A.eitherDecode' . fromStrict <$> readFile fpath
|
||||||
|
|
||||||
exportFileBookmarks :: Key User -> FilePath -> DB ()
|
exportFileBookmarks :: Key User -> FilePath -> DB ()
|
||||||
exportFileBookmarks user fpath = do
|
exportFileBookmarks user fpath =
|
||||||
liftIO . A.encodeFile fpath =<< getFileBookmarks user
|
liftIO . A.encodeFile fpath =<< getFileBookmarks user
|
||||||
|
|
||||||
getFileBookmarks :: Key User -> DB [FileBookmark]
|
getFileBookmarks :: Key User -> DB [FileBookmark]
|
||||||
|
@ -489,7 +487,7 @@ instance FromJSON TagCloudMode where
|
||||||
case lookup "mode" o of
|
case lookup "mode" o of
|
||||||
Just (String "top") -> TagCloudModeTop <$> o .: "expanded" <*> o .: "value"
|
Just (String "top") -> TagCloudModeTop <$> o .: "expanded" <*> o .: "value"
|
||||||
Just (String "lowerBound") -> TagCloudModeLowerBound <$> o .: "expanded" <*> o .: "value"
|
Just (String "lowerBound") -> TagCloudModeLowerBound <$> o .: "expanded" <*> o .: "value"
|
||||||
Just (String "related") -> TagCloudModeRelated <$> o .: "expanded" <*> (fmap words (o .: "value"))
|
Just (String "related") -> TagCloudModeRelated <$> o .: "expanded" <*> fmap words (o .: "value")
|
||||||
Just (String "none") -> pure TagCloudModeNone
|
Just (String "none") -> pure TagCloudModeNone
|
||||||
_ -> A.parseFail "bad parse"
|
_ -> A.parseFail "bad parse"
|
||||||
parseJSON _ = A.parseFail "bad parse"
|
parseJSON _ = A.parseFail "bad parse"
|
||||||
|
@ -515,27 +513,27 @@ instance ToJSON TagCloudMode where
|
||||||
, "value" .= Null
|
, "value" .= Null
|
||||||
, "expanded" .= Bool False
|
, "expanded" .= Bool False
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
type Tag = Text
|
type Tag = Text
|
||||||
|
|
||||||
tagCountTop :: Key User -> Int -> DB [(Text, Int)]
|
tagCountTop :: Key User -> Int -> DB [(Text, Int)]
|
||||||
tagCountTop user top =
|
tagCountTop user top =
|
||||||
sortOn (toLower . fst) .
|
sortOn (toLower . fst) .
|
||||||
fmap (\(tname, tcount) -> (unValue tname, unValue tcount)) <$>
|
fmap (bimap unValue unValue) <$>
|
||||||
( select $ do
|
( select $ do
|
||||||
t <- from (table @BookmarkTag)
|
t <- from (table @BookmarkTag)
|
||||||
where_ (t ^. BookmarkTagUserId ==. val user)
|
where_ (t ^. BookmarkTagUserId ==. val user)
|
||||||
groupBy (lower_ $ t ^. BookmarkTagTag)
|
groupBy (lower_ $ t ^. BookmarkTagTag)
|
||||||
let countRows' = countRows
|
let countRows' = countRows
|
||||||
orderBy [desc countRows']
|
orderBy [desc countRows']
|
||||||
limit ((fromIntegral . toInteger) top)
|
limit ((fromIntegral . toInteger) top)
|
||||||
pure $ (t ^. BookmarkTagTag, countRows')
|
pure (t ^. BookmarkTagTag, countRows')
|
||||||
)
|
)
|
||||||
|
|
||||||
tagCountLowerBound :: Key User -> Int -> DB [(Text, Int)]
|
tagCountLowerBound :: Key User -> Int -> DB [(Text, Int)]
|
||||||
tagCountLowerBound user lowerBound =
|
tagCountLowerBound user lowerBound =
|
||||||
fmap (\(tname, tcount) -> (unValue tname, unValue tcount)) <$>
|
fmap (bimap unValue unValue) <$>
|
||||||
( select $ do
|
( select $ do
|
||||||
t <- from (table @BookmarkTag)
|
t <- from (table @BookmarkTag)
|
||||||
where_ (t ^. BookmarkTagUserId ==. val user)
|
where_ (t ^. BookmarkTagUserId ==. val user)
|
||||||
|
@ -543,17 +541,17 @@ tagCountLowerBound user lowerBound =
|
||||||
let countRows' = countRows
|
let countRows' = countRows
|
||||||
orderBy [asc (t ^. BookmarkTagTag)]
|
orderBy [asc (t ^. BookmarkTagTag)]
|
||||||
having (countRows' >=. val lowerBound)
|
having (countRows' >=. val lowerBound)
|
||||||
pure $ (t ^. BookmarkTagTag, countRows')
|
pure (t ^. BookmarkTagTag, countRows')
|
||||||
)
|
)
|
||||||
|
|
||||||
tagCountRelated :: Key User -> [Tag] -> DB [(Text, Int)]
|
tagCountRelated :: Key User -> [Tag] -> DB [(Text, Int)]
|
||||||
tagCountRelated user tags =
|
tagCountRelated user tags =
|
||||||
fmap (\(tname, tcount) -> (unValue tname, unValue tcount)) <$>
|
fmap (bimap unValue unValue) <$>
|
||||||
( select $ do
|
( select $ do
|
||||||
t <- from (table @BookmarkTag)
|
t <- from (table @BookmarkTag)
|
||||||
where_ $
|
where_ $
|
||||||
foldl (\expr tag ->
|
foldl (\expr tag ->
|
||||||
expr &&. (exists $ do
|
expr &&. exists ( do
|
||||||
u <- from (table @BookmarkTag)
|
u <- from (table @BookmarkTag)
|
||||||
where_ (u ^. BookmarkTagBookmarkId ==. t ^. BookmarkTagBookmarkId &&.
|
where_ (u ^. BookmarkTagBookmarkId ==. t ^. BookmarkTagBookmarkId &&.
|
||||||
(u ^. BookmarkTagTag `like` val tag))))
|
(u ^. BookmarkTagTag `like` val tag))))
|
||||||
|
@ -562,13 +560,13 @@ tagCountRelated user tags =
|
||||||
groupBy (lower_ $ t ^. BookmarkTagTag)
|
groupBy (lower_ $ t ^. BookmarkTagTag)
|
||||||
let countRows' = countRows
|
let countRows' = countRows
|
||||||
orderBy [asc $ lower_ $ (t ^. BookmarkTagTag)]
|
orderBy [asc $ lower_ $ (t ^. BookmarkTagTag)]
|
||||||
pure $ (t ^. BookmarkTagTag, countRows')
|
pure (t ^. BookmarkTagTag, countRows')
|
||||||
)
|
)
|
||||||
|
|
||||||
-- Notes
|
-- Notes
|
||||||
|
|
||||||
fileNoteToNote :: UserId -> FileNote -> IO Note
|
fileNoteToNote :: UserId -> FileNote -> IO Note
|
||||||
fileNoteToNote user (FileNote {..} ) = do
|
fileNoteToNote user FileNote {..} = do
|
||||||
slug <- mkNtSlug
|
slug <- mkNtSlug
|
||||||
pure $
|
pure $
|
||||||
Note
|
Note
|
||||||
|
@ -580,7 +578,7 @@ fileNoteToNote user (FileNote {..} ) = do
|
||||||
, noteIsMarkdown = False
|
, noteIsMarkdown = False
|
||||||
, noteShared = False
|
, noteShared = False
|
||||||
, noteCreated = fileNoteCreatedAt
|
, noteCreated = fileNoteCreatedAt
|
||||||
, noteUpdated = fileNoteUpdatedAt
|
, noteUpdated = fileNoteUpdatedAt
|
||||||
}
|
}
|
||||||
|
|
||||||
insertDirFileNotes :: Key User -> FilePath -> DB (Either String Int)
|
insertDirFileNotes :: Key User -> FilePath -> DB (Either String Int)
|
||||||
|
@ -610,7 +608,7 @@ instance FromJSON AccountSettingsForm where parseJSON = A.genericParseJSON gDefa
|
||||||
instance ToJSON AccountSettingsForm where toJSON = A.genericToJSON gDefaultFormOptions
|
instance ToJSON AccountSettingsForm where toJSON = A.genericToJSON gDefaultFormOptions
|
||||||
|
|
||||||
toAccountSettingsForm :: User -> AccountSettingsForm
|
toAccountSettingsForm :: User -> AccountSettingsForm
|
||||||
toAccountSettingsForm (User {..}) =
|
toAccountSettingsForm User {..} =
|
||||||
AccountSettingsForm
|
AccountSettingsForm
|
||||||
{ _privateDefault = userPrivateDefault
|
{ _privateDefault = userPrivateDefault
|
||||||
, _archiveDefault = userArchiveDefault
|
, _archiveDefault = userArchiveDefault
|
||||||
|
@ -618,12 +616,12 @@ toAccountSettingsForm (User {..}) =
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUserFromAccountSettingsForm :: Key User -> AccountSettingsForm -> DB ()
|
updateUserFromAccountSettingsForm :: Key User -> AccountSettingsForm -> DB ()
|
||||||
updateUserFromAccountSettingsForm userId (AccountSettingsForm {..}) = do
|
updateUserFromAccountSettingsForm userId AccountSettingsForm {..} =
|
||||||
CP.update userId
|
CP.update userId
|
||||||
[ UserPrivateDefault CP.=. _privateDefault
|
[ UserPrivateDefault CP.=. _privateDefault
|
||||||
, UserArchiveDefault CP.=. _archiveDefault
|
, UserArchiveDefault CP.=. _archiveDefault
|
||||||
, UserPrivacyLock CP.=. _privacyLock
|
, UserPrivacyLock CP.=. _privacyLock
|
||||||
]
|
]
|
||||||
|
|
||||||
-- BookmarkForm
|
-- BookmarkForm
|
||||||
|
|
||||||
|
@ -662,10 +660,10 @@ _toBookmarkForm' (Entity bid Bookmark {..}, tags) =
|
||||||
, _description = Just $ Textarea $ bookmarkExtended
|
, _description = Just $ Textarea $ bookmarkExtended
|
||||||
, _tags = Just $ fromMaybe "" tags
|
, _tags = Just $ fromMaybe "" tags
|
||||||
, _private = Just $ not bookmarkShared
|
, _private = Just $ not bookmarkShared
|
||||||
, _toread = Just $ bookmarkToRead
|
, _toread = Just bookmarkToRead
|
||||||
, _bid = Just $ unBookmarkKey $ bid
|
, _bid = Just $ unBookmarkKey $ bid
|
||||||
, _slug = Just $ bookmarkSlug
|
, _slug = Just bookmarkSlug
|
||||||
, _selected = Just $ bookmarkSelected
|
, _selected = Just bookmarkSelected
|
||||||
, _time = Just $ UTCTimeStr $ bookmarkTime
|
, _time = Just $ UTCTimeStr $ bookmarkTime
|
||||||
, _archiveUrl = bookmarkArchiveHref
|
, _archiveUrl = bookmarkArchiveHref
|
||||||
}
|
}
|
||||||
|
@ -682,16 +680,16 @@ _toBookmark userId BookmarkForm {..} = do
|
||||||
, bookmarkHref = _url
|
, bookmarkHref = _url
|
||||||
, bookmarkDescription = fromMaybe "" _title
|
, bookmarkDescription = fromMaybe "" _title
|
||||||
, bookmarkExtended = maybe "" unTextarea _description
|
, bookmarkExtended = maybe "" unTextarea _description
|
||||||
, bookmarkTime = fromMaybe time (fmap unUTCTimeStr _time)
|
, bookmarkTime = maybe time unUTCTimeStr _time
|
||||||
, bookmarkShared = maybe True not _private
|
, bookmarkShared = maybe True not _private
|
||||||
, bookmarkToRead = fromMaybe False _toread
|
, bookmarkToRead = Just True == _toread
|
||||||
, bookmarkSelected = fromMaybe False _selected
|
, bookmarkSelected = Just True == _selected
|
||||||
, bookmarkArchiveHref = _archiveUrl
|
, bookmarkArchiveHref = _archiveUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchBookmarkByUrl :: Key User -> Maybe Text -> DB (Maybe (Entity Bookmark, [Entity BookmarkTag]))
|
fetchBookmarkByUrl :: Key User -> Maybe Text -> DB (Maybe (Entity Bookmark, [Entity BookmarkTag]))
|
||||||
fetchBookmarkByUrl userId murl = runMaybeT do
|
fetchBookmarkByUrl userId murl = runMaybeT do
|
||||||
bmark <- MaybeT . getBy . UniqueUserHref userId =<< (MaybeT $ pure murl)
|
bmark <- MaybeT . getBy . UniqueUserHref userId =<< MaybeT (pure murl)
|
||||||
btags <- lift $ withTags (entityKey bmark)
|
btags <- lift $ withTags (entityKey bmark)
|
||||||
pure (bmark, btags)
|
pure (bmark, btags)
|
||||||
|
|
||||||
|
@ -700,22 +698,22 @@ data UpsertResult = Created | Updated
|
||||||
upsertBookmark :: Key User -> Maybe (Key Bookmark) -> Bookmark -> [Text] -> DB (UpsertResult, Key Bookmark)
|
upsertBookmark :: Key User -> Maybe (Key Bookmark) -> Bookmark -> [Text] -> DB (UpsertResult, Key Bookmark)
|
||||||
upsertBookmark userId mbid bm tags = do
|
upsertBookmark userId mbid bm tags = do
|
||||||
res <- case mbid of
|
res <- case mbid of
|
||||||
Just bid -> do
|
Just bid ->
|
||||||
get bid >>= \case
|
get bid >>= \case
|
||||||
Just prev_bm -> do
|
Just prev_bm -> do
|
||||||
when (userId /= bookmarkUserId prev_bm)
|
when (userId /= bookmarkUserId prev_bm)
|
||||||
(throwString "unauthorized")
|
(throwString "unauthorized")
|
||||||
replaceBookmark bid prev_bm
|
replaceBookmark bid prev_bm
|
||||||
_ -> throwString "not found"
|
_ -> throwString "not found"
|
||||||
Nothing -> do
|
Nothing ->
|
||||||
getBy (UniqueUserHref (bookmarkUserId bm) (bookmarkHref bm)) >>= \case
|
getBy (UniqueUserHref (bookmarkUserId bm) (bookmarkHref bm)) >>= \case
|
||||||
Just (Entity bid prev_bm) -> replaceBookmark bid prev_bm
|
Just (Entity bid prev_bm) -> replaceBookmark bid prev_bm
|
||||||
_ -> (Created,) <$> insert bm
|
_ -> (Created,) <$> insert bm
|
||||||
insertTags (bookmarkUserId bm) (snd res)
|
insertTags (bookmarkUserId bm) (snd res)
|
||||||
pure res
|
pure res
|
||||||
where
|
where
|
||||||
prepareReplace prev_bm = do
|
prepareReplace prev_bm =
|
||||||
if (bookmarkHref bm /= bookmarkHref prev_bm)
|
if bookmarkHref bm /= bookmarkHref prev_bm
|
||||||
then bm { bookmarkArchiveHref = Nothing }
|
then bm { bookmarkArchiveHref = Nothing }
|
||||||
else bm { bookmarkArchiveHref = bookmarkArchiveHref prev_bm }
|
else bm { bookmarkArchiveHref = bookmarkArchiveHref prev_bm }
|
||||||
replaceBookmark bid prev_bm = do
|
replaceBookmark bid prev_bm = do
|
||||||
|
@ -729,18 +727,18 @@ upsertBookmark userId mbid bm tags = do
|
||||||
\(i, tag) -> void $ insert $ BookmarkTag userId' tag bid' i
|
\(i, tag) -> void $ insert $ BookmarkTag userId' tag bid' i
|
||||||
|
|
||||||
updateBookmarkArchiveUrl :: Key User -> Key Bookmark -> Maybe Text -> DB ()
|
updateBookmarkArchiveUrl :: Key User -> Key Bookmark -> Maybe Text -> DB ()
|
||||||
updateBookmarkArchiveUrl userId bid marchiveUrl = do
|
updateBookmarkArchiveUrl userId bid marchiveUrl =
|
||||||
updateWhere
|
updateWhere
|
||||||
[BookmarkUserId CP.==. userId, BookmarkId CP.==. bid]
|
[BookmarkUserId CP.==. userId, BookmarkId CP.==. bid]
|
||||||
[BookmarkArchiveHref CP.=. marchiveUrl]
|
[BookmarkArchiveHref CP.=. marchiveUrl]
|
||||||
|
|
||||||
upsertNote :: Key User -> Maybe (Key Note) -> Note -> DB (UpsertResult, Key Note)
|
upsertNote :: Key User -> Maybe (Key Note) -> Note -> DB (UpsertResult, Key Note)
|
||||||
upsertNote userId mnid note = do
|
upsertNote userId mnid note =
|
||||||
case mnid of
|
case mnid of
|
||||||
Just nid -> do
|
Just nid -> do
|
||||||
get nid >>= \case
|
get nid >>= \case
|
||||||
Just note' -> do
|
Just note' -> do
|
||||||
when (userId /= (noteUserId note'))
|
when (userId /= noteUserId note')
|
||||||
(throwString "unauthorized")
|
(throwString "unauthorized")
|
||||||
replace nid note
|
replace nid note
|
||||||
pure (Updated, nid)
|
pure (Updated, nid)
|
||||||
|
@ -774,7 +772,7 @@ instance FromJSON FileBookmark where
|
||||||
parseJSON _ = A.parseFail "bad parse"
|
parseJSON _ = A.parseFail "bad parse"
|
||||||
|
|
||||||
instance ToJSON FileBookmark where
|
instance ToJSON FileBookmark where
|
||||||
toJSON (FileBookmark {..}) =
|
toJSON FileBookmark {..} =
|
||||||
object
|
object
|
||||||
[ "href" .= toJSON fileBookmarkHref
|
[ "href" .= toJSON fileBookmarkHref
|
||||||
, "description" .= toJSON fileBookmarkDescription
|
, "description" .= toJSON fileBookmarkDescription
|
||||||
|
@ -815,7 +813,7 @@ instance FromJSON FileNote where
|
||||||
parseJSON _ = A.parseFail "bad parse"
|
parseJSON _ = A.parseFail "bad parse"
|
||||||
|
|
||||||
instance ToJSON FileNote where
|
instance ToJSON FileNote where
|
||||||
toJSON (FileNote {..}) =
|
toJSON FileNote {..} =
|
||||||
object
|
object
|
||||||
[ "id" .= toJSON fileNoteId
|
[ "id" .= toJSON fileNoteId
|
||||||
, "title" .= toJSON fileNoteTitle
|
, "title" .= toJSON fileNoteTitle
|
||||||
|
|
|
@ -17,7 +17,7 @@ instance PathPiece UserNameP where
|
||||||
_ -> Nothing
|
_ -> Nothing
|
||||||
|
|
||||||
instance PathPiece TagsP where
|
instance PathPiece TagsP where
|
||||||
toPathPiece (TagsP tags) = "t:" <> (intercalate "+" tags)
|
toPathPiece (TagsP tags) = "t:" <> intercalate "+" tags
|
||||||
fromPathPiece s =
|
fromPathPiece s =
|
||||||
case splitOn ":" s of
|
case splitOn ":" s of
|
||||||
["t", ""] -> Nothing
|
["t", ""] -> Nothing
|
||||||
|
|
Loading…
Reference in a new issue