packages feed

lnurl-authenticator-0.1.0.0: exec/Main.hs

{-# LANGUAGE LambdaCase #-}

module Main (main) where

import Control.Applicative (optional, (<**>))
import Control.Exception (throwIO)
import LnUrl.Authenticator (
    AuthenticatorError (..),
    handleAuth,
    handleInit,
    handleList,
    handleLog,
 )
import qualified Options.Applicative as Opt
import System.Clipboard (getClipboardString)
import System.Environment (getEnv)

data CliOptions = CliOptions
    { identityFile :: Maybe FilePath
    , command :: Command
    }
    deriving (Eq, Show)

data Command
    = Init
    | Auth AuthOptions
    | Log LogOptions
    | List
    deriving (Eq, Show)

newtype AuthOptions = AuthOptions {authOptionsURL :: Maybe String}
    deriving (Eq, Show)

newtype LogOptions = LogOptions {logOptionsDomain :: String}
    deriving (Eq, Show)

getOptions :: IO CliOptions
getOptions = Opt.execParser $ Opt.info (opts <**> Opt.helper) desc
  where
    opts = CliOptions <$> optional optIdentFile <*> optCommand

    optIdentFile =
        Opt.strOption $
            Opt.long "file"
                <> Opt.short 'f'
                <> Opt.help
                    ( "File in which to store identity (default: ~"
                        <> defaultIdentFilePath
                        <> ")"
                    )

    optCommand =
        Opt.hsubparser $
            Opt.command "init" cmdInit
                <> Opt.command "auth" cmdRun
                <> Opt.command "log" cmdLog
                <> Opt.command "list" cmdList

    cmdInit = Opt.info (pure Init) descInit
    descInit = Opt.progDesc "Initialize a new identity"

    cmdRun = Opt.info optsRun descRun
    descRun = Opt.progDesc "Identify to a service using LNURL-auth"
    optsRun = fmap Auth $ AuthOptions <$> optional optURL

    optURL =
        Opt.strOption $
            Opt.long "url"
                <> Opt.help "Service URL (default is to take the URL from the clipboard)"

    cmdLog = Opt.info optsLog descLog
    descLog = Opt.progDesc "Print an activity log for a domain"
    optsLog = fmap Log $ LogOptions <$> optDomain

    optDomain = Opt.strArgument $ Opt.metavar "DOMAIN"

    cmdList = Opt.info (pure List) descList
    descList = Opt.progDesc "List all domains with which we have interacted"

    desc = Opt.progDesc "LNURL-auth helper"

defaultIdentFile :: IO FilePath
defaultIdentFile = identFile <$> getEnv "HOME"
  where
    identFile = (<> defaultIdentFilePath)

defaultIdentFilePath :: FilePath
defaultIdentFilePath = "/.lnurl-auth/default.auth"

getIdentFile :: CliOptions -> IO FilePath
getIdentFile = maybe defaultIdentFile pure . identityFile

main :: IO ()
main = do
    options <- getOptions
    identFile <- getIdentFile options
    case command options of
        Init -> handleInit identFile
        Auth theOpts ->
            maybe getUrlFromClipboard pure (authOptionsURL theOpts) >>= handleAuth identFile
        Log theOpts -> handleLog identFile $ logOptionsDomain theOpts
        List -> handleList identFile
  where
    getUrlFromClipboard = getClipboardString >>= maybe noURL pure
    noURL = throwIO NoUrl