| Portability | GHC |
|---|---|
| Stability | experimental |
| Maintainer | me@haolian.org |
| Safe Haskell | None |
Network.Linklater
Description
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 baby corgi in one of your channels, you'll get the
image from http:baby.corgi.jpg.to. How, you say? Screen scraping.
-- Remaining imports left as an exercise to the reader.
import Network.Linklater (say, slashSimple, Command(..), Config(..), Message(..), Icon(..), Format(..))
--
findUrl :: Text -> Maybe Text
findUrl = fmap fromStrict . maybeResult . parse (manyTill (notChar '\n') (string "src=\"") *> takeTill (== '"'))
jpgto :: Maybe Command -> IO Text
jpgto (Just (Command user channel (Just text))) = do
message <- (fmap messageOf . findUrl . decodeUtf8 . flip (^.) responseBody) <$> get ("http://" <> (unpack subdomain) <> ".jpg.to/")
case (debug, message) of
(True, _) -> putStrLn ("+ Pretending to post " <> (unpack . decodeUtf8 . encode) message) >> return ""
(False, Just m) -> config' >>= say m >> return ""
(False, Nothing) -> return "Something went wrong!"
where config' = (Config "trello.slack.com" . filter (/= '\n') . pack) <$> readFile "token"
subdomain = (intercalate "." . fmap (filter isLetter . filter isAscii) . words) text
messageOf url = FormattedMessage (EmojiIcon "gift") "jpgtobot" channel [FormatAt user, FormatLink url (subdomain <> ".jpg.to>"), FormatString "no way!: &<>"]
debug = True
jpgto _ = return "Type more! (Did you know? jpgtobot is only 26 lines of Haskell. <https://github.com/hlian/jpgtobot/blob/master/Main.hs>)"
main :: IO ()
main = let port = 3000 in putStrLn ("+ Listening on port " <> show port) >> run port (slashSimple jpgto)
One /jpgto baby corgi, et voila.
For the full example (since this one is missing a ton of imports),
see the examples/ directory on GitHub.
https:github.comhlianlinklater
- say :: Message -> Config -> IO (Response ByteString)
- slash :: (Maybe Command -> Application) -> Application
- slashSimple :: (Maybe Command -> IO Text) -> Application
- data Channel
- newtype User = User Text
- data Message where
- data Config = Config {}
- data Command = Command {}
- newtype Icon = EmojiIcon Text
- data Format
- = FormatAt User
- | FormatUser User Text
- | FormatLink Text Text
- | FormatString Text
Documentation
slash :: (Maybe Command -> Application) -> ApplicationSource
slashSimple :: (Maybe Command -> IO Text) -> ApplicationSource
Constructors
| GroupChannel Text | A public or private group. |
| IMChannel Text | A private conversation with your best friend -- or lover ;). |
A username: no at-signs, just text!
Here's how you talk: you make one of these and pass it to say.
Before the day is done, Linklater will convert this to a JSON blob
using Aeson.
- Simple messages are parsed by Slack with parse=full (i.e. as if you had typed it into the input box).
- Complex messages are parsed according to Slack formatting. See
Format.
Like a curiosity about the world, you'll need one of these to
say something.
Constructors
| Config | |
Fields
| |
Incoming HTTP requests to the slash function get parsed into one of these babies.
Constructors
| Command | |
Fields
| |
The icon next to the messages you say. (Images unsupported
right now, sorry.)
A little DSL for Slack formatting.