module Pythia.Services.GlobalIp
(
queryGlobalIp,
queryGlobalIpv4,
queryGlobalIpv6,
IpType (..),
IpAddress (..),
GlobalIpv4Config,
GlobalIpv6Config,
GlobalIpBothConfig,
GlobalIpConfig (..),
GlobalIpApp (..),
UrlSource (..),
)
where
import Data.Char qualified as Char
import Data.Text qualified as T
import Pythia.Data.Command (Command)
import Pythia.Internal.ShellApp qualified as ShellApp
import Pythia.Prelude
import Pythia.Services.GlobalIp.Types
( GlobalIpApp (GlobalIpAppCurl, GlobalIpAppDig),
GlobalIpBothConfig,
GlobalIpConfig (MkGlobalIpConfig, app, sources),
GlobalIpv4Config,
GlobalIpv6Config,
UrlSource (MkUrlSource, unUrlSource),
)
import Pythia.Services.Types.Network
( IpAddress (MkIpAddress),
IpRefinement,
IpType (Ipv4, Ipv6),
)
import Refined (Predicate, Refined)
import Refined qualified as R
queryGlobalIp ::
( MonadCatch m,
MonadTypedProcess m
) =>
GlobalIpBothConfig ->
m (IpAddress Ipv4, IpAddress Ipv6)
queryGlobalIp :: forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpBothConfig -> m (IpAddress 'Ipv4, IpAddress 'Ipv6)
queryGlobalIp = Lens' GlobalIpBothConfig GlobalIpApp
-> Lens' GlobalIpBothConfig ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> (GlobalIpApp
-> ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> m (IpAddress 'Ipv4, IpAddress 'Ipv6))
-> GlobalIpBothConfig
-> m (IpAddress 'Ipv4, IpAddress 'Ipv6)
forall config sources (m :: Type -> Type) result.
Lens' config GlobalIpApp
-> Lens' config sources
-> (GlobalIpApp -> sources -> m result)
-> config
-> m result
queryGlobalIp' Lens' GlobalIpBothConfig GlobalIpApp
#app Lens' GlobalIpBothConfig ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
#sources GlobalIpApp
-> ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> m (IpAddress 'Ipv4, IpAddress 'Ipv6)
forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp
-> ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> m (IpAddress 'Ipv4, IpAddress 'Ipv6)
getBothIps
{-# INLINEABLE queryGlobalIp #-}
queryGlobalIpv4 ::
( MonadCatch m,
MonadTypedProcess m
) =>
GlobalIpv4Config ->
m (IpAddress Ipv4)
queryGlobalIpv4 :: forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpv4Config -> m (IpAddress 'Ipv4)
queryGlobalIpv4 = Lens' GlobalIpv4Config GlobalIpApp
-> Lens' GlobalIpv4Config [UrlSource 'Ipv4]
-> (GlobalIpApp -> [UrlSource 'Ipv4] -> m (IpAddress 'Ipv4))
-> GlobalIpv4Config
-> m (IpAddress 'Ipv4)
forall config sources (m :: Type -> Type) result.
Lens' config GlobalIpApp
-> Lens' config sources
-> (GlobalIpApp -> sources -> m result)
-> config
-> m result
queryGlobalIp' Lens' GlobalIpv4Config GlobalIpApp
#app Lens' GlobalIpv4Config [UrlSource 'Ipv4]
#sources GlobalIpApp -> [UrlSource 'Ipv4] -> m (IpAddress 'Ipv4)
forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp -> [UrlSource 'Ipv4] -> m (IpAddress 'Ipv4)
getIpv4s
{-# INLINEABLE queryGlobalIpv4 #-}
queryGlobalIpv6 ::
( MonadCatch m,
MonadTypedProcess m
) =>
GlobalIpv6Config ->
m (IpAddress Ipv6)
queryGlobalIpv6 :: forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpv6Config -> m (IpAddress 'Ipv6)
queryGlobalIpv6 = Lens' GlobalIpv6Config GlobalIpApp
-> Lens' GlobalIpv6Config [UrlSource 'Ipv6]
-> (GlobalIpApp -> [UrlSource 'Ipv6] -> m (IpAddress 'Ipv6))
-> GlobalIpv6Config
-> m (IpAddress 'Ipv6)
forall config sources (m :: Type -> Type) result.
Lens' config GlobalIpApp
-> Lens' config sources
-> (GlobalIpApp -> sources -> m result)
-> config
-> m result
queryGlobalIp' Lens' GlobalIpv6Config GlobalIpApp
#app Lens' GlobalIpv6Config [UrlSource 'Ipv6]
#sources GlobalIpApp -> [UrlSource 'Ipv6] -> m (IpAddress 'Ipv6)
forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp -> [UrlSource 'Ipv6] -> m (IpAddress 'Ipv6)
getIpv6s
{-# INLINEABLE queryGlobalIpv6 #-}
queryGlobalIp' ::
Lens' config GlobalIpApp ->
Lens' config sources ->
(GlobalIpApp -> sources -> m result) ->
config ->
m result
queryGlobalIp' :: forall config sources (m :: Type -> Type) result.
Lens' config GlobalIpApp
-> Lens' config sources
-> (GlobalIpApp -> sources -> m result)
-> config
-> m result
queryGlobalIp' Lens' config GlobalIpApp
appLens Lens' config sources
sourceLens GlobalIpApp -> sources -> m result
getIpFn config
config =
GlobalIpApp -> sources -> m result
getIpFn (config
config config -> Lens' config GlobalIpApp -> GlobalIpApp
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' config GlobalIpApp
appLens) (config
config config -> Lens' config sources -> sources
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Lens' config sources
sourceLens)
{-# INLINEABLE queryGlobalIp' #-}
getBothIps ::
( MonadCatch m,
MonadTypedProcess m
) =>
GlobalIpApp ->
([UrlSource Ipv4], [UrlSource Ipv6]) ->
m (IpAddress Ipv4, IpAddress Ipv6)
getBothIps :: forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp
-> ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> m (IpAddress 'Ipv4, IpAddress 'Ipv6)
getBothIps GlobalIpApp
app ([UrlSource 'Ipv4]
ipv4Srcs, [UrlSource 'Ipv6]
ipv6Srcs) =
(,)
(IpAddress 'Ipv4
-> IpAddress 'Ipv6 -> (IpAddress 'Ipv4, IpAddress 'Ipv6))
-> m (IpAddress 'Ipv4)
-> m (IpAddress 'Ipv6 -> (IpAddress 'Ipv4, IpAddress 'Ipv6))
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
<$> GlobalIpApp -> [UrlSource 'Ipv4] -> m (IpAddress 'Ipv4)
forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp -> [UrlSource 'Ipv4] -> m (IpAddress 'Ipv4)
getIpv4s GlobalIpApp
app [UrlSource 'Ipv4]
ipv4Srcs
m (IpAddress 'Ipv6 -> (IpAddress 'Ipv4, IpAddress 'Ipv6))
-> m (IpAddress 'Ipv6) -> m (IpAddress 'Ipv4, IpAddress 'Ipv6)
forall a b. m (a -> b) -> m a -> m b
forall (f :: Type -> Type) a b.
Applicative f =>
f (a -> b) -> f a -> f b
<*> GlobalIpApp -> [UrlSource 'Ipv6] -> m (IpAddress 'Ipv6)
forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp -> [UrlSource 'Ipv6] -> m (IpAddress 'Ipv6)
getIpv6s GlobalIpApp
app [UrlSource 'Ipv6]
ipv6Srcs
{-# INLINEABLE getBothIps #-}
getIpv4s ::
( MonadCatch m,
MonadTypedProcess m
) =>
GlobalIpApp ->
[UrlSource Ipv4] ->
m (IpAddress Ipv4)
getIpv4s :: forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp -> [UrlSource 'Ipv4] -> m (IpAddress 'Ipv4)
getIpv4s GlobalIpApp
app [UrlSource 'Ipv4]
extraSrcs = do
let sources :: [UrlSource 'Ipv4]
sources = case [UrlSource 'Ipv4]
extraSrcs of
[] -> GlobalIpApp -> [UrlSource 'Ipv4]
ipv4Defaults GlobalIpApp
app
[UrlSource 'Ipv4]
_ -> GlobalIpApp -> [UrlSource 'Ipv4] -> [UrlSource 'Ipv4]
forall (a :: IpType). GlobalIpApp -> [UrlSource a] -> [UrlSource a]
prependApp GlobalIpApp
app [UrlSource 'Ipv4]
extraSrcs
[UrlSource 'Ipv4] -> m (IpAddress 'Ipv4)
forall (m :: Type -> Type) (a :: IpType).
(MonadCatch m, MonadTypedProcess m,
Predicate (IpRefinement a) Text) =>
[UrlSource a] -> m (IpAddress a)
getIpFromSources [UrlSource 'Ipv4]
sources
{-# INLINEABLE getIpv4s #-}
getIpv6s ::
( MonadCatch m,
MonadTypedProcess m
) =>
GlobalIpApp ->
[UrlSource Ipv6] ->
m (IpAddress Ipv6)
getIpv6s :: forall (m :: Type -> Type).
(MonadCatch m, MonadTypedProcess m) =>
GlobalIpApp -> [UrlSource 'Ipv6] -> m (IpAddress 'Ipv6)
getIpv6s GlobalIpApp
app [UrlSource 'Ipv6]
extraSrcs = do
let sources :: [UrlSource 'Ipv6]
sources = case [UrlSource 'Ipv6]
extraSrcs of
[] -> GlobalIpApp -> [UrlSource 'Ipv6]
ipv6Defaults GlobalIpApp
app
[UrlSource 'Ipv6]
_ -> GlobalIpApp -> [UrlSource 'Ipv6] -> [UrlSource 'Ipv6]
forall (a :: IpType). GlobalIpApp -> [UrlSource a] -> [UrlSource a]
prependApp GlobalIpApp
app [UrlSource 'Ipv6]
extraSrcs
[UrlSource 'Ipv6] -> m (IpAddress 'Ipv6)
forall (m :: Type -> Type) (a :: IpType).
(MonadCatch m, MonadTypedProcess m,
Predicate (IpRefinement a) Text) =>
[UrlSource a] -> m (IpAddress a)
getIpFromSources [UrlSource 'Ipv6]
sources
{-# INLINEABLE getIpv6s #-}
prependApp :: GlobalIpApp -> [UrlSource a] -> [UrlSource a]
prependApp :: forall (a :: IpType). GlobalIpApp -> [UrlSource a] -> [UrlSource a]
prependApp GlobalIpApp
GlobalIpAppCurl [UrlSource a]
srcs = (UrlSource a -> UrlSource a) -> [UrlSource a] -> [UrlSource a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (Optic An_Iso '[] (UrlSource a) (UrlSource a) Text Text
#unUrlSource Optic An_Iso '[] (UrlSource a) (UrlSource a) Text Text
-> (Text -> Text) -> UrlSource a -> UrlSource a
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
%~ (Text
"curl " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>)) [UrlSource a]
srcs
prependApp GlobalIpApp
GlobalIpAppDig [UrlSource a]
srcs = (UrlSource a -> UrlSource a) -> [UrlSource a] -> [UrlSource a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap (Optic An_Iso '[] (UrlSource a) (UrlSource a) Text Text
#unUrlSource Optic An_Iso '[] (UrlSource a) (UrlSource a) Text Text
-> (Text -> Text) -> UrlSource a -> UrlSource a
forall k (is :: IxList) s t a b.
Is k A_Setter =>
Optic k is s t a b -> (a -> b) -> s -> t
%~ (\Text
s -> Text
"dig " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" +short")) [UrlSource a]
srcs
{-# INLINEABLE prependApp #-}
ipv4Defaults :: GlobalIpApp -> [UrlSource Ipv4]
ipv4Defaults :: GlobalIpApp -> [UrlSource 'Ipv4]
ipv4Defaults GlobalIpApp
GlobalIpAppCurl = ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
curlDefaults ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv4]
-> [UrlSource 'Ipv4]
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv4]
forall s t a b. Field1 s t a b => Lens s t a b
_1
ipv4Defaults GlobalIpApp
GlobalIpAppDig = ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
digDefaults ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv4]
-> [UrlSource 'Ipv4]
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv4]
forall s t a b. Field1 s t a b => Lens s t a b
_1
{-# INLINEABLE ipv4Defaults #-}
ipv6Defaults :: GlobalIpApp -> [UrlSource Ipv6]
ipv6Defaults :: GlobalIpApp -> [UrlSource 'Ipv6]
ipv6Defaults GlobalIpApp
GlobalIpAppCurl = ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
curlDefaults ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv6]
-> [UrlSource 'Ipv6]
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv6]
forall s t a b. Field2 s t a b => Lens s t a b
_2
ipv6Defaults GlobalIpApp
GlobalIpAppDig = ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
digDefaults ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
-> Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv6]
-> [UrlSource 'Ipv6]
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Optic'
A_Lens '[] ([UrlSource 'Ipv4], [UrlSource 'Ipv6]) [UrlSource 'Ipv6]
forall s t a b. Field2 s t a b => Lens s t a b
_2
{-# INLINEABLE ipv6Defaults #-}
curlDefaults :: ([UrlSource Ipv4], [UrlSource Ipv6])
curlDefaults :: ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
curlDefaults = ([UrlSource 'Ipv4]
ipv4s, [UrlSource 'Ipv6]
forall {a}. [a]
ipv6s)
where
ipv4s :: [UrlSource 'Ipv4]
ipv4s =
[ UrlSource 'Ipv4
"curl http://whatismyip.akamai.com/",
UrlSource 'Ipv4
"curl http://ifconfig.me/ip",
UrlSource 'Ipv4
"curl http://myexternalip.com/raw",
UrlSource 'Ipv4
"curl http://checkip.amazonaws.com/"
]
ipv6s :: [a]
ipv6s = []
{-# INLINEABLE curlDefaults #-}
digDefaults :: ([UrlSource Ipv4], [UrlSource Ipv6])
digDefaults :: ([UrlSource 'Ipv4], [UrlSource 'Ipv6])
digDefaults = ([UrlSource 'Ipv4]
ipv4s, [UrlSource 'Ipv6]
forall {a}. [a]
ipv6s)
where
ipv4s :: [UrlSource 'Ipv4]
ipv4s =
[ UrlSource 'Ipv4
"dig @resolver1.opendns.com myip.opendns.com +short",
UrlSource 'Ipv4
"dig @resolver2.opendns.com myip.opendns.com +short",
UrlSource 'Ipv4
"dig @resolver3.opendns.com myip.opendns.com +short",
UrlSource 'Ipv4
"dig @resolver4.opendns.com myip.opendns.com +short",
UrlSource 'Ipv4
"dig @ns1-1.akamaitech.net ANY whoami.akamai.net +short",
UrlSource 'Ipv4
"dig -4 TXT o-o.myaddr.l.google.com @ns1.google.com +short"
]
ipv6s :: [a]
ipv6s = []
{-# INLINEABLE digDefaults #-}
getIpFromSources ::
( MonadCatch m,
MonadTypedProcess m,
Predicate (IpRefinement a) Text
) =>
[UrlSource a] ->
m (IpAddress a)
getIpFromSources :: forall (m :: Type -> Type) (a :: IpType).
(MonadCatch m, MonadTypedProcess m,
Predicate (IpRefinement a) Text) =>
[UrlSource a] -> m (IpAddress a)
getIpFromSources = (Refined (IpRefinement a) Text -> IpAddress a)
-> m (Refined (IpRefinement a) Text) -> m (IpAddress a)
forall a b. (a -> b) -> m a -> m b
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap Refined (IpRefinement a) Text -> IpAddress a
forall (a :: IpType). Refined (IpRefinement a) Text -> IpAddress a
MkIpAddress (m (Refined (IpRefinement a) Text) -> m (IpAddress a))
-> ([UrlSource a] -> m (Refined (IpRefinement a) Text))
-> [UrlSource a]
-> m (IpAddress a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Iso' (UrlSource a) Command
-> [UrlSource a] -> m (Refined (IpRefinement a) Text)
forall (m :: Type -> Type) p a.
(MonadCatch m, MonadTypedProcess m, Predicate p Text) =>
Iso' a Command -> [a] -> m (Refined p Text)
getIp (Optic An_Iso '[] (UrlSource a) (UrlSource a) Text Text
#unUrlSource Optic An_Iso '[] (UrlSource a) (UrlSource a) Text Text
-> Optic (ReversedOptic An_Iso) '[] Text Text Command Command
-> Iso' (UrlSource a) Command
forall k l m (is :: IxList) (js :: IxList) (ks :: IxList) s t u v a
b.
(JoinKinds k l m, AppendIndices is js ks) =>
Optic k is s t u v -> Optic l js u v a b -> Optic m ks s t a b
% Optic An_Iso '[] Command Command Text Text
-> Optic (ReversedOptic An_Iso) '[] Text Text Command Command
forall (is :: IxList) s t a b.
AcceptsEmptyIndices "re" is =>
Optic An_Iso is s t a b -> Optic (ReversedOptic An_Iso) is b a t s
forall k (is :: IxList) s t a b.
(ReversibleOptic k, AcceptsEmptyIndices "re" is) =>
Optic k is s t a b -> Optic (ReversedOptic k) is b a t s
re Optic An_Iso '[] Command Command Text Text
#unCommand)
{-# INLINEABLE getIpFromSources #-}
getIp ::
forall m p a.
( MonadCatch m,
MonadTypedProcess m,
Predicate p Text
) =>
Iso' a Command ->
[a] ->
m (Refined p Text)
getIp :: forall (m :: Type -> Type) p a.
(MonadCatch m, MonadTypedProcess m, Predicate p Text) =>
Iso' a Command -> [a] -> m (Refined p Text)
getIp Iso' a Command
cmdIso [a]
cmds = [m (Refined p Text)] -> m (Refined p Text)
forall (m :: Type -> Type) result.
MonadCatch m =>
[m result] -> m result
ShellApp.tryIOs ((a -> m (Refined p Text)) -> [a] -> [m (Refined p Text)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> m (Refined p Text)
go [a]
cmds)
where
go :: a -> m (Refined p Text)
go a
cmd = do
Text
txt <- Command -> m Text
forall (m :: Type -> Type).
(MonadThrow m, MonadTypedProcess m) =>
Command -> m Text
ShellApp.runCommand (Command -> m Text) -> Command -> m Text
forall a b. (a -> b) -> a -> b
$ a
cmd a -> Iso' a Command -> Command
forall k s (is :: IxList) a.
Is k A_Getter =>
s -> Optic' k is s a -> a
^. Iso' a Command
cmdIso
Text -> m (Refined p Text)
forall {k} (p :: k) x (m :: Type -> Type).
(Predicate p x, MonadThrow m) =>
x -> m (Refined p x)
R.refineThrow (Text -> Text
trim Text
txt)
{-# INLINEABLE getIp #-}
trim :: Text -> Text
trim :: Text -> Text
trim = (Char -> Bool) -> Text -> Text
T.dropAround Char -> Bool
Char.isSpace
{-# INLINEABLE trim #-}