nationstates 0.3.0.1 → 0.4.0.0
raw patch · 8 files changed
+363/−46 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- NationStates.Core: expected :: String -> String -> a
+ NationStates: newContext' :: String -> Bool -> IO Context
+ NationStates.Core: contextIsSecure :: Context -> Bool
+ NationStates.Core: pureIf :: Alternative f => (a -> Bool) -> a -> f a
+ NationStates.RateLimit: setDelay :: Rational -> RateLimit -> RateLimit
+ NationStates.Region: delegatevotes :: Region Integer
+ NationStates.Region: embassies :: Region [String]
+ NationStates.Region: flag :: Region (Maybe String)
+ NationStates.Region: founder :: Region (Maybe String)
+ NationStates.Region: gavote :: Region (Integer, Integer)
+ NationStates.Region: power :: Region String
+ NationStates.Region: scvote :: Region (Integer, Integer)
+ NationStates.Region: tags :: Region [String]
+ NationStates.Types: readWAStatus :: String -> Maybe Bool
+ NationStates.Types: showWAStatus :: Bool -> String
- NationStates.Core: Context :: Manager -> (forall a. IO a -> IO a) -> String -> Context
+ NationStates.Core: Context :: Manager -> (forall a. IO a -> IO a) -> Bool -> String -> Context
- NationStates.Core: expect :: String -> (String -> Maybe a) -> String -> a
+ NationStates.Core: expect :: String -> String -> Maybe a -> a
- NationStates.Region: delegate :: Region String
+ NationStates.Region: delegate :: Region (Maybe String)
Files
- LICENSE +202/−0
- NationStates.hs +17/−2
- NationStates/Core.hs +18/−13
- NationStates/Nation.hs +6/−10
- NationStates/RateLimit.hs +15/−8
- NationStates/Region.hs +91/−12
- NationStates/Types.hs +12/−0
- nationstates.cabal +2/−1
+ LICENSE view
@@ -0,0 +1,202 @@++ Apache License+ Version 2.0, January 2004+ http://www.apache.org/licenses/++ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION++ 1. Definitions.++ "License" shall mean the terms and conditions for use, reproduction,+ and distribution as defined by Sections 1 through 9 of this document.++ "Licensor" shall mean the copyright owner or entity authorized by+ the copyright owner that is granting the License.++ "Legal Entity" shall mean the union of the acting entity and all+ other entities that control, are controlled by, or are under common+ control with that entity. For the purposes of this definition,+ "control" means (i) the power, direct or indirect, to cause the+ direction or management of such entity, whether by contract or+ otherwise, or (ii) ownership of fifty percent (50%) or more of the+ outstanding shares, or (iii) beneficial ownership of such entity.++ "You" (or "Your") shall mean an individual or Legal Entity+ exercising permissions granted by this License.++ "Source" form shall mean the preferred form for making modifications,+ including but not limited to software source code, documentation+ source, and configuration files.++ "Object" form shall mean any form resulting from mechanical+ transformation or translation of a Source form, including but+ not limited to compiled object code, generated documentation,+ and conversions to other media types.++ "Work" shall mean the work of authorship, whether in Source or+ Object form, made available under the License, as indicated by a+ copyright notice that is included in or attached to the work+ (an example is provided in the Appendix below).++ "Derivative Works" shall mean any work, whether in Source or Object+ form, that is based on (or derived from) the Work and for which the+ editorial revisions, annotations, elaborations, or other modifications+ represent, as a whole, an original work of authorship. For the purposes+ of this License, Derivative Works shall not include works that remain+ separable from, or merely link (or bind by name) to the interfaces of,+ the Work and Derivative Works thereof.++ "Contribution" shall mean any work of authorship, including+ the original version of the Work and any modifications or additions+ to that Work or Derivative Works thereof, that is intentionally+ submitted to Licensor for inclusion in the Work by the copyright owner+ or by an individual or Legal Entity authorized to submit on behalf of+ the copyright owner. For the purposes of this definition, "submitted"+ means any form of electronic, verbal, or written communication sent+ to the Licensor or its representatives, including but not limited to+ communication on electronic mailing lists, source code control systems,+ and issue tracking systems that are managed by, or on behalf of, the+ Licensor for the purpose of discussing and improving the Work, but+ excluding communication that is conspicuously marked or otherwise+ designated in writing by the copyright owner as "Not a Contribution."++ "Contributor" shall mean Licensor and any individual or Legal Entity+ on behalf of whom a Contribution has been received by Licensor and+ subsequently incorporated within the Work.++ 2. Grant of Copyright License. Subject to the terms and conditions of+ this License, each Contributor hereby grants to You a perpetual,+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable+ copyright license to reproduce, prepare Derivative Works of,+ publicly display, publicly perform, sublicense, and distribute the+ Work and such Derivative Works in Source or Object form.++ 3. Grant of Patent License. Subject to the terms and conditions of+ this License, each Contributor hereby grants to You a perpetual,+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable+ (except as stated in this section) patent license to make, have made,+ use, offer to sell, sell, import, and otherwise transfer the Work,+ where such license applies only to those patent claims licensable+ by such Contributor that are necessarily infringed by their+ Contribution(s) alone or by combination of their Contribution(s)+ with the Work to which such Contribution(s) was submitted. If You+ institute patent litigation against any entity (including a+ cross-claim or counterclaim in a lawsuit) alleging that the Work+ or a Contribution incorporated within the Work constitutes direct+ or contributory patent infringement, then any patent licenses+ granted to You under this License for that Work shall terminate+ as of the date such litigation is filed.++ 4. Redistribution. You may reproduce and distribute copies of the+ Work or Derivative Works thereof in any medium, with or without+ modifications, and in Source or Object form, provided that You+ meet the following conditions:++ (a) You must give any other recipients of the Work or+ Derivative Works a copy of this License; and++ (b) You must cause any modified files to carry prominent notices+ stating that You changed the files; and++ (c) You must retain, in the Source form of any Derivative Works+ that You distribute, all copyright, patent, trademark, and+ attribution notices from the Source form of the Work,+ excluding those notices that do not pertain to any part of+ the Derivative Works; and++ (d) If the Work includes a "NOTICE" text file as part of its+ distribution, then any Derivative Works that You distribute must+ include a readable copy of the attribution notices contained+ within such NOTICE file, excluding those notices that do not+ pertain to any part of the Derivative Works, in at least one+ of the following places: within a NOTICE text file distributed+ as part of the Derivative Works; within the Source form or+ documentation, if provided along with the Derivative Works; or,+ within a display generated by the Derivative Works, if and+ wherever such third-party notices normally appear. The contents+ of the NOTICE file are for informational purposes only and+ do not modify the License. You may add Your own attribution+ notices within Derivative Works that You distribute, alongside+ or as an addendum to the NOTICE text from the Work, provided+ that such additional attribution notices cannot be construed+ as modifying the License.++ You may add Your own copyright statement to Your modifications and+ may provide additional or different license terms and conditions+ for use, reproduction, or distribution of Your modifications, or+ for any such Derivative Works as a whole, provided Your use,+ reproduction, and distribution of the Work otherwise complies with+ the conditions stated in this License.++ 5. Submission of Contributions. Unless You explicitly state otherwise,+ any Contribution intentionally submitted for inclusion in the Work+ by You to the Licensor shall be under the terms and conditions of+ this License, without any additional terms or conditions.+ Notwithstanding the above, nothing herein shall supersede or modify+ the terms of any separate license agreement you may have executed+ with Licensor regarding such Contributions.++ 6. Trademarks. This License does not grant permission to use the trade+ names, trademarks, service marks, or product names of the Licensor,+ except as required for reasonable and customary use in describing the+ origin of the Work and reproducing the content of the NOTICE file.++ 7. Disclaimer of Warranty. Unless required by applicable law or+ agreed to in writing, Licensor provides the Work (and each+ Contributor provides its Contributions) on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or+ implied, including, without limitation, any warranties or conditions+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A+ PARTICULAR PURPOSE. You are solely responsible for determining the+ appropriateness of using or redistributing the Work and assume any+ risks associated with Your exercise of permissions under this License.++ 8. Limitation of Liability. In no event and under no legal theory,+ whether in tort (including negligence), contract, or otherwise,+ unless required by applicable law (such as deliberate and grossly+ negligent acts) or agreed to in writing, shall any Contributor be+ liable to You for damages, including any direct, indirect, special,+ incidental, or consequential damages of any character arising as a+ result of this License or out of the use or inability to use the+ Work (including but not limited to damages for loss of goodwill,+ work stoppage, computer failure or malfunction, or any and all+ other commercial damages or losses), even if such Contributor+ has been advised of the possibility of such damages.++ 9. Accepting Warranty or Additional Liability. While redistributing+ the Work or Derivative Works thereof, You may choose to offer,+ and charge a fee for, acceptance of support, warranty, indemnity,+ or other liability obligations and/or rights consistent with this+ License. However, in accepting such obligations, You may act only+ on Your own behalf and on Your sole responsibility, not on behalf+ of any other Contributor, and only if You agree to indemnify,+ defend, and hold each Contributor harmless for any liability+ incurred by, or claims asserted against, such Contributor by reason+ of your accepting any such warranty or additional liability.++ END OF TERMS AND CONDITIONS++ APPENDIX: How to apply the Apache License to your work.++ To apply the Apache License to your work, attach the following+ boilerplate notice, with the fields enclosed by brackets "[]"+ replaced with your own identifying information. (Don't include+ the brackets!) The text should be enclosed in the appropriate+ comment syntax for the file format. We also recommend that a+ file or class name and description of purpose be included on the+ same "printed page" as the copyright notice for easier+ identification within third-party archives.++ Copyright [yyyy] [name of copyright owner]++ Licensed under the Apache License, Version 2.0 (the "License");+ you may not use this file except in compliance with the License.+ You may obtain a copy of the License at++ http://www.apache.org/licenses/LICENSE-2.0++ Unless required by applicable law or agreed to in writing, software+ distributed under the License is distributed on an "AS IS" BASIS,+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.+ See the License for the specific language governing permissions and+ limitations under the License.
NationStates.hs view
@@ -2,6 +2,7 @@ Context(), newContext,+ newContext', -- * Core types module NationStates.Types,@@ -22,11 +23,25 @@ :: String -- ^ User agent -> IO Context-newContext userAgent = do- man <- newManager tlsManagerSettings+newContext userAgent = newContext' userAgent False+++-- | Create a new 'Context', with extra options.+newContext'+ :: String+ -- ^ User agent+ -> Bool+ -- ^ Use HTTPS (experimental)+ -> IO Context+newContext' userAgent isSecure = do+ man <- newManager $+ if isSecure+ then tlsManagerSettings+ else defaultManagerSettings limit <- newRateLimit 0.6 return Context { contextManager = man, contextRateLimit = rateLimit limit,+ contextIsSecure = isSecure, contextUserAgent = userAgent }
NationStates/Core.hs view
@@ -25,7 +25,7 @@ wordsBy, readMaybe, expect,- expected,+ pureIf, -- * Data structures module NationStates.Types,@@ -132,12 +132,13 @@ <> BC.pack options, requestHeaders = ("User-Agent", BC.pack $ contextUserAgent c)- : requestHeaders initRequest+ : requestHeaders initRequest,+ secure = contextIsSecure c } (shards, options) = queryToUrl q initRequest :: Request-Just initRequest = parseUrl "https://www.nationstates.net/cgi-bin/api.cgi"+Just initRequest = parseUrl "http://www.nationstates.net/cgi-bin/api.cgi" -- | The version of the NationStates API used by this package.@@ -160,6 +161,7 @@ data Context = Context { contextManager :: Manager, contextRateLimit :: forall a. IO a -> IO a,+ contextIsSecure :: Bool, contextUserAgent :: String } @@ -211,17 +213,20 @@ -- -- If parsing fails, raise an 'error'. ----- >>> expect "integer" readMaybe "42" :: Integer+-- >>> (expect "integer" <*> readMaybe) "42" :: Integer -- 42 ----- >>> expect "integer" readMaybe "butts" :: Integer--- *** Exception: invalid integer: "butts"-expect :: String -> (String -> Maybe a) -> String -> a-expect want parse = fromMaybe <$> expected want <*> parse+-- >>> (expect "integer" <*> readMaybe) "butts" :: Integer+-- *** Exception: expected integer but got: butts+expect :: String -> String -> Maybe a -> a+expect want got = fromMaybe (error $ "expected " ++ want ++ " but got: " ++ got) --- | Raise an 'error'.+-- | Return the value only if the given predicate is true. ----- >>> expected "integer" "butts"--- *** Exception: invalid integer: "butts"-expected :: String -> String -> a-expected want s = error $ "invalid " ++ want ++ ": " ++ show s+-- >>> pureIf (> 0) 5 :: Maybe Integer+-- Just 5+--+-- >>> pureIf (> 0) (-2) :: Maybe Integer+-- Nothing+pureIf :: Alternative f => (a -> Bool) -> a -> f a+pureIf p x = if p x then pure x else empty
NationStates/Nation.hs view
@@ -149,18 +149,14 @@ -- -- > InoffensiveCentristDemocracy category :: Nation WACategory-category = Nation . fmap (expect "category" readWACategory) $+category = Nation . fmap (expect "category" <*> readWACategory) $ makeNS "category" "CATEGORY" -- | Whether the nation is in the World Assembly. -- -- > True wa :: Nation Bool-wa = Nation . fmap parse $ makeNS "wa" "UNSTATUS"- where- parse "WA Member" = True- parse "Non-member" = False- parse s = expected "WA status" s+wa = Nation . fmap (expect "WA status" <*> readWAStatus) $ makeNS "wa" "UNSTATUS" -- | List of endorsements received. --@@ -173,14 +169,14 @@ -- -- > Just True gavote :: Nation WAVote-gavote = Nation . fmap (expect "General Assembly vote" readWAVote) $+gavote = Nation . fmap (expect "General Assembly vote" <*> readWAVote) $ makeNS "gavote" "GAVOTE" -- | Security council vote. -- -- > Nothing scvote :: Nation WAVote-scvote = Nation . fmap (expect "Security Council vote" readWAVote) $+scvote = Nation . fmap (expect "Security Council vote" <*> readWAVote) $ makeNS "scvote" "SCVOTE" -- | Description of civil rights, economy, and political freedoms.@@ -206,14 +202,14 @@ -- -- > 25764 population :: Nation Integer-population = Nation . fmap (expect "population" readMaybe) $+population = Nation . fmap (expect "population" <*> readMaybe) $ makeNS "population" "POPULATION" -- | Income tax, percent. -- -- > 83.6 tax :: Nation Double-tax = Nation . fmap (expect "tax" readMaybe) $+tax = Nation . fmap (expect "tax" <*> readMaybe) $ makeNS "tax" "TAX" -- | National animal.
NationStates/RateLimit.hs view
@@ -4,6 +4,7 @@ RateLimit(), newRateLimit, rateLimit,+ setDelay, ) where @@ -13,8 +14,8 @@ data RateLimit = RateLimit {- rateLock :: !(MVar TimeSpec),- rateDelay :: !TimeSpec+ _rateLock :: !(MVar TimeSpec),+ _rateDelay :: !TimeSpec } @@ -27,17 +28,14 @@ -> IO RateLimit newRateLimit delay' = do lock <- newMVar $! negate delay- return RateLimit {- rateLock = lock,- rateDelay = delay- }+ return $ RateLimit lock delay where- delay = fromInteger . ceiling $ delay' * 1000 * 1000 * 1000+ delay = fromSeconds delay' -- | Run the given action, pausing as necessary to keep under the rate limit. rateLimit :: RateLimit -> IO a -> IO a-rateLimit RateLimit { rateLock = lock, rateDelay = delay } action =+rateLimit (RateLimit lock delay) action = mask $ \restore -> do prev <- takeMVar lock now <- getTime Monotonic@@ -47,3 +45,12 @@ threadDelay' :: TimeSpec -> IO () threadDelay' t = threadDelay . fromInteger $ timeSpecAsNanoSecs t `div` 1000+++-- | Create a new rate limiter with the same lock but a different delay.+setDelay :: Rational -> RateLimit -> RateLimit+setDelay delay' (RateLimit lock _) = RateLimit lock (fromSeconds delay')+++fromSeconds :: Rational -> TimeSpec+fromSeconds n = fromInteger . ceiling $ n * 1000 * 1000 * 1000
NationStates/Region.hs view
@@ -38,14 +38,14 @@ numnations, nations, delegate,--- delegatevote,--- gavote,--- scvote,--- founder,--- power,--- flag,--- embassies,--- tags,+ delegatevotes,+ gavote,+ scvote,+ founder,+ power,+ flag,+ embassies,+ tags, -- happenings, -- messages, -- history,@@ -55,6 +55,8 @@ import Control.Applicative+import Control.Monad+import Text.XML.Light import Prelude -- GHC 7.10 import NationStates.Core@@ -93,7 +95,7 @@ -- -- > 112 numnations :: Region Integer-numnations = Region . fmap (expect "nation count" readMaybe) $+numnations = Region . fmap (expect "nation count" <*> readMaybe) $ makeNS "numnations" "NUMNATIONS" -- | List of nations in the region.@@ -104,6 +106,83 @@ -- | Region delegate. ----- > "princess_luna"-delegate :: Region String-delegate = Region $ makeNS "delegate" "DELEGATE"+-- Returns @Nothing@ when the region has no delegate.+--+-- > Just "princess_luna"+delegate :: Region (Maybe String)+delegate = Region . fmap (pureIf (/= "0")) $ makeNS "delegate" "DELEGATE"++-- | The number of endorsements earned by the delegate.+--+-- Returns @0@ when the region has no delegate.+--+-- > 22+delegatevotes :: Region Integer+delegatevotes = Region . fmap (expect "delegate vote count" <*> readMaybe) $+ makeNS "delegatevotes" "DELEGATEVOTES"++-- | The number of votes for and against the current General Assembly+-- resolution.+--+-- > (28,11)+gavote :: Region (Integer, Integer)+gavote = Region $ makeNS' "gavote" Nothing [] parse+ where+ parse _ = expect "GA vote counts" <$> showElement <*>+ (grabVotes <=< findChild (unqual "GAVOTE"))++-- | The number of votes for and against the current Security Council+-- resolution.+--+-- > (20,34)+scvote :: Region (Integer, Integer)+scvote = Region $ makeNS' "scvote" Nothing [] parse+ where+ parse _ = expect "SC vote counts" <$> showElement <*>+ (grabVotes <=< findChild (unqual "SCVOTE"))++grabVotes :: Element -> Maybe (Integer, Integer)+grabVotes root = (,)+ <$> (readMaybe . strContent =<< findChild (unqual "FOR") root)+ <*> (readMaybe . strContent =<< findChild (unqual "AGAINST") root)++-- | Region founder.+--+-- Returns @Nothing@ when the region is founderless.+--+-- > Just "magical_equestria"+founder :: Region (Maybe String)+founder = Region . fmap (pureIf (/= "0")) $ makeNS "founder" "FOUNDER"++-- | Regional power.+--+-- > "High"+power :: Region String+power = Region $ makeNS "power" "POWER"++-- | Regional flag.+--+-- > Just "http://www.nationstates.net/images/flags/uploads/rflags/pony_lands__478033.png"+flag :: Region (Maybe String)+flag = Region . fmap (pureIf (/= "")) $ makeNS "flag" "FLAG"++-- | Region embassies.+--+-- > ["New Lunar Republic","Tareldanore"]+embassies :: Region [String]+embassies = Region $ makeNS' "embassies" Nothing [] parse+ where+ parse _ = expect "embassy names" <$> showElement <*>+ fmap (grabChildren "EMBASSY") . findChild (unqual "EMBASSIES")++-- | Region tags.+--+-- > ["Silly","Monarchist","Large"]+tags :: Region [String]+tags = Region $ makeNS' "tags" Nothing [] parse+ where+ parse _ = expect "region tags" <$> showElement <*>+ fmap (grabChildren "TAG") . findChild (unqual "TAGS")++grabChildren :: String -> Element -> [String]+grabChildren childName = map strContent . findChildren (unqual childName)
NationStates/Types.hs view
@@ -128,3 +128,15 @@ Nothing -> "UNDECIDED" Just True -> "FOR" Just False -> "AGAINST"+++readWAStatus :: String -> Maybe Bool+readWAStatus s = case s of+ "WA Member" -> Just True+ "Non-member" -> Just False+ _ -> Nothing++showWAStatus :: Bool -> String+showWAStatus v = case v of+ True -> "WA Member"+ False -> "Non-member"
nationstates.cabal view
@@ -1,5 +1,5 @@ name: nationstates-version: 0.3.0.1+version: 0.4.0.0 synopsis: NationStates API client description: NationStates API client@@ -9,6 +9,7 @@ maintainer: lambda.fairy@gmail.com copyright: 2015 Chris Wong license: Apache-2.0+license-file: LICENSE category: Network, Web build-type: Simple