module Web.Data.Yahoo.Request where import Data.List (intercalate) import Data.Maybe (catMaybes) import Data.Time.Calendar (Day, fromGregorian) import Text.Printf (printf) import Web.Data.Yahoo.Utils (dayAsEpoch) data Ticker = Ticker String class YahooParam a where key :: a -> String symbol :: a -> String paramToString :: YahooParam a => a -> String paramToString :: a -> String paramToString a p = String -> String -> String -> String forall r. PrintfType r => String -> r printf String "%s=%s" (a -> String forall a. YahooParam a => a -> String key a p) (a -> String forall a. YahooParam a => a -> String symbol a p) data Interval = Daily | Weekly | Monthly deriving (Int -> Interval -> String -> String [Interval] -> String -> String Interval -> String (Int -> Interval -> String -> String) -> (Interval -> String) -> ([Interval] -> String -> String) -> Show Interval forall a. (Int -> a -> String -> String) -> (a -> String) -> ([a] -> String -> String) -> Show a showList :: [Interval] -> String -> String $cshowList :: [Interval] -> String -> String show :: Interval -> String $cshow :: Interval -> String showsPrec :: Int -> Interval -> String -> String $cshowsPrec :: Int -> Interval -> String -> String Show, Interval -> Interval -> Bool (Interval -> Interval -> Bool) -> (Interval -> Interval -> Bool) -> Eq Interval forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a /= :: Interval -> Interval -> Bool $c/= :: Interval -> Interval -> Bool == :: Interval -> Interval -> Bool $c== :: Interval -> Interval -> Bool Eq) instance YahooParam Interval where key :: Interval -> String key Interval _ = String "interval" symbol :: Interval -> String symbol Interval Daily = String "1d" symbol Interval Weekly = String "1wk" symbol Interval Monthly = String "1mo" data Events = HistoricalPrices | Dividends | Splits instance YahooParam Events where key :: Events -> String key Events _ = String "events" symbol :: Events -> String symbol Events HistoricalPrices = String "history" symbol Events Dividends = String "div" symbol Events Splits = String "split" data FromEndpoint = FromEndpoint Day instance YahooParam FromEndpoint where key :: FromEndpoint -> String key FromEndpoint _ = String "period1" symbol :: FromEndpoint -> String symbol (FromEndpoint Day day) = Integer -> String forall a. Show a => a -> String show (Integer -> String) -> Integer -> String forall a b. (a -> b) -> a -> b $ Day -> Integer dayAsEpoch Day day data ToEndpoint = ToEndpoint Day instance YahooParam ToEndpoint where key :: ToEndpoint -> String key ToEndpoint _ = String "period2" symbol :: ToEndpoint -> String symbol (ToEndpoint Day day) = Integer -> String forall a. Show a => a -> String show (Integer -> String) -> Integer -> String forall a b. (a -> b) -> a -> b $ Day -> Integer dayAsEpoch Day day data TimeRange = After Day | Before Day | Range Day Day timeRangeToEndpoints :: TimeRange -> (FromEndpoint, ToEndpoint) timeRangeToEndpoints :: TimeRange -> (FromEndpoint, ToEndpoint) timeRangeToEndpoints (After Day day) = (Day -> FromEndpoint FromEndpoint Day day, Day -> ToEndpoint ToEndpoint (Day -> ToEndpoint) -> Day -> ToEndpoint forall a b. (a -> b) -> a -> b $ Integer -> Int -> Int -> Day fromGregorian Integer 2050 Int 12 Int 31) timeRangeToEndpoints (Before Day day) = (Day -> FromEndpoint FromEndpoint (Day -> FromEndpoint) -> Day -> FromEndpoint forall a b. (a -> b) -> a -> b $ Integer -> Int -> Int -> Day fromGregorian Integer 1970 Int 1 Int 1, Day -> ToEndpoint ToEndpoint Day day) timeRangeToEndpoints (Range Day from Day to) = (Day -> FromEndpoint FromEndpoint Day from, Day -> ToEndpoint ToEndpoint Day to) data YahooRequest = YahooRequest { YahooRequest -> Ticker ticker :: Ticker, YahooRequest -> Maybe Interval interval :: Maybe Interval, YahooRequest -> Maybe TimeRange period :: Maybe TimeRange } requestUrl :: YahooRequest -> String requestUrl :: YahooRequest -> String requestUrl (YahooRequest { ticker :: YahooRequest -> Ticker ticker = (Ticker String t), interval :: YahooRequest -> Maybe Interval interval = Maybe Interval i, period :: YahooRequest -> Maybe TimeRange period = Maybe TimeRange p }) = String -> String -> String -> String -> String forall r. PrintfType r => String -> r printf String "%s/%s%s" String baseUrl String t ([String] -> String queryString [String] queryParams) where baseUrl :: String baseUrl :: String baseUrl = String "http://query1.finance.yahoo.com/v7/finance/download" rangeEndpoints :: Maybe (FromEndpoint, ToEndpoint) rangeEndpoints :: Maybe (FromEndpoint, ToEndpoint) rangeEndpoints = (TimeRange -> (FromEndpoint, ToEndpoint)) -> Maybe TimeRange -> Maybe (FromEndpoint, ToEndpoint) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap TimeRange -> (FromEndpoint, ToEndpoint) timeRangeToEndpoints Maybe TimeRange p fromEndpoint :: Maybe FromEndpoint fromEndpoint :: Maybe FromEndpoint fromEndpoint = ((FromEndpoint, ToEndpoint) -> FromEndpoint) -> Maybe (FromEndpoint, ToEndpoint) -> Maybe FromEndpoint forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (FromEndpoint, ToEndpoint) -> FromEndpoint forall a b. (a, b) -> a fst Maybe (FromEndpoint, ToEndpoint) rangeEndpoints toEndpoint :: Maybe ToEndpoint toEndpoint :: Maybe ToEndpoint toEndpoint = ((FromEndpoint, ToEndpoint) -> ToEndpoint) -> Maybe (FromEndpoint, ToEndpoint) -> Maybe ToEndpoint forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap (FromEndpoint, ToEndpoint) -> ToEndpoint forall a b. (a, b) -> b snd Maybe (FromEndpoint, ToEndpoint) rangeEndpoints queryParams :: [String] queryParams :: [String] queryParams = [Maybe String] -> [String] forall a. [Maybe a] -> [a] catMaybes ([Maybe String] -> [String]) -> [Maybe String] -> [String] forall a b. (a -> b) -> a -> b $ [ (Interval -> String) -> Maybe Interval -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap Interval -> String forall a. YahooParam a => a -> String paramToString Maybe Interval i, (FromEndpoint -> String) -> Maybe FromEndpoint -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap FromEndpoint -> String forall a. YahooParam a => a -> String paramToString Maybe FromEndpoint fromEndpoint, (ToEndpoint -> String) -> Maybe ToEndpoint -> Maybe String forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b fmap ToEndpoint -> String forall a. YahooParam a => a -> String paramToString Maybe ToEndpoint toEndpoint ] queryString :: [String] -> String queryString :: [String] -> String queryString [] = String "" queryString [String] ps = String -> String -> String forall r. PrintfType r => String -> r printf String "?%s" (String -> [String] -> String forall a. [a] -> [[a]] -> [a] intercalate String "&" [String] ps)