module Network.RTorrent.Tracker (
TrackerId (..)
, TrackerType (..)
, TrackerInfo (..)
, TrackerAction
, getTrackerPartial
, getTorrentTrackers
, allTrackers
, getTrackerUrl
, getTrackerEnabled
, setTrackerEnabled
, getTrackerType
, getTrackerOpen
) 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 TrackerId = TrackerId !TorrentId !Int deriving Show
instance XmlRpcType TrackerId where
toValue (TrackerId (TorrentId tid) i) = ValueString $ tid ++ ":t" ++ show i
fromValue v = return . uncurry TrackerId =<< parse =<< fromValue v
where
parse :: Monad m => String -> m (TorrentId, Int)
parse str = do
[hash, i] <- return $ splitOn ":t" str
return (TorrentId hash, read i)
getType _ = TString
data TrackerType =
TrackerHTTP
| TrackerUDP
| TrackerDHT
deriving (Show, Eq)
instance Enum TrackerType where
toEnum 1 = TrackerHTTP
toEnum 2 = TrackerUDP
toEnum 3 = TrackerDHT
toEnum i = error $ "toEnum :: Int -> TrackerType failed, got : " ++ show i
fromEnum TrackerHTTP = 1
fromEnum TrackerUDP = 2
fromEnum TrackerDHT = 3
instance XmlRpcType TrackerType where
toValue = toValue . fromEnum
fromValue v = return . toEnum =<< check =<< fromValue v
where
check i
| 1 <= i && i <= 3 = return i
| otherwise = fail $ "Invalid TrackerType, got : " ++ show i
getType _ = TInt
instance NFData TrackerType
data TrackerInfo = TrackerInfo {
trackerUrl :: String
, trackerType :: !TrackerType
, trackerEnabled :: !Bool
, trackerOpen :: !Bool
, trackerId :: TrackerId
} deriving Show
instance NFData TrackerId where
rnf (TrackerId tid i) = rnf tid `seq` rnf i
instance NFData TrackerInfo where
rnf (TrackerInfo a0 a1 a2 a3 a4) =
rnf a0
`seq` rnf a1
`seq` rnf a2
`seq` rnf a3
`seq` rnf a4
type TrackerAction = Action TrackerId
allTrackers :: (TrackerId -> TrackerAction a) -> TorrentId -> TorrentAction [TrackerId :*: a]
allTrackers t = fmap addId . (getTorrentId <+> allToMulti (allT t))
where
addId (hash :*: trackers) =
zipWith (\index -> (:*:) (TrackerId hash index)) [0..] trackers
allT :: (TrackerId -> TrackerAction a) -> AllAction TrackerId a
allT = AllAction (TrackerId (TorrentId "") 0) "t.multicall"
getTrackerUrl :: TrackerId -> TrackerAction String
getTrackerUrl = simpleAction "t.get_url" []
getTrackerEnabled :: TrackerId -> TrackerAction Bool
getTrackerEnabled = fmap toEnum . simpleAction "t.is_enabled" []
setTrackerEnabled :: Bool -> TrackerId -> TrackerAction Int
setTrackerEnabled i = simpleAction "t.is_enabled" [PInt (fromEnum i)]
getTrackerType :: TrackerId -> TrackerAction TrackerType
getTrackerType = simpleAction "t.get_type" []
getTrackerOpen :: TrackerId -> TrackerAction Bool
getTrackerOpen = fmap toEnum . simpleAction "t.is_open" []
getTrackerPartial :: TrackerId -> TrackerAction (TrackerId -> TrackerInfo)
getTrackerPartial = runActionB $ TrackerInfo
<$> b getTrackerUrl
<*> b getTrackerType
<*> b getTrackerEnabled
<*> b getTrackerOpen
where
b = ActionB
getTorrentTrackers :: TorrentId -> TorrentAction [TrackerInfo]
getTorrentTrackers = fmap (map contract) . allTrackers getTrackerPartial
where
contract (x :*: f) = f x