-
Notifications
You must be signed in to change notification settings - Fork 2
/
Main.hs
133 lines (116 loc) · 3.88 KB
/
Main.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
{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}
import BasePrelude hiding (readFile)
import Network.Linklater
import qualified Control.Concurrent.MVar as MVar
import qualified Data.Map as M
import Data.Map (Map)
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Text.IO (readFile)
import Network.Wai.Handler.Warp (run)
data Want = WantsUser Text | WantsChannel
deriving (Eq, Show, Ord)
data Person = Person User Channel Want
deriving (Eq, Show, Ord)
type DB = Map Channel [Person]
dbGet :: DB -> Channel -> [Person]
dbGet db channel =
fromMaybe [] (M.lookup channel db)
dbPut :: DB -> Person -> DB
dbPut db person@(Person _ channel _) =
M.insert channel (person:dbGet db channel) db
dbDelete :: DB -> Person -> DB
dbDelete db person@(Person _ channel _) =
M.insert channel [p | p <- dbGet db channel, p /= person] db
findPerson :: DB -> Channel -> Want -> Maybe Person
findPerson db channel want = do
people <- M.lookup channel db
let predicate user' = case want of
WantsUser user -> user' == user
WantsChannel -> True
listToMaybe [p | p@(Person (User user') _ _ ) <- people, predicate user']
foundMessage :: Person -> Person -> Message
foundMessage (Person subject _ _) (Person object channel want) =
SimpleMessage (EmojiIcon "rainbow") "hi5bot" channel ("@" <> u subject <> " " <> body)
where
body =
if subject == object then
"touches a hand to the other hand while people avert their eyes."
else
case want of
WantsUser objectDesire
| subject /= User objectDesire ->
"swoops in for a high-five with @"
<> u object
<> ". Caw caw! Better luck next time, @"
<> objectDesire
<> ". :hand::octopus:"
| otherwise ->
"high-fives @"
<> u object
<> ", and everybody's eyes widen with respect. :hand::guitar:"
WantsChannel ->
"high-fives @"
<> u object
<> "! :hand:"
u (User x) = x
wantMessage :: Person -> Message
wantMessage (Person user channel want) =
SimpleMessage (EmojiIcon "hand") "hi5bot" channel ("@" <> u user <> " " <> body)
where
body =
case want of
WantsUser objectDesire ->
"raises a hand high in the air for @"
<> objectDesire
<> " to `/hi5`. A high-five is afoot!"
WantsChannel ->
"raises a hand high in the air."
u (User x) = x
cheatMode :: Bool
cheatMode = False
parseWant :: Maybe Text -> Want
parseWant t =
case t' of
Just text ->
case Text.length text of
0 -> WantsChannel
_ -> WantsUser text
Nothing -> WantsChannel
where
t' = Text.strip <$> t
parseCommand :: Command -> (User, Want)
parseCommand (Command _ user _ maybeText) =
case (cheatMode, (map Text.strip . Text.splitOn "--") <$> maybeText) of
(True, Just [text', user']) ->
(User user', parseWant (return text'))
_ ->
(user, parseWant maybeText)
hi5 :: MVar DB -> Config -> Maybe Command -> IO Text
hi5 dbM config (Just command@(Command _ _ channel _)) = do
MVar.modifyMVar_ dbM $ \db ->
case findPerson db channel want of
Just giver -> do
let db' = dbDelete db giver
void (say (foundMessage person giver) config)
return db'
Nothing -> do
let db' = dbPut db person
void (say (wantMessage person) config)
return db'
return ""
where
(user, want) =
parseCommand command
person =
Person user channel want
hi5 _ _ Nothing =
return "hi5bot is a high-five robot. It's a robot that helps you give and get high-fives. You can't high-five hi5bot. (Yet.) <https://github.com/hlian/hi5bot>"
main :: IO ()
main = do
db <- MVar.newMVar M.empty
url <- Text.filter (/= '\n') <$> readFile "token"
putStrLn ("+ Listening on port " <> show port)
run port (slashSimple (hi5 db (Config url)))
where
port = 3334