import Browser import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onInput, onClick) import Url exposing (percentEncode) import Regex import Dict main = Browser.element { init = init, view = view, update = update, subscriptions = \_ -> Sub.none } type Tab = TabJid | TabSMS | TabEmail | TabSIP type alias Model = { tab : Tab, jabberId : String, bifrost : Bifrost } init : () -> (Model, Cmd Msg) init _ = (Model TabJid "" ariaNet, Cmd.none) type Msg = SetTab Tab | JabberID String | SMS String | Email String | SIP String | Gateway String update : Msg -> Model -> (Model, Cmd Msg) update msg model = case msg of SetTab tab -> ({ model | tab = tab }, Cmd.none) JabberID jid -> ({ model | jabberId = jid }, Cmd.none) SMS tel -> ({ model | jabberId = telToJid tel }, Cmd.none) Email email -> ({ model | jabberId = emailToJid email }, Cmd.none) SIP sip -> ({ model | jabberId = sipToJid sip }, Cmd.none) Gateway gw -> ({ model | bifrost = Maybe.withDefault ariaNet (Dict.get gw gateways) }, Cmd.none) mkTab : Model -> Tab -> String -> Html Msg mkTab model tab label = let klass = if model.tab == tab then [class "current"] else [] in li ([onClick (SetTab tab)] ++ klass) [text label] view : Model -> Html Msg view model = let matrixId = jidToMatrix model.bifrost model.jabberId in div [] [ select [title "Use Gateway", onInput Gateway] (List.map (\gateway -> option [] [text gateway] ) (Dict.keys gateways)), ul [class "tabs"] [ mkTab model TabJid "Jabber ID", mkTab model TabSMS "SMS", mkTab model TabEmail "Email", mkTab model TabSIP "SIP" ], case model.tab of TabJid -> input [ type_ "text", placeholder "Jabber ID", value model.jabberId, onInput JabberID ] [] TabSMS -> input [ type_ "tel", placeholder "SMS", onInput SMS ] [] TabEmail -> input [ type_ "email", placeholder "Email", onInput Email ] [] TabSIP -> input [ type_ "text", placeholder "SIP", onInput SIP ] [], if matrixId /= "" then a [class "mxid", target "_blank", href ("https://matrix.to/#/" ++ matrixId)] [text matrixId] else text "" ] type alias Bifrost = { domain : String, prefix : String } gateways = Dict.fromList [("aria-net.org", ariaNet), ("matrix.org", matrixOrg)] ariaNet = Bifrost "aria-net.org" "bifrost" matrixOrg = Bifrost "matrix.org" "xmpp" jidToMatrix : Bifrost -> String -> String jidToMatrix gateway jid = if jid == "" then "" else "@_" ++ gateway.prefix ++ "_" ++ String.replace "%" "=" (String.toLower (percentEncode jid)) ++ ":" ++ gateway.domain emailToJid : String -> String emailToJid email = if email == "" then "" else escapeJid email ++ "@smtp.cheogram.com" sipToJid : String -> String sipToJid sip = if sip == "" then "" else if String.startsWith "sip:" sip then (escapeJid (String.dropLeft 4 sip)) ++ "@sip.cheogram.com" else (escapeJid sip) ++ "@sip.cheogram.com" telToJid : String -> String telToJid telish = let digits = String.filter Char.isDigit telish in if String.startsWith "+" telish then "+" ++ digits ++ "@cheogram.com" else if String.startsWith "1" digits && String.length digits == 11 then "+" ++ digits ++ "@cheogram.com" else if String.length digits == 10 then "+1" ++ digits ++ "@cheogram.com" else "" aRegex : String -> Regex.Regex aRegex str = Maybe.withDefault Regex.never <| Regex.fromString str escapeJid : String -> String escapeJid str = Regex.replace (aRegex "[ \"&'/:<>@]") (\match -> String.replace "%" "\\" (percentEncode match.match)) <| Regex.replace (aRegex "\\\\(20|22|26|27|2f|3a|3c|3e|40|5c)") (\match -> "\\5c" ++ String.dropLeft 1 match.match) str