hissmetrics (empty) → 0.1
raw patch · 4 files changed
+220/−0 lines, 4 filesdep +basedep +bytestringdep +conduitsetup-changed
Dependencies added: base, bytestring, conduit, http-conduit, http-types, text, time
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- hissmetrics.cabal +36/−0
- src/Web/KISSmetrics.hs +152/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012, Felipe Lessa <felipe.lessa@gmail.com>++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Felipe Lessa <felipe.lessa@gmail.com> nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ hissmetrics.cabal view
@@ -0,0 +1,36 @@+Name: hissmetrics+Version: 0.1+Synopsis: Unofficial API bindings to KISSmetrics.+Homepage: https://github.com/meteficha/hissmetrics+License: BSD3+License-file: LICENSE+Author: Felipe Lessa+Maintainer: Felipe Lessa <felipe.lessa@gmail.com>+Category: Web+Build-type: Simple+Cabal-version: >=1.6++Description:+ This package provides simple functions that allow you to access+ KISSmetrics using Haskell.+++Source-repository head+ type: git+ location: git://github.com/meteficha/hissmetrics.git+++Library+ hs-source-dirs: src+ Exposed-modules:+ Web.KISSmetrics+ Build-depends: base >= 4.3 && < 5+ , time >= 1.1 && < 2+ , bytestring+ , text >= 0.7 && < 0.12+ , conduit == 0.4.*+ , http-types+ , http-conduit == 1.4.*+ Extensions:+ RecordWildCards,+ OverloadedStrings
+ src/Web/KISSmetrics.hs view
@@ -0,0 +1,152 @@+-- | This module is meant to be imported qualified:+--+-- @+-- import qualified Web.KISSmetrics as KISSmetrics+-- @+module Web.KISSmetrics+ (+ ) where++import Control.Arrow (second)+import Data.Text (Text)+import Data.Time (UTCTime, formatTime)+import qualified Data.ByteString.Char8 as B8+import qualified Data.Conduit as C+import qualified Data.Conduit.List as CL+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import qualified Network.HTTP.Conduit as H+import qualified Network.HTTP.Types as H+++-- | Your KISSmetrics API key.+type APIKey = H.Ascii+++-- | KISSmetrics names and identities are limited to at most 255+-- characters and all commas (@,@) and colons (@:@) are changed+-- to spaces (@ @). Nothing is checked by this Haskell library,+-- so be careful =).+type SimpleText = H.Ascii+++-- | A KISSmetrics property. The property names needs to follow+-- the rules outlined on 'SimpleText'@'s@ documentation. The+-- property value, on the other hand, are only limited to 8 KiB+-- and don't have any other restrictions.+type Property = (SimpleText, Text)+++-- | A timestamp used only to ignore duplicated events.+data Timestamp =+ Automatic+ -- ^ Use KISSmetrics' servers time as the timestamp.+ | Manual UTCTime+ -- ^ Use given time as the timestamp.+++data CallType =+ -- | Record an event.+ Record { eventName :: SimpleText+ -- ^ Name of the event being recorded.+ , identity :: SimpleText+ -- ^ Identity of the person doing the event.+ , timestamp :: Timestamp+ -- ^ See 'Timestamp'.+ , properties :: [Property]+ -- ^ Any additional properties you may want.+ }+ -- | Set user properties without recording an event.+ | SetProps { identity :: SimpleText+ -- ^ Identity of the person whose properties will+ -- to be changed.+ , timestamp :: Timestamp+ -- ^ See 'Timestamp'.+ , properties :: [Property]+ -- ^ Properties to be set.+ }+ -- | Alias two identities as the same one.+ | Alias { identity :: SimpleText+ -- ^ Identity of the person you're aliasing.+ , identity' :: SimpleText+ -- ^ Other identity you want to alias.+ }+++-- | Call KISSmetrics' API. See 'CallType' for documentation+-- about which calls you may make.+--+-- Note that official KISSmetrics' APIs provide many functions+-- (usually four) while we provide just this one and a sum data+-- type. This function alone does the work of @record@, @set@,+-- @identify@ and @alias@.+--+-- TODO: Currently there's no support for automatically retrying+-- failed request, you need to retry yourself.+call :: H.Manager -- ^ HTTP connection manager (cf. 'H.newManager').+ -> APIKey -- ^ Your KISSmetrics API key.+ -> CallType -- ^ Which call you would like to make.+ -> IO ()+call manager apikey callType =+ C.runResourceT $ do+ -- Create the request+ let (path, args) = callInfo callType+ request =+ H.def { H.method = "GET"+ , H.secure = True+ , H.host = "trk.kissmetrics.com"+ , H.path = path+ , H.queryString =+ H.renderSimpleQuery False $+ ("_k", apikey) : args+ , H.redirectCount = 0+ }++ -- Make the call+ H.Response {..} <- H.http request manager++ -- By default http-conduit will already throw an exception on+ -- anything other than 200 Ok, so we don't need to check the+ -- response. We consume it just to free the resources as early+ -- as possible. (If we just closed and KISSmetrics decided to+ -- give an OK message in the body, the connection would not be+ -- keep-alived correctly.)+ responseBody C.$$ CL.sinkNull++++-- | Internal function. Given a 'CallType', return the URL to be+-- used and generate a list of arguments.+callInfo :: CallType -> (H.Ascii, H.SimpleQuery)+callInfo Record {..} =+ ( "/e"+ , (:) ("_n", eventName) $+ (:) ("_p", identity) $+ timestampInfo timestamp $+ propsInfo properties+ )+callInfo SetProps {..} =+ ( "/s"+ , (:) ("_p", identity) $+ timestampInfo timestamp $+ propsInfo properties+ )+callInfo Alias {..} =+ ( "/a"+ , [("_p", identity), ("_n", identity')]+ )+++-- | Generate a difference list of arguments for a timestamp.+timestampInfo :: Timestamp+ -> (H.SimpleQuery -> H.SimpleQuery) -- ^ Difference list.+timestampInfo Automatic = id+timestampInfo (Manual t) =+ (:) ("_d", "1") .+ (:) ("_t", B8.pack $ formatTime locale "%s" t)+ where locale = error "Web.KISSmetrics.timestampInfo: locale shouldn't be needed."+++-- | Generate a list of arguments for a list of properties.+propsInfo :: [Property] -> H.SimpleQuery+propsInfo = map (second TE.encodeUtf8)