summaryrefslogtreecommitdiff
path: root/Network/API/Telegram/Bot/Object/Update/Message/Content.hs
blob: cf68addff644d3049d255c845593dbceaa0f30af (plain)
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
module Network.API.Telegram.Bot.Object.Update.Message.Content (Content (..), module Exports) where

import Network.API.Telegram.Bot.Object.Update.Message.Content.File as Exports
import Network.API.Telegram.Bot.Object.Update.Message.Content.Info as Exports
import Network.API.Telegram.Bot.Object.Update.Message.Content.Location as Exports
import Network.API.Telegram.Bot.Object.Update.Message.Content.Size as Exports

import "aeson" Data.Aeson (FromJSON (parseJSON), withArray, withObject, (.:), (.:?))
import "aeson" Data.Aeson.Types (Object, Parser, Value (Object))
import "base" Control.Applicative (Applicative ((<*>)), Alternative (empty, (<|>)))
import "base" Control.Monad (Monad ((>>=)), fail)
import "base" Data.Function ((.), ($))
import "base" Data.Functor ((<$>))
import "base" Data.Foldable (Foldable (foldr))
import "base" Data.Int (Int)
import "base" Data.Maybe (Maybe)
import "base" Text.Show (Show)
import "base" Prelude ((+))
import "text" Data.Text (Text, drop, take)

data Content
	= Textual Text
	| Command Text
	| Attachment (Maybe Text) File
	| Information Info
	deriving Show

instance FromJSON Content where
	parseJSON = withObject "Content" $ \v -> command v <|> attachment v <|> other v <|> textual v where

		command :: Object -> Parser Content
		command v = Command <$> (v .: "entities" >>= command_entity >>= extract_command v)

		command_entity :: Value -> Parser (Int, Int)
		command_entity = withArray "Command content" $ \a ->
			foldr ((<|>) . entity) empty a where

			entity :: Value -> Parser (Int, Int)
			entity = withObject "Command entity" $ \v -> v .: "type" >>= \case
				("bot_command" :: Text) -> (,) <$> v .: "offset" <*> v .: "length"
				_ -> fail "It's not a bot command"

		extract_command :: Object -> (Int, Int) -> Parser Text
		extract_command v (ofs, len) = (take len . drop (ofs + 1)) <$> v .: "text"

		attachment :: Object -> Parser Content
		attachment v = Attachment <$> v .:? "caption" <*> parseJSON (Object v)

		other :: Object -> Parser Content
		other v = Information <$> parseJSON (Object v)

		textual :: Object -> Parser Content
		textual v = Textual <$> v .: "text"