packages feed

twitter-conduit 0.1.0 → 0.1.1

raw patch · 12 files changed

+228/−50 lines, 12 filesdep ~bytestringdep ~lensPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: bytestring, lens

API changes (from Hackage documentation)

+ Web.Twitter.Conduit: sourceWithSearchResult :: (MonadResource m, FromJSON responseType, HasMaxIdParam (APIRequest apiName (SearchResult [responseType]))) => TWInfo -> Manager -> APIRequest apiName (SearchResult [responseType]) -> m (SearchResult (Source m responseType))
+ Web.Twitter.Conduit: sourceWithSearchResult' :: (MonadResource m, HasMaxIdParam (APIRequest apiName (SearchResult [responseType]))) => TWInfo -> Manager -> APIRequest apiName (SearchResult [responseType]) -> m (SearchResult (Source m Value))
+ Web.Twitter.Conduit.Base: sourceWithSearchResult :: (MonadResource m, FromJSON responseType, HasMaxIdParam (APIRequest apiName (SearchResult [responseType]))) => TWInfo -> Manager -> APIRequest apiName (SearchResult [responseType]) -> m (SearchResult (Source m responseType))
+ Web.Twitter.Conduit.Base: sourceWithSearchResult' :: (MonadResource m, HasMaxIdParam (APIRequest apiName (SearchResult [responseType]))) => TWInfo -> Manager -> APIRequest apiName (SearchResult [responseType]) -> m (SearchResult (Source m Value))
- Web.Twitter.Conduit.Parameters: class Parameters a_albG => HasContributorDetailsParam a_albG where contributorDetails = wrappedParam "contributor_details" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anfd => HasContributorDetailsParam a_anfd where contributorDetails = wrappedParam "contributor_details" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_al6I => HasCountParam a_al6I where count = wrappedParam "count" PVInteger unPVInteger
+ Web.Twitter.Conduit.Parameters: class Parameters a_anaf => HasCountParam a_anaf where count = wrappedParam "count" PVInteger unPVInteger
- Web.Twitter.Conduit.Parameters: class Parameters a_al9y => HasCursorParam a_al9y where cursor = wrappedParam "cursor" PVInteger unPVInteger
+ Web.Twitter.Conduit.Parameters: class Parameters a_and5 => HasCursorParam a_and5 where cursor = wrappedParam "cursor" PVInteger unPVInteger
- Web.Twitter.Conduit.Parameters: class Parameters a_alfW => HasDisplayCoordinatesParam a_alfW where displayCoordinates = wrappedParam "display_coordinates" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anjt => HasDisplayCoordinatesParam a_anjt where displayCoordinates = wrappedParam "display_coordinates" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alaY => HasExcludeRepliesParam a_alaY where excludeReplies = wrappedParam "exclude_replies" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anev => HasExcludeRepliesParam a_anev where excludeReplies = wrappedParam "exclude_replies" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alju => HasFilterLevelParam a_alju where filterLevel = wrappedParam "filter_level" PVString unPVString
+ Web.Twitter.Conduit.Parameters: class Parameters a_ann1 => HasFilterLevelParam a_ann1 where filterLevel = wrappedParam "filter_level" PVString unPVString
- Web.Twitter.Conduit.Parameters: class Parameters a_aln2 => HasFollowParam a_aln2 where follow = wrappedParam "follow" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anqz => HasFollowParam a_anqz where follow = wrappedParam "follow" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alfe => HasInReplyToStatusIdParam a_alfe where inReplyToStatusId = wrappedParam "in_reply_to_status_id" PVInteger unPVInteger
+ Web.Twitter.Conduit.Parameters: class Parameters a_aniL => HasInReplyToStatusIdParam a_aniL where inReplyToStatusId = wrappedParam "in_reply_to_status_id" PVInteger unPVInteger
- Web.Twitter.Conduit.Parameters: class Parameters a_alco => HasIncludeEntitiesParam a_alco where includeEntities = wrappedParam "include_entities" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anfV => HasIncludeEntitiesParam a_anfV where includeEntities = wrappedParam "include_entities" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alew => HasIncludeMyRetweetParam a_alew where includeMyRetweet = wrappedParam "include_my_retweet" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_ani3 => HasIncludeMyRetweetParam a_ani3 where includeMyRetweet = wrappedParam "include_my_retweet" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_aldO => HasIncludeRtsParam a_aldO where includeRts = wrappedParam "include_rts" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anhl => HasIncludeRtsParam a_anhl where includeRts = wrappedParam "include_rts" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_ald6 => HasIncludeUserEntitiesParam a_ald6 where includeUserEntities = wrappedParam "include_user_entities" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_angD => HasIncludeUserEntitiesParam a_angD where includeUserEntities = wrappedParam "include_user_entities" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alhm => HasLangParam a_alhm where lang = wrappedParam "lang" PVString unPVString
+ Web.Twitter.Conduit.Parameters: class Parameters a_ankT => HasLangParam a_ankT where lang = wrappedParam "lang" PVString unPVString
- Web.Twitter.Conduit.Parameters: class Parameters a_ali4 => HasLanguageParam a_ali4 where language = wrappedParam "language" PVString unPVString
+ Web.Twitter.Conduit.Parameters: class Parameters a_anlB => HasLanguageParam a_anlB where language = wrappedParam "language" PVString unPVString
- Web.Twitter.Conduit.Parameters: class Parameters a_aliM => HasLocaleParam a_aliM where locale = wrappedParam "locale" PVString unPVString
+ Web.Twitter.Conduit.Parameters: class Parameters a_anmj => HasLocaleParam a_anmj where locale = wrappedParam "locale" PVString unPVString
- Web.Twitter.Conduit.Parameters: class Parameters a_alnK => HasMapParam a_alnK where map = wrappedParam "map" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anrh => HasMapParam a_anrh where map = wrappedParam "map" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_al88 => HasMaxIdParam a_al88 where maxId = wrappedParam "max_id" PVInteger unPVInteger
+ Web.Twitter.Conduit.Parameters: class Parameters a_anbF => HasMaxIdParam a_anbF where maxId = wrappedParam "max_id" PVInteger unPVInteger
- Web.Twitter.Conduit.Parameters: class Parameters a_alos => HasMediaIdsParam a_alos where mediaIds = wrappedParam "media_ids" PVIntegerArray unPVIntegerArray
+ Web.Twitter.Conduit.Parameters: class Parameters a_anrZ => HasMediaIdsParam a_anrZ where mediaIds = wrappedParam "media_ids" PVIntegerArray unPVIntegerArray
- Web.Twitter.Conduit.Parameters: class Parameters a_al8Q => HasPageParam a_al8Q where page = wrappedParam "page" PVInteger unPVInteger
+ Web.Twitter.Conduit.Parameters: class Parameters a_ancn => HasPageParam a_ancn where page = wrappedParam "page" PVInteger unPVInteger
- Web.Twitter.Conduit.Parameters: class Parameters a_algE => HasPossiblySensitiveParam a_algE where possiblySensitive = wrappedParam "possibly_sensitive" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_ankb => HasPossiblySensitiveParam a_ankb where possiblySensitive = wrappedParam "possibly_sensitive" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alkU => HasRepliesParam a_alkU where replies = wrappedParam "replies" PVString unPVString
+ Web.Twitter.Conduit.Parameters: class Parameters a_anor => HasRepliesParam a_anor where replies = wrappedParam "replies" PVString unPVString
- Web.Twitter.Conduit.Parameters: class Parameters a_al7q => HasSinceIdParam a_al7q where sinceId = wrappedParam "since_id" PVInteger unPVInteger
+ Web.Twitter.Conduit.Parameters: class Parameters a_anaX => HasSinceIdParam a_anaX where sinceId = wrappedParam "since_id" PVInteger unPVInteger
- Web.Twitter.Conduit.Parameters: class Parameters a_almk => HasSkipStatusParam a_almk where skipStatus = wrappedParam "skip_status" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_anpR => HasSkipStatusParam a_anpR where skipStatus = wrappedParam "skip_status" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alkc => HasStallWarningsParam a_alkc where stallWarnings = wrappedParam "stall_warnings" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_annJ => HasStallWarningsParam a_annJ where stallWarnings = wrappedParam "stall_warnings" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_alag => HasTrimUserParam a_alag where trimUser = wrappedParam "trim_user" PVBool unPVBool
+ Web.Twitter.Conduit.Parameters: class Parameters a_andN => HasTrimUserParam a_andN where trimUser = wrappedParam "trim_user" PVBool unPVBool
- Web.Twitter.Conduit.Parameters: class Parameters a_allC => HasUntilParam a_allC where until = wrappedParam "until" PVDay unPVDay
+ Web.Twitter.Conduit.Parameters: class Parameters a_anp9 => HasUntilParam a_anp9 where until = wrappedParam "until" PVDay unPVDay
- Web.Twitter.Conduit.Parameters: contributorDetails :: HasContributorDetailsParam a_albG => Lens' a_albG (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: contributorDetails :: HasContributorDetailsParam a_anfd => Lens' a_anfd (Maybe Bool)
- Web.Twitter.Conduit.Parameters: count :: HasCountParam a_al6I => Lens' a_al6I (Maybe Integer)
+ Web.Twitter.Conduit.Parameters: count :: HasCountParam a_anaf => Lens' a_anaf (Maybe Integer)
- Web.Twitter.Conduit.Parameters: cursor :: HasCursorParam a_al9y => Lens' a_al9y (Maybe Integer)
+ Web.Twitter.Conduit.Parameters: cursor :: HasCursorParam a_and5 => Lens' a_and5 (Maybe Integer)
- Web.Twitter.Conduit.Parameters: displayCoordinates :: HasDisplayCoordinatesParam a_alfW => Lens' a_alfW (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: displayCoordinates :: HasDisplayCoordinatesParam a_anjt => Lens' a_anjt (Maybe Bool)
- Web.Twitter.Conduit.Parameters: excludeReplies :: HasExcludeRepliesParam a_alaY => Lens' a_alaY (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: excludeReplies :: HasExcludeRepliesParam a_anev => Lens' a_anev (Maybe Bool)
- Web.Twitter.Conduit.Parameters: filterLevel :: HasFilterLevelParam a_alju => Lens' a_alju (Maybe Text)
+ Web.Twitter.Conduit.Parameters: filterLevel :: HasFilterLevelParam a_ann1 => Lens' a_ann1 (Maybe Text)
- Web.Twitter.Conduit.Parameters: follow :: HasFollowParam a_aln2 => Lens' a_aln2 (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: follow :: HasFollowParam a_anqz => Lens' a_anqz (Maybe Bool)
- Web.Twitter.Conduit.Parameters: inReplyToStatusId :: HasInReplyToStatusIdParam a_alfe => Lens' a_alfe (Maybe Integer)
+ Web.Twitter.Conduit.Parameters: inReplyToStatusId :: HasInReplyToStatusIdParam a_aniL => Lens' a_aniL (Maybe Integer)
- Web.Twitter.Conduit.Parameters: includeEntities :: HasIncludeEntitiesParam a_alco => Lens' a_alco (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: includeEntities :: HasIncludeEntitiesParam a_anfV => Lens' a_anfV (Maybe Bool)
- Web.Twitter.Conduit.Parameters: includeMyRetweet :: HasIncludeMyRetweetParam a_alew => Lens' a_alew (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: includeMyRetweet :: HasIncludeMyRetweetParam a_ani3 => Lens' a_ani3 (Maybe Bool)
- Web.Twitter.Conduit.Parameters: includeRts :: HasIncludeRtsParam a_aldO => Lens' a_aldO (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: includeRts :: HasIncludeRtsParam a_anhl => Lens' a_anhl (Maybe Bool)
- Web.Twitter.Conduit.Parameters: includeUserEntities :: HasIncludeUserEntitiesParam a_ald6 => Lens' a_ald6 (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: includeUserEntities :: HasIncludeUserEntitiesParam a_angD => Lens' a_angD (Maybe Bool)
- Web.Twitter.Conduit.Parameters: lang :: HasLangParam a_alhm => Lens' a_alhm (Maybe Text)
+ Web.Twitter.Conduit.Parameters: lang :: HasLangParam a_ankT => Lens' a_ankT (Maybe Text)
- Web.Twitter.Conduit.Parameters: language :: HasLanguageParam a_ali4 => Lens' a_ali4 (Maybe Text)
+ Web.Twitter.Conduit.Parameters: language :: HasLanguageParam a_anlB => Lens' a_anlB (Maybe Text)
- Web.Twitter.Conduit.Parameters: locale :: HasLocaleParam a_aliM => Lens' a_aliM (Maybe Text)
+ Web.Twitter.Conduit.Parameters: locale :: HasLocaleParam a_anmj => Lens' a_anmj (Maybe Text)
- Web.Twitter.Conduit.Parameters: map :: HasMapParam a_alnK => Lens' a_alnK (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: map :: HasMapParam a_anrh => Lens' a_anrh (Maybe Bool)
- Web.Twitter.Conduit.Parameters: maxId :: HasMaxIdParam a_al88 => Lens' a_al88 (Maybe Integer)
+ Web.Twitter.Conduit.Parameters: maxId :: HasMaxIdParam a_anbF => Lens' a_anbF (Maybe Integer)
- Web.Twitter.Conduit.Parameters: mediaIds :: HasMediaIdsParam a_alos => Lens' a_alos (Maybe [Integer])
+ Web.Twitter.Conduit.Parameters: mediaIds :: HasMediaIdsParam a_anrZ => Lens' a_anrZ (Maybe [Integer])
- Web.Twitter.Conduit.Parameters: page :: HasPageParam a_al8Q => Lens' a_al8Q (Maybe Integer)
+ Web.Twitter.Conduit.Parameters: page :: HasPageParam a_ancn => Lens' a_ancn (Maybe Integer)
- Web.Twitter.Conduit.Parameters: possiblySensitive :: HasPossiblySensitiveParam a_algE => Lens' a_algE (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: possiblySensitive :: HasPossiblySensitiveParam a_ankb => Lens' a_ankb (Maybe Bool)
- Web.Twitter.Conduit.Parameters: replies :: HasRepliesParam a_alkU => Lens' a_alkU (Maybe Text)
+ Web.Twitter.Conduit.Parameters: replies :: HasRepliesParam a_anor => Lens' a_anor (Maybe Text)
- Web.Twitter.Conduit.Parameters: sinceId :: HasSinceIdParam a_al7q => Lens' a_al7q (Maybe Integer)
+ Web.Twitter.Conduit.Parameters: sinceId :: HasSinceIdParam a_anaX => Lens' a_anaX (Maybe Integer)
- Web.Twitter.Conduit.Parameters: skipStatus :: HasSkipStatusParam a_almk => Lens' a_almk (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: skipStatus :: HasSkipStatusParam a_anpR => Lens' a_anpR (Maybe Bool)
- Web.Twitter.Conduit.Parameters: stallWarnings :: HasStallWarningsParam a_alkc => Lens' a_alkc (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: stallWarnings :: HasStallWarningsParam a_annJ => Lens' a_annJ (Maybe Bool)
- Web.Twitter.Conduit.Parameters: trimUser :: HasTrimUserParam a_alag => Lens' a_alag (Maybe Bool)
+ Web.Twitter.Conduit.Parameters: trimUser :: HasTrimUserParam a_andN => Lens' a_andN (Maybe Bool)
- Web.Twitter.Conduit.Parameters: until :: HasUntilParam a_allC => Lens' a_allC (Maybe Day)
+ Web.Twitter.Conduit.Parameters: until :: HasUntilParam a_anp9 => Lens' a_anp9 (Maybe Day)

