Skip to content

Instantly share code, notes, and snippets.

@erewok
Last active August 29, 2015 14:03
Show Gist options
  • Save erewok/324cf7f50f4480e8a8d1 to your computer and use it in GitHub Desktop.
Save erewok/324cf7f50f4480e8a8d1 to your computer and use it in GitHub Desktop.
Haskell: Pulling IP Addresses from Django Tracebacks
module Main where
import Control.Applicative
import Data.List
import System.Environment
data IpAddress = IpAddress String
deriving (Show, Eq, Ord)
data IpTree = Leaf
| Node IpAddress IpTree IpTree
cleanIp :: Char -> Bool
cleanIp '\'' = False
cleanIp '"' = False
cleanIp ',' = False
cleanIp _ = True
parseIp :: String -> IpAddress
parseIp line = IpAddress . filter cleanIp . last $ words line
filterIps :: String -> Bool
filterIps line = isInfixOf "REMOTE_ADDR" line
leadingZero :: String -> String
leadingZero n
| length n < 3 = leadingZero $ '0' : n
| otherwise = n
deLeadingZero :: String -> String
deLeadingZero ('0':xs) = deLeadingZero xs
deLeadingZero x = x
getAddress :: IpAddress -> String
getAddress (IpAddress address) = address
padIp :: (String -> String) -> String -> String
padIp f [] = []
padIp f ('.':xs) = '.' : padIp f xs
padIp f address = f takeAdd ++ (padIp f dropAdd)
where takeAdd = takeWhile (/= '.') address
dropAdd = dropWhile (/= '.') address
padding :: String -> String
padding address = padIp leadingZero address
depad :: String -> String
depad address = padIp deLeadingZero address
spammers :: String -> [IpAddress]
spammers = map parseIp . filter filterIps . lines
ipOnly :: [IpAddress] -> [String]
ipOnly = map depad . sort . map padding . map getAddress
countUnique :: [String] -> [(String, Int)]
countUnique = map (\xs@(x:_) -> (x, length xs)) . group
flatten :: (String, Int) -> String
flatten (x, y) = x ++ " " ++ show y
main :: IO ()
main = do
[f, g] <- getArgs
input <- readFile f
let output = unlines . map flatten . countUnique . ipOnly . spammers $ input
writeFile g output
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment