linklater 1.0.0.2 → 1.0.0.3
raw patch · 4 files changed
+155/−1 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- README.md +77/−0
- changelog +9/−0
- examples/JointPhotographicExpertsGroupTonga.hs +63/−0
- linklater.cabal +6/−1
+ README.md view
@@ -0,0 +1,77 @@+## Who let you in here?++Relax! I'm here to make your life easier. Has your company ever+switched to using [Slack](https://slack.com), and then you wanted to+write silly Slack bots in Haskell as a way to learn Haskell?++<sup>Really?<sup>Wow<sup>That was a pretty specific question.</sup></sup>++Uh, do you want to be friends? Well let's talk about it later, because right now I have an example for you.++## Show me an example!++Here's a `/jpgto` bot. If you run this program and then tell Slack+about your server (incoming hook and custom slash command) and then+type `/jpgto diplomatico` in one of your channels, you'll get the+image from [http://diplomatico.jpg.to](http://diplomatico.jpg.to). How, you say? _Screen scraping_.++```haskell+import Network.Linklater (say, slash,+ Command(..), Config(..), Icon(..), Message(..), User(..))++urlParser :: Parser B.ByteString+urlParser = p+ where+ p = garbage *> url+ garbage = string "src=\"" <|> (P.take 1 *> garbage)+ url = takeTill (== _quotedbl)++urlFor :: Text -> IO Text+urlFor search = do+ r <- get (T.unpack $ F.format "http://{}.jpg.to/" [search])+ (return . handle . parse urlParser . strictly) (r ^. responseBody)+ where+ strictly = B.concat . L.toChunks+ handle (Fail i ctxs s) = error (show (i, ctxs, s))+ handle (Partial f) = handle (f "")+ handle (Done _ r) = toText r++jpgto :: Maybe Command -> Application+jpgto (Just (Command (User user) channel text)) req respond = do+ url <- urlFor (maybe "spolsky" id text)+ say (Message channel (response url) (EmojiIcon "gift")) config+ (respond . responseLBS status200 headers) ""+ where+ response url = F.format "@{} {}" (user, url)+ config = Config token "trello.slack.com"+ headers = [("Content-Type", "text/plain")]++main :: IO ()+main = do+ let port = 80+ putStrLn (F.format "+ Listening on port {}" [port])+ run port (slash jpgto)+ return ()+```++For the full example (since this one is missing a ton of imports), see+the `examples/` directory on GitHub.++Now! `/jpgto corgi`:++++So easy. Much fast.++## Features++* Uses `Text` everywhere so you can send your slash commands crazy Unicode characters all day long.+* Lovely documentation.+* Battle-tested.+++## Contributors++* [Hao Lian](https://hao.codes), author+* [Ian Henry](https://ianthehenry.com), design review and _future contributor_???+* *Shields* (the Grizzly Bear album), which I listened all the way through for the first time while I was writing this ★★★★
+ changelog view
@@ -0,0 +1,9 @@+-*- markdown -*-++## 2014-07-23 1.0.0.3++* Include extra source files in `.cabal`++## 2014-07-23 1.0.0.2 (and 1.0.0.1)++* Lower dependency constraints for GHC 7.6.x users
+ examples/JointPhotographicExpertsGroupTonga.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE OverloadedStrings #-}++module JointPhotographicExpertsGroupTonga where++import Control.Applicative+import Control.Lens hiding ((.=))+import Control.Monad+import Data.Attoparsec.ByteString+import qualified Data.Attoparsec.ByteString as P+import qualified Data.ByteString as B+import qualified Data.ByteString.Lazy as L+import qualified Data.Text.Format as F+import Data.Text.Lazy (Text)+import qualified Data.Text.Lazy as T+import Data.Text.Lazy.Encoding (decodeUtf8)+import Data.Text.Lazy.IO+import Data.Word8+import Network.HTTP.Types (status200)+import Network.Linklater+import Network.Wai+import Network.Wai.Handler.Warp (run)+import Network.Wreq hiding (params, headers)+import Prelude hiding (readFile, writeFile, putStrLn)++toText :: B.ByteString -> Text+toText = decodeUtf8 . L.fromChunks . return++token :: Text+token = undefined++urlParser :: Parser B.ByteString+urlParser = p+ where+ p = garbage *> url+ garbage = string "src=\"" <|> (P.take 1 *> garbage)+ url = takeTill (== _quotedbl)++urlFor :: Text -> IO Text+urlFor search = do+ r <- get (T.unpack $ F.format "http://{}.jpg.to/" [search])+ (return . handle . parse urlParser . strictly) (r ^. responseBody)+ where+ strictly = B.concat . L.toChunks+ handle (Fail i ctxs s) = error (show (i, ctxs, s))+ handle (Partial f) = handle (f "")+ handle (Done _ r) = toText r++jpgto :: Maybe Command -> Application+jpgto (Just (Command (User user) channel text)) req respond = do+ url <- urlFor (maybe "spolsky" id text)+ say (Message channel (response url) (EmojiIcon "gift")) config+ (respond . responseLBS status200 headers) ""+ where+ response url = F.format "@{} {}" (user, url)+ config = Config token "trello.slack.com"+ headers = [("Content-Type", "text/plain")]++main :: IO ()+main = do+ let port = 80+ putStrLn (F.format "+ Listening on port {}" [port])+ run port (slash jpgto)+ return ()
linklater.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: linklater-version: 1.0.0.2+version: 1.0.0.3 synopsis: Write bots for your Slack account, and then go to sleep (because it's so easy and late at night) homepage: https://github.com/hlian/linklater license: BSD3@@ -18,6 +18,11 @@ A library for writing <https://slack.com/> Slack chat bots. . A mistake?++extra-source-files:+ examples/*.hs+ README.md+ changelog flag developer default: False