Files

.gitignore view
@@ -24,3 +24,5 @@ cabal-dev/ cabal.sandbox.config .cabal-sandbox+.stack-work/+stack.yaml
.travis.yml view
@@ -1,7 +1,18 @@-language: haskell+language: sh+sudo: required  env:+  matrix:+    - GHCVER=7.4.2+    - GHCVER=7.6.3+    - GHCVER=7.8.4+    - GHCVER=7.10.1 CABAL_FLAGS="-frun-integrated-test"   global:+    # HALCYON_AWS_ACCESS_KEY_ID+    - secure: "PTnc4TbawOwE6Z3v9QP5TRVYKg7FXU4PKgMqRPOy7HRwCriF+v4CxkyFgI2Ve614z85dF3kq9qZrhtyRuTSTL/SAu17Tz57+XhH0laGDF/7/h637ZRxy0+OBv/EDO0z6cJ1+8ndAl+5fbblQ8nmn5fgPrVCfbNIpujcjOSfs8+4="+    # HALCYON_AWS_SECRET_ACCESS_KEY+    - secure: "RCLM7gnzb0b4WgYeDQ+z1cn+IvsJMaqldLppJRM/b+oBeH5v+IZ0BL4hRk187iZsXJdMADC6MAeEchcV0rTseit/zKQAk6fx7360Sv+MdlzNbVHSiO7LpwbKTOvMfIQ5hB/S8oTuC1qmY18JhShO1lE6RpFsitwNdENRZv85fuQ="+     # OAUTH_CONSUMER_KEY     - secure: "U3hh6wJf87tdZmwLtPyMQ0ci39ouKvTm/JCi0CCz2jaPvWZR+4Tt7aYV5WYqzjSmgfBOqKpXTpwFBcvvWRty8rI1b8OtrlljC1zUcgf/hsz3hfPtv+GKW/ldYnqg7znyeAdxWEF1a4JszKgOJaGMdX7zSpFewgwEq7T4jAlebLA="     # OAUTH_CONSUMER_SECRET@@ -10,56 +21,41 @@     - secure: "dW2pYRplxJ7HmJEo3lMgLlzfdOylBvWiV4PJt1j4GMDPJBOu3RM0h3zNkkxDoS9D0wWRkBEH0iN2Bh08v2z7sJtF3f/kgLvPlOy5mNSYcozwMdHJRlJEcXaGULHbZ4p79lVIOdTAhY2WU2QdP7PEv0BiqqVcysnfK0TGkTa+KEc="     # OAUTH_ACCESS_SECRET     - secure: "I5hzi7sONDn8KJAhmkroHsGNJ2zUxYq2iGamTV9lgMUDH0bwpMx+guzfZr+fGesdlUphM0t+ZCh9YH8BoVJsjZ/db9u/lotg78DKp1QwhrWnISqWj6TIfXrSLPkBwY+xFtxl6Ihsjyl+ileiK5sb0C9mC+zXidgBqEM73miAokY="-  matrix:-    - GHCVER=7.4.2-    - GHCVER=7.6.3-    - GHCVER=7.8.3 USE_COVERALLS=1 CABAL_FLAGS="-frun-integrated-test"-    - GHCVER=head  matrix:   allow_failures:     - env: GHCVER=7.4.2-    - env: GHCVER=head+    - env: GHCVER=7.6.3  before_install:-  - |-    if [ $GHCVER = `ghc --numeric-version` ]; then-      echo "use system ghc: `which ghc` `ghc --numeric-version`"-    else-      travis_retry sudo add-apt-repository -y ppa:hvr/ghc-      travis_retry sudo apt-get update-      travis_retry sudo apt-get install  -y --force-yes cabal-install-1.18 ghc-$GHCVER-      export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/1.18/bin:$PATH-      echo "use ppa:hvr/ghc: `which ghc` `ghc --numeric-version`"-    fi-    cabal install Cabal --constraint="Cabal >= 1.18 && < 1.19"+  - eval "$( curl -sL https://github.com/mietek/halcyon/raw/master/setup.sh )"+  - export HALCYON_GHC_VERSION=$GHCVER HALCYON_CABAL_VERSION=1.22.4.0+  - export HALCYON_S3_BUCKET=himura-halcyon  install:-  - export PATH=$HOME/.cabal/bin:$PATH-  - which cabal-  - travis_retry cabal update-  # GHC 7.8.3 exports transformers-0.3.0, but happy and our package installs transformers 0.4 series.-  # However, doctest fails when we have multiple version of transformers.-  # To prevent this, we restrict transformers version to (< 0.4)-  - cabal install happy --constraint="transformers < 0.4"-  - cabal install --only-dependencies --enable-tests-  - "[ -n \"$USE_COVERALLS\" ] && travis_retry cabal install hpc-coveralls || true"-  - ghc-pkg list+  - HALCYON_SANDBOX_EXTRA_APPS="hpc-coveralls happy" HALCYON_SANDBOX_EXTRA_CONFIGURE_FLAGS="--enable-tests --only-dependencies $CABAL_FLAGS" halcyon build+  - ln -s /app/sandbox/cabal.sandbox.config .  script:-  - |-    if [ -n "$USE_COVERALLS" ]; then-      cabal configure --enable-tests --enable-library-coverage $CABAL_FLAGS-    else-      cabal configure --enable-tests $CABAL_FLAGS-    fi-  - cabal build+  - cabal configure --enable-tests --enable-library-coverage $CABAL_FLAGS+  - travis_wait run-cabal-test --cabal-name=cabal --show-details=always++  # tests source distribution package+  - cabal sdist   - |-    if [ -n "$USE_COVERALLS" ]; then-      run-cabal-test --show-details=always-    else-      cabal test --show-details=always+    PKGNAME="$(cabal info . | awk '/^\*/{print $2}')"+    SRCTGZ="${PKGNAME}.tar.gz"+    cd dist/+    if [ -f "$SRCTGZ" ]; then+      tar xvzf "$SRCTGZ"+      cd "$PKGNAME"+      NG=$(git ls-tree HEAD --full-tree -r | while read perm blob hash name; do [ -e "$name" ] || echo NG "$name"; done)+      if [ -n "$NG" ]; then+        echo "Missing files:"+        echo $NG+        exit 1+      fi     fi  after_script:-  - "[ -n \"$USE_COVERALLS\" ] && hpc-coveralls --exclude-dir=tests spec_main || true"+  - hpc-coveralls --exclude-dir=tests tests
+ ChangeLog.md view
@@ -0,0 +1,3 @@+## 0.1.1++* Add `sourceWithSearchResult` and `sourceWithSearchResult'`
README.md view
@@ -1,6 +1,7 @@ # twitter-conduit: An Conduit based Twitter API library for Haskell # -[![Build Status](https://travis-ci.org/himura/twitter-conduit.png?branch=master)](https://travis-ci.org/himura/twitter-conduit)+[![Travis](https://img.shields.io/travis/himura/twitter-conduit.svg)](https://travis-ci.org/himura/twitter-conduit)+[![Hackage-Deps](https://img.shields.io/hackage-deps/v/twitter-conduit.svg)](http://packdeps.haskellers.com/feed?needle=twitter-conduit)  ## About ## @@ -31,6 +32,7 @@ and then,  ~~~~+$ cabal install --only-dependencies -fbuild-samples $ cabal configure -fbuild-samples $ cabal build ~~~~
Web/Twitter/Conduit.hs view
@@ -36,8 +36,10 @@        , sourceWithMaxId'        , sourceWithCursor        , sourceWithCursor'+       , sourceWithSearchResult+       , sourceWithSearchResult' -       -- * Backward compativility+       -- * Backward compatibility        -- $backward        ) where 
Web/Twitter/Conduit/Base.hs view
@@ -14,6 +14,8 @@        , sourceWithMaxId'        , sourceWithCursor        , sourceWithCursor'+       , sourceWithSearchResult+       , sourceWithSearchResult'        , TwitterBaseM        , endpoint        , makeRequest@@ -38,6 +40,8 @@ import qualified Data.Conduit as C import qualified Data.Conduit.Attoparsec as CA import qualified Data.Conduit.List as CL+import qualified Data.Map as M+import Data.Monoid import qualified Data.Text.Encoding as T import Network.HTTP.Client.MultipartFormData import qualified Network.HTTP.Conduit as HTTP@@ -283,6 +287,57 @@         res <- lift $ call info mgr $ relax $ req & cursor ?~ cur         CL.sourceList $ contents res         loop $ nextCursor res++-- | A wrapper function to perform multiple API request with @SearchResult@.+sourceWithSearchResult :: ( MonadResource m+                          , FromJSON responseType+                          , HasMaxIdParam (APIRequest apiName (SearchResult [responseType]))+                          )+                       => TWInfo -- ^ Twitter Setting+                       -> HTTP.Manager+                       -> APIRequest apiName (SearchResult [responseType])+                       -> m (SearchResult (C.Source m responseType))+sourceWithSearchResult info mgr req = do+    res <- call info mgr req+    let body = CL.sourceList (res ^. searchResultStatuses) <>+               loop (res ^. searchResultSearchMetadata . searchMetadataNextResults)+    return $ res & searchResultStatuses .~ body+  where+    origQueryMap = req ^. params . to M.fromList+    loop Nothing = CL.sourceNull+    loop (Just nextResultsStr) = do+        let nextResults = nextResultsStr & HT.parseSimpleQuery . T.encodeUtf8 & traversed . _2 %~ (PVString . T.decodeUtf8)+            nextParams = M.toList $ M.union (M.fromList nextResults) origQueryMap+        res <- call info mgr $ req & params .~ nextParams+        CL.sourceList (res ^. searchResultStatuses)+        loop $ res ^. searchResultSearchMetadata . searchMetadataNextResults++-- | A wrapper function to perform multiple API request with @SearchResult@.+sourceWithSearchResult' :: ( MonadResource m+                           , HasMaxIdParam (APIRequest apiName (SearchResult [responseType]))+                           )+                        => TWInfo -- ^ Twitter Setting+                        -> HTTP.Manager+                        -> APIRequest apiName (SearchResult [responseType])+                        -> m (SearchResult (C.Source m Value))+sourceWithSearchResult' info mgr req = do+    res <- call info mgr $ relax req+    let body = CL.sourceList (res ^. searchResultStatuses) <>+               loop (res ^. searchResultSearchMetadata . searchMetadataNextResults)+    return $ res & searchResultStatuses .~ body+  where+    origQueryMap = req ^. params . to M.fromList+    relax :: FromJSON value+          => APIRequest apiName (SearchResult responseType)+          -> APIRequest apiName (SearchResult value)+    relax = unsafeCoerce+    loop Nothing = CL.sourceNull+    loop (Just nextResultsStr) = do+        let nextResults = nextResultsStr & HT.parseSimpleQuery . T.encodeUtf8 & traversed . _2 %~ (PVString . T.decodeUtf8)+            nextParams = M.toList $ M.union (M.fromList nextResults) origQueryMap+        res <- call info mgr $ relax $ req & params .~ nextParams+        CL.sourceList (res ^. searchResultStatuses)+        loop $ res ^. searchResultSearchMetadata . searchMetadataNextResults  sinkJSON :: ( MonadThrow m             ) => C.Consumer ByteString m Value
Web/Twitter/Conduit/Request.hs view
@@ -31,7 +31,7 @@ -- see details: https://ghc.haskell.org/trac/ghc/ticket/5820 #if __GLASGOW_HASKELL__ >= 706 -- $setup--- >>> :set -XOverloadedStrings -XRank2Types -XEmptyDataDecls -XFlexibleInstances -XOverlappingInstances -XIncoherentInstances+-- >>> :set -XOverloadedStrings -XRank2Types -XEmptyDataDecls -XFlexibleInstances -- >>> import Control.Lens -- >>> import Data.Default -- >>> import Web.Twitter.Conduit.Parameters
+ sample/searchSource.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE OverloadedStrings #-}+module Main where++import Web.Twitter.Conduit+import Web.Twitter.Types.Lens+import Common++import Control.Lens+import Control.Monad.IO.Class+import Data.Conduit+import qualified Data.Conduit.List as CL+import qualified Data.Text as T+import Network.HTTP.Conduit+import System.Environment++main :: IO ()+main = do+    [num, keyword] <- getArgs++    twInfo <- getTWInfoFromEnv++    withManager $ \mgr -> do+        res <- sourceWithSearchResult twInfo mgr $ searchTweets $ T.pack keyword+        let metadata = res ^. searchResultSearchMetadata+        liftIO . putStrLn $ "search completed in: " ++ metadata ^. searchMetadataCompletedIn . to show+        liftIO . putStrLn $ "search result max id: " ++ metadata ^. searchMetadataMaxId . to show+        res ^. searchResultStatuses $$ CL.isolate (read num) =$ CL.mapM_ (liftIO . print)
sample/userstream.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE PatternGuards #-}  import Web.Twitter.Conduit@@ -37,7 +36,7 @@     twInfo <- getTWInfoFromEnv     withManager $ \mgr -> do         src <- stream twInfo mgr userstream-        src C.$$+- CL.mapM_ (^! act (liftIO . printTL))+        src C.$$+- CL.mapM_ (liftIO . printTL)  showStatus :: AsStatus s => s -> T.Text showStatus s = T.concat [ s ^. user . userScreenName@@ -53,7 +52,7 @@                                                      ] printTL (SEvent event)     | (event^.evEvent) == "favorite" || (event^.evEvent) == "unfavorite",-      Just (ETStatus st) <- (event ^. evTargetObject) = do+      Just (ETStatus st) <- event ^. evTargetObject = do           let (fromUser, fromIcon) = evUserInfo (event^.evSource)               (toUser, _toIcon) = evUserInfo (event^.evTarget)               evUserInfo (ETUser u) = (u ^. userScreenName, u ^. userProfileImageURL)
+ tests/BaseSpec.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE OverloadedStrings #-}++module BaseSpec where++import Web.Twitter.Conduit.Response+import Web.Twitter.Conduit.Base++import Control.Applicative+import Control.Lens+import Data.Aeson+import Data.Aeson.Lens+import Data.Conduit+import qualified Data.Conduit.Attoparsec as CA+import Data.Maybe+import qualified Data.Text as T+import qualified Network.HTTP.Types as HT++import Test.Hspec++spec :: Spec+spec = do+    unit++unit :: Spec+unit = do+    describe "checkResponse" $ do+        describe "when the response has \"errors\" key" $ do+            let errorMessage = fromJust . decode $ "{\"errors\":[{\"message\":\"Sorry, that page does not exist\",\"code\":34}]}"+                response = Response HT.status404 [] errorMessage+                result = checkResponse response++            it "returns TwitterErrorResponse" $ do+                case result of+                    Left res@(TwitterErrorResponse _ _ msgs) -> do+                        res `shouldBe` TwitterErrorResponse HT.status404 [] [TwitterErrorMessage 34 ""]+                        twitterErrorMessage (head msgs) `shouldBe` "Sorry, that page does not exist"+                    _ -> expectationFailure $ "Unexpected " ++ show result+        describe "when the response does not has \"errors\" key but have error status code" $ do+            let errorMessage = fromJust . decode $ "{}"+                response = Response HT.status404 [] errorMessage+                result = checkResponse response+            it "returns TwitterStatusError" $ do+                case result of+                    Left (TwitterStatusError st hdr body) -> do+                        st `shouldBe` HT.status404+                        hdr `shouldBe` []+                        body `shouldBe` errorMessage+                    _ -> expectationFailure $ "Unexpected " ++ show result++    describe "sinkJSON" $ do+        describe "when valid JSON input" $ do+            let input = "{\"test\": \"input\", \"status\": 200 }"+            it "can consume the input from Source and returns JSON Value" $ do+                res <- yield input $$ sinkJSON+                res ^. key "test" . _String `shouldBe` "input"+                res ^? key "status" . _Integer `shouldBe` Just 200+        describe "when invalid JSON input" $ do+            let input = "{]"+            it "should raise Data.Conduit.Attoparsec.ParseError" $ do+                let parseErrorException (CA.ParseError {}) = True+                    parseErrorException _ = False+                    action = yield input $$ sinkJSON+                action `shouldThrow` parseErrorException++    describe "sinkFromJSON" $ do+        describe "when valid JSON input" $ do+            let input = "{\"test\": \"input\", \"status\": 200 }"+            it "can consume the input from Source and returns a value which type is the specified one" $ do+                res <- yield input $$ sinkFromJSON+                res `shouldBe` TestJSON "input" 200+        describe "when the JSON value does not have expected format" $ do+            let input = "{\"status\": 200}"+            it "should raise FromJSONError" $ do+                let fromJSONException (FromJSONError {}) = True+                    fromJSONException _ = False+                    action :: IO TestJSON+                    action = yield input $$ sinkFromJSON+                action `shouldThrow` fromJSONException++data TestJSON = TestJSON+    { testField :: T.Text+    , testStatus :: Int+    } deriving (Show, Eq)+instance FromJSON TestJSON where+    parseJSON (Object o) =+        TestJSON <$> o .: "test"+                 <*> o .: "status"+    parseJSON v = fail $ "Unexpected: " ++ show v
tests/StatusSpec.hs view
@@ -6,6 +6,7 @@ import Control.Lens import Data.Conduit import qualified Data.Conduit.List as CL+import Data.Time import Network.HTTP.Conduit import System.IO.Unsafe import Web.Twitter.Conduit (call, accountVerifyCredentials, sourceWithMaxId, TWInfo)@@ -74,7 +75,7 @@             res <- withManager $ \mgr -> call twInfo mgr $ showId 477833886768959488             res ^. statusId `shouldBe` 477833886768959488             res ^. statusText `shouldBe` "真紅かわいいはアレセイア"-            res ^. statusCreatedAt `shouldBe` "Sat Jun 14 15:24:10 +0000 2014"+            res ^. statusCreatedAt `shouldBe` UTCTime (fromGregorian 2014 6 14) (secondsToDiffTime 55450)             res ^. statusUser . userScreenName `shouldBe` "thimura"      describe "update & destroyId" $ do
twitter-conduit.cabal view
@@ -1,5 +1,5 @@ name:              twitter-conduit-version:           0.1.0+version:           0.1.1 license:           BSD3 license-file:      LICENSE author:            HATTORI Hiroki, Hideyuki Tanaka, Takahiro HIMURA@@ -25,7 +25,9 @@   .gitignore   .travis.yml   README.md+  ChangeLog.md   sample/*.hs+  tests/*.hs  source-repository head   type: git@@ -64,7 +66,7 @@     , aeson >= 0.7.0.5     , attoparsec >= 0.10     , data-default >= 0.3-    , bytestring >= 0.9+    , bytestring >= 0.10.2     , text >= 0.11     , containers     , time@@ -74,7 +76,7 @@   if flag(lens-aeson)     build-depends:         lens-aeson >= 1-      , lens >= 4.4 && < 4.5+      , lens >= 4.4   else     build-depends:         lens >= 4.0 && < 4.4@@ -159,6 +161,7 @@   other-modules:     Spec     ApiSpec+    BaseSpec     StatusSpec     TestUtils