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 +2/−0
- .travis.yml +36/−40
- ChangeLog.md +3/−0
- README.md +3/−1
- Web/Twitter/Conduit.hs +3/−1
- Web/Twitter/Conduit/Base.hs +55/−0
- Web/Twitter/Conduit/Request.hs +1/−1
- sample/searchSource.hs +27/−0
- sample/userstream.hs +2/−3
- tests/BaseSpec.hs +88/−0
- tests/StatusSpec.hs +2/−1
- twitter-conduit.cabal +6/−3
.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 # -[](https://travis-ci.org/himura/twitter-conduit)+[](https://travis-ci.org/himura/twitter-conduit)+[](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