module Network.RTorrent.Peer (
PeerId (..)
, PeerInfo (..)
, PeerAction
, getPeerPartial
, allPeers
, getTorrentPeers
, banPeer
, disconnectPeer
, getPeerHash
, getPeerIp
, getPeerClientVersion
, getPeerUpRate
, getPeerDownRate
, getPeerUpTotal
, getPeerDownTotal
, getPeerEncrypted
, getPeerCompletedPercent
, getPeerPort
) where
import Control.Applicative
import Control.DeepSeq
import Network.RTorrent.Action.Internals
import Network.RTorrent.Torrent
import Network.RTorrent.Command
import Network.XmlRpc.Internals
import Data.List.Split (splitOn)
data PeerId = PeerId !TorrentId !String
deriving Show
instance XmlRpcType PeerId where
toValue (PeerId (TorrentId tid) i) = ValueString $ tid ++ ":p" ++ i
fromValue v = return . uncurry PeerId =<< parse =<< fromValue v
where
parse :: Monad m => String -> m (TorrentId, String)
parse str = do
[hash, s] <- return $ splitOn ":p" str
return (TorrentId hash, s)
getType _ = TString
instance NFData PeerId where
rnf (PeerId tid i) = rnf tid `seq` rnf i
data PeerInfo = PeerInfo {
peerClientVersion :: String
, peerIp :: String
, peerUpRate :: !Int
, peerDownRate :: !Int
, peerUpTotal :: !Int
, peerDownTotal :: !Int
, peerEncrypted :: !Bool
, peerCompletedPercent :: !Int
, peerPort :: !Int
, peerId :: PeerId
} deriving Show
instance NFData PeerInfo where
rnf (PeerInfo a0 a1 a2 a3 a4 a5 a6 a7 a8 a9) =
rnf a0
`seq` rnf a1
`seq` rnf a2
`seq` rnf a3
`seq` rnf a4
`seq` rnf a5
`seq` rnf a6
`seq` rnf a7
`seq` rnf a8
`seq` rnf a9
getPeerHash :: PeerId -> PeerAction String
getPeerHash = simpleAction "p.get_id" []
getPeerIp :: PeerId -> PeerAction String
getPeerIp = simpleAction "p.get_address" []
getPeerClientVersion :: PeerId -> PeerAction String
getPeerClientVersion = simpleAction "p.get_client_version" []
getPeerUpRate :: PeerId -> PeerAction Int
getPeerUpRate = simpleAction "p.get_up_rate" []
getPeerDownRate :: PeerId -> PeerAction Int
getPeerDownRate = simpleAction "p.get_down_rate" []
getPeerUpTotal :: PeerId -> PeerAction Int
getPeerUpTotal = simpleAction "p.get_up_total" []
getPeerDownTotal :: PeerId -> PeerAction Int
getPeerDownTotal = simpleAction "p.get_down_total" []
getPeerEncrypted :: PeerId -> PeerAction Bool
getPeerEncrypted = fmap toEnum . simpleAction "p.is_encrypted" []
getPeerCompletedPercent :: PeerId -> PeerAction Int
getPeerCompletedPercent = simpleAction "p.get_completed_percent" []
getPeerPort :: PeerId -> PeerAction Int
getPeerPort = simpleAction "p.get_port" []
getPeerPartial :: PeerId -> PeerAction (PeerId -> PeerInfo)
getPeerPartial = runActionB $ PeerInfo
<$> b getPeerClientVersion
<*> b getPeerIp
<*> b getPeerUpRate
<*> b getPeerDownRate
<*> b getPeerUpTotal
<*> b getPeerDownTotal
<*> b getPeerEncrypted
<*> b getPeerCompletedPercent
<*> b getPeerPort
where
b = ActionB
disconnectPeer :: PeerId -> PeerAction Int
disconnectPeer = simpleAction "p.disconnect" []
banPeer :: PeerId -> PeerAction Int
banPeer = simpleAction "p.banned.set" [PInt 1]
type PeerAction = Action PeerId
getTorrentPeers :: TorrentId -> TorrentAction [PeerInfo]
getTorrentPeers = fmap (map contract) . allPeers getPeerPartial
where
contract (x :*: f) = f x
allPeers :: (PeerId -> PeerAction a) -> TorrentId -> TorrentAction [PeerId :*: a]
allPeers p = fmap addId . (getTorrentId <+> allToMulti (allP (getPeerHash <+> p)))
where
addId (hash :*: peers) =
map (\(phash :*: f) -> PeerId hash phash :*: f) peers
allP :: (PeerId -> PeerAction a) -> AllAction PeerId a
allP = AllAction (PeerId (TorrentId "") "") "p.multicall"