This is kind of a chonker because I went into so many rabbit holes. Foremost this implements a simple “Refresh Artist” button that fetches current artist torrent groups. BUG: the `artist` endpoint torrent struct is shite, it’s missing most info that we get in the `search` endpoint torrent struct, plus it’s organized differently (e.g. the `artists` thingy is in the torrent_group not the torrent). I should switch everything over to fetching the `torrent_group.id`s first and then going through and slowly fetching every torrent group separately … however that might time out very quickly. ugh. There doesn’t seem to be a way of fetching multiple torrent groups. Random other shit & improvements: * intersperse for builders * fix json errors so that the structs don’t get too big (`restrictJson`) * show error messages as json so jaeger displays it with nested UI * color pretty-printed json outpt on command line * add some important integral functions to MyPrelude * add `sintersperse` and `mintersperse` to MyPrelude Change-Id: If8bfcd68dc5c905e118ad86d50d7416962bf55d4 Reviewed-on: https://cl.tvl.fyi/c/depot/+/12960 Tested-by: BuildkiteCI Reviewed-by: Profpatsch <mail@profpatsch.de>
144 lines
4.7 KiB
Haskell
144 lines
4.7 KiB
Haskell
module Builder
|
|
( TextBuilder (..),
|
|
BytesBuilder (..),
|
|
buildText,
|
|
buildTextLazy,
|
|
buildBytes,
|
|
buildBytesLazy,
|
|
textT,
|
|
textLazyT,
|
|
bytesB,
|
|
bytesLazyB,
|
|
utf8B,
|
|
utf8LazyB,
|
|
utf8LenientT,
|
|
utf8LenientLazyT,
|
|
intDecimalT,
|
|
intDecimalB,
|
|
integerDecimalT,
|
|
integerDecimalB,
|
|
naturalDecimalT,
|
|
naturalDecimalB,
|
|
scientificDecimalT,
|
|
scientificDecimalB,
|
|
intersperseT,
|
|
intersperseB,
|
|
)
|
|
where
|
|
|
|
import Data.ByteString.Builder qualified as Bytes
|
|
import Data.ByteString.Builder.Scientific qualified as Scientific.Bytes
|
|
import Data.ByteString.Lazy qualified as Bytes.Lazy
|
|
import Data.Functor.Contravariant
|
|
import Data.Functor.Contravariant.Divisible
|
|
import Data.String
|
|
import Data.Text.Lazy qualified as Text.Lazy
|
|
import Data.Text.Lazy.Builder qualified as Text
|
|
import Data.Text.Lazy.Builder.Int qualified as Text
|
|
import Data.Text.Lazy.Builder.Scientific qualified as Scientific.Text
|
|
import MyPrelude
|
|
|
|
newtype TextBuilder a = TextBuilder {unTextBuilder :: a -> Text.Builder}
|
|
deriving newtype (Semigroup, Monoid)
|
|
|
|
instance IsString (TextBuilder a) where
|
|
fromString s = TextBuilder $ \_ -> s & fromString
|
|
|
|
instance Contravariant TextBuilder where
|
|
contramap f (TextBuilder g) = TextBuilder $ g . f
|
|
|
|
instance Divisible TextBuilder where
|
|
divide f (TextBuilder bb) (TextBuilder bc) =
|
|
TextBuilder $ \a -> let (b, c) = f a in bb b <> bc c
|
|
conquer = TextBuilder $ \_ -> mempty
|
|
|
|
-- | Convert a 'TextBuilder' to a strict 'Text' by applying it to a value.
|
|
buildText :: TextBuilder a -> a -> Text
|
|
buildText (TextBuilder f) a = f a & Text.toLazyText & toStrict
|
|
|
|
-- | Convert a 'TextBuilder' to a lazy 'Text' by applying it to a value.
|
|
buildTextLazy :: TextBuilder a -> a -> Text.Lazy.Text
|
|
buildTextLazy (TextBuilder f) a = f a & Text.toLazyText
|
|
|
|
newtype BytesBuilder a = BytesBuilder {unBytesBuilder :: a -> Bytes.Builder}
|
|
|
|
instance IsString (BytesBuilder a) where
|
|
fromString s = BytesBuilder $ \_ -> s & fromString
|
|
|
|
instance Contravariant BytesBuilder where
|
|
contramap f (BytesBuilder g) = BytesBuilder $ g . f
|
|
|
|
instance Divisible BytesBuilder where
|
|
divide f (BytesBuilder bb) (BytesBuilder bc) =
|
|
BytesBuilder $ \a -> let (b, c) = f a in bb b <> bc c
|
|
conquer = BytesBuilder $ \_ -> mempty
|
|
|
|
-- | Convert a 'BytesBuilder' to a strict 'ByteString' by applying it to a value.
|
|
buildBytes :: BytesBuilder a -> a -> ByteString
|
|
buildBytes (BytesBuilder b) a = b a & Bytes.toLazyByteString & toStrictBytes
|
|
|
|
-- | Convert a 'BytesBuilder' to a lazy 'ByteString' by applying it to a value.
|
|
buildBytesLazy :: BytesBuilder a -> a -> Bytes.Lazy.ByteString
|
|
buildBytesLazy (BytesBuilder b) a = b a & Bytes.toLazyByteString
|
|
|
|
textT :: TextBuilder Text
|
|
textT = TextBuilder Text.fromText
|
|
|
|
textLazyT :: TextBuilder Text.Lazy.Text
|
|
textLazyT = TextBuilder Text.fromLazyText
|
|
|
|
bytesB :: BytesBuilder ByteString
|
|
bytesB = BytesBuilder Bytes.byteString
|
|
|
|
bytesLazyB :: BytesBuilder Bytes.Lazy.ByteString
|
|
bytesLazyB = BytesBuilder Bytes.lazyByteString
|
|
|
|
utf8LenientT :: TextBuilder ByteString
|
|
utf8LenientT = bytesToTextUtf8Lenient >$< textT
|
|
|
|
utf8LenientLazyT :: TextBuilder Bytes.Lazy.ByteString
|
|
utf8LenientLazyT = bytesToTextUtf8LenientLazy >$< textLazyT
|
|
|
|
utf8B :: BytesBuilder Text
|
|
utf8B = textToBytesUtf8 >$< bytesB
|
|
|
|
utf8LazyB :: BytesBuilder Text.Lazy.Text
|
|
utf8LazyB = textToBytesUtf8Lazy >$< bytesLazyB
|
|
|
|
intDecimalT :: TextBuilder Int
|
|
intDecimalT = TextBuilder Text.decimal
|
|
|
|
intDecimalB :: BytesBuilder Int
|
|
intDecimalB = BytesBuilder Bytes.intDec
|
|
|
|
integerDecimalT :: TextBuilder Integer
|
|
integerDecimalT = TextBuilder Text.decimal
|
|
|
|
integerDecimalB :: BytesBuilder Integer
|
|
integerDecimalB = BytesBuilder Bytes.integerDec
|
|
|
|
naturalDecimalT :: TextBuilder Natural
|
|
naturalDecimalT = TextBuilder Text.decimal
|
|
|
|
naturalDecimalB :: BytesBuilder Natural
|
|
naturalDecimalB = toInteger >$< integerDecimalB
|
|
|
|
scientificDecimalT :: TextBuilder Scientific
|
|
scientificDecimalT = TextBuilder Scientific.Text.scientificBuilder
|
|
|
|
scientificDecimalB :: BytesBuilder Scientific
|
|
scientificDecimalB = BytesBuilder Scientific.Bytes.scientificBuilder
|
|
|
|
-- TODO: can these be abstracted over Divisible & Semigroup? Or something?
|
|
|
|
intersperseT :: (forall b. TextBuilder b) -> TextBuilder a -> TextBuilder [a]
|
|
intersperseT sep a = ((),) >$< intersperseT' sep a
|
|
|
|
intersperseT' :: TextBuilder b -> TextBuilder a -> TextBuilder (b, [a])
|
|
intersperseT' (TextBuilder sep) (TextBuilder a) = TextBuilder $ \(b, as) -> mintersperse (sep b) (fmap a as)
|
|
|
|
intersperseB :: (forall b. BytesBuilder b) -> BytesBuilder a -> BytesBuilder [a]
|
|
intersperseB sep a = ((),) >$< intersperseB' sep a
|
|
|
|
intersperseB' :: BytesBuilder b -> BytesBuilder a -> BytesBuilder (b, [a])
|
|
intersperseB' (BytesBuilder sep) (BytesBuilder a) = BytesBuilder $ \(b, as) -> mintersperse (sep b) (fmap a as)
|