content: {-# Language OverloadedStrings #-}
  {-|
  Module      : Client.Hook.Matterbridge
  Description : Hook for intergrating Matterbridge bridged messages
  Copyright   : (c) Felix Friedlander 2021
  License     : ISC
  Maintainer  : felix@ffetc.net
  
  Matterbridge is a simple multi-protocol chat bridge, supporting
  dozens of different protocols. This hook makes Matterbridged messages
  appear native in the client.
  
  message-hooks configuration takes one of two forms;
  to operate on all channels:
  
  > ["matterbridge", "nick"]
  
  or, to operate only on selected channels:
  
  > ["matterbridge", "nick", "#chan1", "#chan2", ..., "#chann"]
  
  This hook assumes the Matterbridge RemoteNickFormat is simply
  "<{NICK}> ".
  
  -}
  module Client.Hook.Matterbridge (matterbridgeHook) where
  
  import Client.Hook (MessageHook(..), MessageResult(..))
  import Control.Lens (set, view)
  import Data.Text (Text)
  import Irc.Identifier (mkId, Identifier)
  import Irc.Message (IrcMsg(Ctcp, Privmsg), Source(Source))
  import Irc.UserInfo (UserInfo(..), uiNick)
  import Text.Regex.TDFA ((=~))
  
  data MbMsg = Msg | Act
  
  matterbridgeHook :: [Text] -> Maybe MessageHook
  matterbridgeHook [] = Nothing
  matterbridgeHook (nick:chans) = Just (MessageHook "matterbridge" False (remap (mkId nick) chanfilter))
   where
    chanfilter
      | null chans = const True
      | otherwise  = (`elem` map mkId chans)
  
  remap :: Identifier -> (Identifier -> Bool) -> IrcMsg -> MessageResult
  remap nick chanfilter ircmsg =
    case ircmsg of
      Privmsg (Source ui _ _ _) chan msg
        | view uiNick ui == nick, chanfilter chan -> remap' Msg ui chan msg
      Ctcp (Source ui _ _ _) chan "ACTION" msg
        | view uiNick ui == nick, chanfilter chan -> remap' Act ui chan msg
      _ -> PassMessage
  
  remap' :: MbMsg -> UserInfo -> Identifier -> Text -> MessageResult
  remap' mbmsg ui chan msg =
    case msg =~ ("^(\x03\&[0-9]{2})?<([^>]+)> \x0f?(.*)$"::Text) of
      [_,_,nick,msg']:_ -> RemapMessage (newmsg mbmsg (fakeUser nick ui) chan msg')
      _                 -> PassMessage
  
  newmsg :: MbMsg -> Source -> Identifier -> Text -> IrcMsg
  newmsg Msg src chan msg = Privmsg src chan msg
  newmsg Act src chan msg = Ctcp src chan "ACTION" msg
  
  fakeUser :: Text -> UserInfo -> Source
  fakeUser nick ui = Source (set uiNick (mkId nick) ui) "" "" False
  