module Network.Telegram.API.Bot.Object.Message (Message (..), Initial, Marking) where import "aeson" Data.Aeson (FromJSON (parseJSON), object, withArray, withObject, (.:), (.=)) import "aeson" Data.Aeson.Types (Object, Parser, Value) import "base" Control.Applicative (Alternative ((<|>), empty)) import "base" Data.Int (Int64) import "text" Data.Text (Text) import qualified "text" Data.Text as T (drop, take) import Network.Telegram.API.Bot.Object.Chat (Chat) import Network.Telegram.API.Bot.Object.From (From) import Network.Telegram.API.Bot.Object.Keyboard (Keyboard) import Network.Telegram.API.Bot.Capacity.Postable (Initial, Postable (initial_value, post_endpoint)) import Network.Telegram.API.Bot.Capacity.Purgeable (Marking, Purgeable (marking_value, purge_endpoint)) import Network.Telegram.API.Bot.Property.Identifiable (Identifiable (identificator), Identificator) data Message = Textual Int Chat From Text | Command Int Chat From Text deriving Show type instance Initial Message = (Int64, Text, Maybe Keyboard) type instance Marking Message = (Int64, Int) type instance Identificator Message = Int instance Identifiable Message where identificator (Textual i _ _ _) = i identificator (Command i _ _ _) = i instance FromJSON Message where parseJSON = withObject "Message" $ \v -> command v <|> textual v where command :: Object -> Parser Message command v = Command <$> v .: "message_id" <*> v .: "chat" <*> v .: "from" <*> (v .: "entities" >>= command_entity >>= extract_command v) textual :: Object -> Parser Message textual v = Textual <$> v .: "message_id" <*> v .: "chat" <*> v .: "from" <*> v .: "text" command_entity :: Value -> Parser (Int, Int) command_entity = withArray "Command entity" $ \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) = (T.take len . T.drop (ofs + 1)) <$> v .: "text" instance Postable Message where initial_value (chat_id, text, Nothing) = object ["chat_id" .= chat_id, "text" .= text] initial_value (chat_id, text, Just kb) = object ["chat_id" .= chat_id, "text" .= text, "reply_markup" .= kb] post_endpoint _ = "sendMessage" instance Purgeable Message where marking_value (chat_id, message_id) = object ["chat_id" .= chat_id, "message_id" .= message_id] purge_endpoint _ = "deleteMessage"