314 Commits

Author SHA1 Message Date
swcs 0209d1a5b1 5.0 release 2019-04-05 14:26:19 +02:00
swcs aade66eef8 update dependencies 2019-04-05 14:12:31 +02:00
swcs 81394b9171 make Explore method internal for now 2019-04-05 14:09:05 +02:00
swcs c3a9f921eb add description to user account 2018-07-17 00:33:35 +02:00
swcs 9890a9c8b4 use a new PocketExploreItem model for the explore results 2018-07-16 01:34:15 +02:00
swcs bfc63bc55d fix some explore bugs 2018-07-15 11:50:23 +02:00
swcs 5d1f05f91d forgot new file -.- 2018-07-14 23:27:12 +02:00
swcs eb89784117 add Explore method 2018-07-14 23:26:57 +02:00
swcs ab3b532e30 merge httpclient+restparserclient; add RequestAsString method 2018-07-14 22:10:44 +02:00
swcs 960fd56d6c oops 2018-07-14 15:10:47 +02:00
swcs 0dff3dc3de delete tag action 2018-07-14 14:10:03 +02:00
swcs a0fce1a5fb RenameTag does not accept an item Id 2018-07-14 13:59:50 +02:00
swcs 4260a3f10d Merge branch 'master' of https://github.com/ceee/PocketSharp 2018-07-14 13:58:13 +02:00
swcs 284b7d16c1 hm ooook 2018-07-14 13:57:39 +02:00
swcs 6bd23cb4fe trending methods do not require a GUID 2018-07-12 11:34:07 +02:00
swcs 000c821661 fix json converter bug 2018-07-12 11:30:20 +02:00
swcs 281034a16d add article suggestions 2018-07-03 12:20:16 +02:00
swcs 8248f90b5b remove JSON prop from PocketItem and introduce an AfterRequest action with the passed raw response 2018-07-02 16:41:18 +02:00
swcs 7edc82d726 complete new requests for trending 2018-07-02 16:25:09 +02:00
swcs 00b44e917e basic implementation of trending articles & topics 2018-07-02 15:56:57 +02:00
swcs e6e242f7c1 get more detailled user data 2018-04-24 13:18:15 +02:00
swcs 1c2c85ad05 method to get a new GUID from Pocket 2018-04-09 12:34:52 +02:00
swcs ed087ffdf5 update tests 2018-04-09 12:18:45 +02:00
swcs e3b571d98b update readme to reflect changet to .NET Standard 2018-04-05 16:11:40 +02:00
swcs 2db1dadc38 add nuspec file 2018-04-05 16:09:08 +02:00
swcs f9e68da5ef migrate to .NET Standard 2.0 and remove old examples 2018-04-05 16:07:35 +02:00
swcs 18202a16de reconfigure projects and update deps 2018-04-05 15:58:02 +02:00
swcs 5e04409310 remove .nuget files 2018-04-05 15:43:19 +02:00
swcs aa51acc5de remove .vs files 2018-04-05 15:41:12 +02:00
swcs 48e75d21c0 add pocket video type 2016-02-27 18:51:59 +01:00
swcs bc2b17cc20 Merge pull request #34 from fujiy/FixEquals
Fix PocketItem.Equals(object obj). #32
2016-02-21 23:30:35 +01:00
swcs d227cc535f add failing equality test case (see issue #32) 2016-02-21 23:28:57 +01:00
swcs 49436e0aaa add equality check unit test 2016-02-21 13:44:00 +01:00
swcs c52bffcd95 remove INPC and add item ID to images + videos 2016-02-21 13:43:41 +01:00
Felipe Fujiy Pessoto a1a56668a0 Fix PocketItem.Equals(object obj). #32 2016-02-20 23:36:46 -03:00
swcs 4998db08a6 update changelog/readme 2015-12-05 17:37:21 +01:00
swcs ded764c9cd forget fodyweavers file 2015-12-05 17:30:28 +01:00
swcs 80f8a2231e update packages + remove decompression from HttpClient (2.2) 2015-12-05 17:30:18 +01:00
swcs b3a794436a update license 2015-01-01 19:33:50 +01:00
swcs 9c597db11c add gitattributes 2014-12-04 18:11:04 +01:00
swcs b16339db98 Update README.md 2014-11-17 18:00:22 +01:00
swcs 459d034aa2 merge to master 2014-08-28 14:22:57 +02:00
swcs b8d211e151 update changelog 2014-08-28 14:15:16 +02:00
swcs c31b771cdb fix datetime conversion issue 2014-08-28 14:14:40 +02:00
swcs fc7d2a7eaf assembly version 2014-07-27 15:20:25 +02:00
swcs 77af7cf20e Revert "sliiim"
This reverts commit 816e06269f.
2014-07-27 15:19:14 +02:00
swcs b284cfc7cc assembly version 2014-07-27 15:18:57 +02:00
swcs 51aa7c9fdf assembly version 2014-07-27 15:17:58 +02:00
swcs 451190daee LOL 2014-07-27 15:17:57 +02:00
swcs 9af20d05dc fixes #28
Fix StackOverflow bug in PocketItem equality overload
2014-07-27 15:17:56 +02:00
swcs f62820e069 convert all datetimes to UTC+0 2014-07-27 15:17:55 +02:00
swcs 816e06269f sliiim 2014-07-27 15:17:54 +02:00
swcs e0f96a092c assembly version 2014-07-27 15:16:39 +02:00
swcs 0301bbaf10 LOL 2014-07-27 13:03:33 +02:00
swcs 5266f220e9 fixes #28
Fix StackOverflow bug in PocketItem equality overload
2014-07-27 13:01:53 +02:00
swcs c83971b4cc convert all datetimes to UTC+0 2014-07-21 16:37:30 +02:00
swcs 1567709ace Merge remote-tracking branch 'origin/master' into simple 2014-07-21 16:24:30 +02:00
swcs 342f16fb8e convert timestamps to UTC+-0 (critical fix) 2014-07-21 16:23:59 +02:00
swcs 423be2df5f Merge remote-tracking branch 'origin/master' into simple 2014-07-18 11:58:08 +02:00
swcs 1605740107 fixes #27
Implement WebAuthenticationBroker-view toggle
see: http://getpocket.com/developer/docs/getstarted/windows8
2014-07-18 11:54:47 +02:00
swcs b7b92d87ed sliiim 2014-07-02 15:31:38 +02:00
swcs 01c36a047a flag for caching last HTTP response 2014-07-01 17:10:14 +02:00
swcs 140e645e86 bugfix 2014-06-25 14:41:42 +02:00
swcs 97919cdd18 supi dupi force param 2014-06-18 18:58:43 +02:00
swcs 761d670c65 update docs and changelog 2014-06-17 11:11:41 +02:00
swcs 1ca93bf07f update version 2014-06-17 10:46:00 +02:00
swcs 556e8004f3 fix Action parameter "url", so batch adding is working now 2014-06-17 10:45:24 +02:00
swcs 7cad855f9c return correct response status for "Send" 2014-06-17 10:14:26 +02:00
swcs 366908a070 fix json converter bug 2014-05-27 00:38:48 +02:00
swcs d141c7b255 fix deserializer bug 2014-05-11 23:07:49 +02:00
swcs 8531d20162 make PocketClient disposable 2014-05-11 22:59:06 +02:00
swcs 4f42ed719a separate HttpClient for parser API 2014-05-11 22:54:44 +02:00
swcs b46cc56362 implement ParserAPI func 2014-05-11 22:50:06 +02:00
swcs 500bd1c65d itemID prop for Tags; PocketArticle model 2014-05-11 22:26:08 +02:00
swcs a207ca7ca4 ConvertJsonToList 2014-05-03 18:54:19 +02:00
swcs 07c9f06f75 add IComparable and tostring/gethashcode to PocketItem 2014-05-02 17:59:26 +02:00
swcs a1ff132ba9 change assemblyversion 2014-05-01 18:14:17 +02:00
swcs 82896d6fb4 prevent creation of Lists and use IEnumerable where possible 2014-05-01 17:56:18 +02:00
swcs 36683c7402 add tags as string 2014-04-20 12:36:20 +02:00
swcs 4e5a8ab096 remove internal search and use official by Pocket 2014-04-17 10:26:59 +02:00
swcs 47baa0fd97 update docs 2014-04-05 11:44:03 +02:00
swcs ec25258de9 assembly version 2014-04-03 12:00:31 +02:00
swcs 6999185c96 remove unnecessary action in tests 2014-04-03 11:50:12 +02:00
swcs 7669d8880e first running version of new package 2014-04-03 11:45:00 +02:00
swcs 38b6a62686 add new test 2014-04-02 16:57:28 +02:00
swcs 0f7f626d15 update readme 2014-03-13 21:28:22 +01:00
swcs 81f099d419 update version 2014-03-13 21:25:04 +01:00
Stephen Erstad ec006b298d Added test for Json property for PocketItem
Tested that the Json property is set on the retrieved PocketItems and
that they represent a JSON object
2014-03-04 22:35:50 -06:00
Stephen Erstad 4fa0ee29fe Raw JSON on PocketItem Model
Implementation of setting the raw JSON representation of a PocketItem to
the PocketSharp model
2014-03-04 22:12:08 -06:00
swcs c21abd5f21 try to normalize URIs retrieved in video array; update tests; 2014-02-23 21:03:55 +01:00
swcs facba2894d update packages solution-wide 2014-02-21 23:50:24 +01:00
swcs 585c203f9a fix PocketAction conversion exception when no ID is given; fixes #20 2014-02-17 23:30:15 +01:00
swcs 07357b9327 add wp7 project 2014-02-11 21:55:22 +01:00
swcs 75e6a23905 update dependencies 2014-02-10 22:48:35 +01:00
swcs 44c4bc11db update nuspec file 2014-02-07 14:31:09 +01:00
swcs d3d8937c60 update changelog 2014-02-07 14:24:25 +01:00
swcs b2113eb065 allow toggle for disabling mobile param 2014-02-07 14:22:52 +01:00
swcs 13664c4201 fixes #18 - new registration via redirect 2014-02-07 14:12:09 +01:00
swcs 13c98e2d59 fixes #17 2014-02-07 14:10:12 +01:00
swcs 7b14044c53 password has to be at least 6 chars long 2014-02-06 13:28:28 +01:00
swcs 0be1efb2df start new exceptions 2014-01-18 21:36:01 +01:00
swcs 13e029a98a use FullTitle if no title given 2013-12-28 14:03:58 +01:00
swcs c6cf19ba4d bump version 2013-12-27 21:45:09 +01:00
swcs 50c15ad6ce remove exception debug code 2013-12-27 21:34:53 +01:00
swcs 670fecb1e0 respect given_url if no resolved_url is given 2013-12-27 21:34:22 +01:00
swcs 85c4ca2c65 update readme 2013-12-19 11:27:11 +01:00
swcs 0183a727ce update readme 2013-12-19 11:25:51 +01:00
swcs 25bb5028a5 Remove PocketSharp.Reader => moved to ReadSharp
See https://github.com/ceee/ReadSharp if you want to use ReadSharp
2013-12-19 11:24:22 +01:00
swcs 3201160d66 move image extractor into NReadability 2013-12-16 22:08:23 +01:00
swcs 996755ef50 extract images from article in Reader 2013-12-16 21:42:11 +01:00
swcs 6e6cef138a update tests; remove PocketArticle from PocketSharp 2013-12-16 21:11:04 +01:00
swcs bcb833ad0d remove PocketSharp dependency from Reader; move PocketArticle into Reader project; 2013-12-16 21:07:34 +01:00
swcs e33ec074fe PreRequest in IPocketClient 2013-12-15 12:49:45 +01:00
swcs a2e68af4dc update readme 2013-12-15 11:50:37 +01:00
swcs ab5361c370 bump version 2013-12-15 11:42:53 +01:00
swcs 4718faf76a HasImage and HasVideo has to be nullable for unresolved items 2013-12-15 11:10:56 +01:00
swcs f6e7594233 respect normal_uri, if submitted; PocketItem.ID as string 2013-12-15 11:00:00 +01:00
swcs c39f8ec7f0 make PocketBoolean internal 2013-12-07 20:42:12 +01:00
ScottIsAFool c1981bbb24 Fixed the HasImage and HasVideo properties 2013-12-07 17:30:53 +00:00
ScottIsAFool 425faf7a90 Added IsVideo, IsImage and ResolvedId props 2013-12-07 16:47:18 +00:00
swcs a1fae6b3ce fix PocketAction conversion 2013-12-04 22:14:29 +01:00
swcs 84981a5de3 add TweetID for Send actions 2013-12-04 20:31:23 +01:00
swcs 5480cebe49 publicly cache last response headers and data 2013-12-03 22:28:22 +01:00
swcs 3fca5a059b update tests 2013-12-02 22:51:24 +01:00
swcs 5854c0c04f rebuild issue #13 in WP8 sample (via Button click) 2013-11-23 22:45:03 +01:00
swcs e2ca21b3be add tests for the since parameter 2013-11-21 21:45:49 +01:00
swcs 178920008b fixes #12
ObjectToArrayConverter returns null when the TokenType is Null.
2013-11-20 20:45:55 +01:00
swcs 67c48839d9 fixes #12
Update ObjectToArrayConverter to return null when JObject cannot be
created
2013-11-19 19:30:59 +01:00
swcs e2bf62e506 Fix accessCode in examples 2013-11-18 23:12:30 +01:00
swcs 31c69fb12b merge 2013-11-18 22:52:39 +01:00
ScottIsAFool 42693a967e Added HttpClientHandler and timeout to ctors 2013-11-18 18:05:02 +00:00
swcs 29f57085aa add IE11 user agent for PocketReader; update to RC3 2013-11-16 15:34:36 +01:00
swcs 5ba027bafc test SendActions 2013-11-16 15:27:54 +01:00
swcs 33e6e9b02d add SendActions method 2013-11-16 15:09:21 +01:00
swcs 44376c0852 IPocketReader interface 2013-11-15 14:30:20 +01:00
swcs a643e5c556 update readme 2013-11-15 14:23:21 +01:00
swcs b2ce585966 bodyOnly and noHeadline options for PocketReader.Read 2013-11-15 14:20:56 +01:00
swcs 6f6d054044 update readme 2013-11-15 13:52:22 +01:00
swcs ff4fae1d35 add second NuGet package for PocketReader; allow user agent in PocketReader constructor 2013-11-15 13:43:27 +01:00
swcs f5c8d45013 move PocketReader into own project 2013-11-15 13:28:16 +01:00
swcs ad40a25b0b make user agent a public property in PocketReader 2013-11-14 20:02:56 +01:00
swcs eb3ac1f152 Update README.md 2013-11-14 19:53:56 +01:00
swcs 3bff4d823f update dependencies 2013-11-14 19:33:55 +01:00
swcs 0427399746 add stress tests 2013-11-13 20:23:02 +01:00
swcs ee989fc019 custom UriConverter to check for invalid URIs 2013-11-12 22:08:02 +01:00
swcs 2a9c30a69b add PreRequest action for all requests 2013-11-11 22:00:41 +01:00
swcs 95d7a5d993 make CancellationToken an optional parameter 2013-11-08 09:31:35 +01:00
swcs bf5d8a50ce cancellationToken for ALL methods - completed; remove obsolete methods in preparation for v3 2013-11-08 01:44:32 +01:00
swcs 10e9575303 cancellationToken for Modify methods 2013-11-08 01:33:32 +01:00
swcs feff91ffd8 cancellationToken for Get methods 2013-11-08 01:24:58 +01:00
swcs 50d896c670 cancellationToken for Add and Account methods 2013-11-08 01:12:34 +01:00
swcs f0ffeb5a68 Merge branch 'stress' 2013-11-08 00:56:02 +01:00
swcs 6b3819b87b require Uri to be absolute in Add method 2013-11-08 00:55:44 +01:00
swcs 8df2836563 add CancellationToken to PocketClient; methods later; 2013-11-06 20:47:53 +01:00
swcs d856e75e76 make test playlists working for XUnit update 2013-11-05 23:31:19 +01:00
swcs 82c9ecd6b5 remove Utilities.DictionaryToList - not needed 2013-11-05 23:17:45 +01:00
swcs 7147d8022e update docs 2013-11-05 23:13:14 +01:00
swcs b1888ac20e Merge branch 'master' of github.com:ceee/PocketSharp 2013-11-04 22:46:47 +01:00
swcs cb8d1d9d43 make Test playlists; refactored PocketItem inline lists (setters are working now); 2013-11-04 22:46:30 +01:00
swcs 2b932d4c07 Update README.md 2013-11-04 08:26:23 +01:00
swcs bc30ea613a Merge branch 'ScottIsAFool-master' 2013-11-03 20:24:45 +01:00
swcs b1b145204e add regions 2013-11-03 20:24:32 +01:00
swcs 01be59b347 add FillAccount method for stress tests 2013-11-03 20:18:57 +01:00
ScottIsAFool af3e2b400b Added IPocketClient interface
Any future public methods that get added in any partial files just need
adding to the interface file too.
2013-11-03 18:07:26 +00:00
swcs 396cf69a40 convert nulls for bool and int in JSOn reader; update stress tests 2013-11-03 18:27:35 +01:00
swcs 088f6a4e0e add stress test wrapper and URL csv's 2013-11-02 10:32:38 +01:00
swcs 25a25472b3 add test for too short passwords in registration 2013-11-02 10:18:33 +01:00
swcs b5b7638ea7 bump version 2013-11-01 16:41:14 +01:00
swcs 6616c2e223 Merge branch 'master' of github.com:ceee/PocketSharp 2013-11-01 16:38:47 +01:00
swcs 145b4456ea remove website 2013-11-01 16:38:24 +01:00
swcs 8dedf11d24 require password in RegisterAccount to be at least 3 chars long 2013-11-01 16:35:16 +01:00
swcs 9caeefbe3c Update README.md 2013-10-29 09:02:15 +01:00
swcs de143d4605 Update README.md 2013-10-29 09:01:06 +01:00
swcs e63dfb60d0 update changelog 2013-10-27 13:35:44 +01:00
swcs 9b19739fc9 update nuspec 2013-10-27 13:32:33 +01:00
swcs ff8bbf17d3 fix serious issue in retrieving <body> in BodyOnly serializer for NReadability 2013-10-27 13:27:45 +01:00
swcs da892067ad resolve conflicts; make GetAccessCode obsolete 2013-10-26 13:16:35 +02:00
swcs 3992a988fc Merge branch 'master' of github.com:ScottIsAFool/PocketSharp into ScottIsAFool-master 2013-10-26 13:05:14 +02:00
ScottIsAFool 2a98cfb0e4 Added new method to return username too 2013-10-25 15:49:47 +01:00
swcs 3057612872 update contributors 2013-10-25 15:22:13 +02:00
swcs 56180b5829 update contributors 2013-10-25 15:21:26 +02:00
swcs 2a08adef45 update version 2013-10-25 15:19:42 +02:00
swcs abfb9f6d78 remove unused using 2013-10-25 15:05:47 +02:00
swcs a1f6637e9d retrieve API usage limits; rename Statistics() to GetUserStatistics(); 2013-10-25 00:52:29 +02:00
swcs 8bce874504 Merge branch 'ScottIsAFool-master' 2013-10-25 00:05:46 +02:00
swcs 50ee8905c5 add PORTABLE constant to SgmlReader 2013-10-25 00:05:42 +02:00
swcs 4d2650072f Merge branch 'master' of github.com:ScottIsAFool/PocketSharp into ScottIsAFool-master 2013-10-24 22:40:18 +02:00
ScottIsAFool 65e31ac2e2 Missed files for propertychanged 2013-10-24 21:37:52 +01:00
swcs 456c4f17f2 Merge branch 'master' of github.com:ScottIsAFool/PocketSharp into ScottIsAFool-master 2013-10-24 21:55:40 +02:00
ScottIsAFool ee1e32b9ab Added Fody/PropertyChanged 2013-10-24 18:44:22 +01:00
swcs 9d677eea5a Merge pull request #7 from ScottIsAFool/master
Made CallbackUri public
2013-10-24 00:44:11 -07:00
ScottIsAFool 64098518fa Made CallbackUri public 2013-10-24 06:52:09 +01:00
swcs cc6aab227d Update README.md 2013-10-23 20:27:19 +02:00
swcs 543b3e8191 Update README.md 2013-10-23 20:26:40 +02:00
swcs 2186561fd8 update readme 2013-10-22 21:46:55 +02:00
swcs 8650883975 Merge branch 'master' of github.com:ceee/PocketSharp 2013-10-22 21:46:35 +02:00
swcs 6ede86c367 allow PocketSharp to be used in .NET 4.0 2013-10-22 21:46:24 +02:00
swcs d373bdd9bf Update README.md 2013-10-21 22:12:53 +02:00
swcs b4ae55d8ab update assembly information 2013-10-20 22:20:37 +02:00
swcs aae43cf00d bump version; update docs 2013-10-19 16:40:14 +02:00
swcs a0e8022f1d Merge branch 'master' of github.com:ceee/PocketSharp 2013-10-19 16:35:02 +02:00
swcs 4119dec95d move utilites; catch HttpRequestException; Read Article from URI 2013-10-19 16:30:01 +02:00
swcs cf2d929d3a Update README.md 2013-10-18 19:28:32 +02:00
swcs e772b8df9e update some spelling mistakes 2013-10-17 15:43:23 +02:00
swcs d9c4b4c51f update documentation and website 2013-10-17 15:34:05 +02:00
swcs 4222e873c7 Merge branch 'master' of github.com:ceee/PocketSharp 2013-10-17 14:51:36 +02:00
swcs 6e02a797b5 remove MaxAutomaticRedirections as not supported on all platforms 2013-10-17 14:51:11 +02:00
swcs 329e16ebd5 update portableports assembly names 2013-10-17 14:33:34 +02:00
swcs 52bac490b4 update portable ports names 2013-10-17 14:28:56 +02:00
swcs 1d500d0d4b update Reader comments and bump assembly version 2013-10-17 14:24:07 +02:00
swcs a731a744bc add Reader Tests; add PocketArticle response object 2013-10-17 14:17:48 +02:00
swcs 352af4f736 fix NReadability CSS issue 2013-10-17 13:28:17 +02:00
swcs 1c74d6ebf4 move Ports into internal namespace; Update JSON.NET 2013-10-17 12:49:52 +02:00
swcs c4d6ea45ea Update README.md 2013-10-16 20:37:19 +02:00
swcs 649ded199d extend NReadability to allow output of body only 2013-10-15 22:21:17 +02:00
swcs ef10ca23a4 rewrite doctype to HTML5 2013-10-15 22:01:22 +02:00
swcs 9c0cf6cb3a allow better customization of nreadability output from PocketSharp assembly 2013-10-15 21:52:33 +02:00
swcs dbb495ce76 Merge branch 'master' of github.com:ceee/PocketSharp 2013-10-15 21:09:38 +02:00
swcs 4e6fdc33d6 update SgmlReader Port to include HTML DTD 2013-10-15 21:09:22 +02:00
swcs 9cc1f231d9 Update README.md 2013-10-15 19:47:42 +02:00
swcs 4136e4cc4b move PocketReader into PocketSharp project 2013-10-14 21:27:45 +02:00
swcs 7aee628000 add reader project (work in progress) 2013-10-13 20:55:28 +02:00
swcs ff3c6a6826 remove Reader for now ... 2013-10-08 22:25:11 +02:00
swcs 2ec09a4a67 Merge pull request #5 from ceee/reader
converted SgmlReader & NReadability to PCL; start reader project
2013-10-01 14:30:30 -07:00
swcs 266f494db6 converted SgmlReader & NReadability to PCL; start reader project 2013-10-01 23:26:28 +02:00
swcs c2b6eab709 update version 2013-09-30 23:30:16 +02:00
swcs f19fdd227b fix RetrieveFilter.All; improve search speed 2013-09-30 23:24:18 +02:00
swcs f231231f4e fix readme formatting issue 2013-09-29 23:28:06 +02:00
swcs a1a5076895 update website 2013-09-29 23:24:07 +02:00
swcs 11769d65fd update readme 2013-09-29 23:22:03 +02:00
swcs 2aa7e3de90 update assembly version 2013-09-28 19:22:24 +02:00
swcs 7564855597 update comments 2013-09-27 09:34:55 +02:00
swcs 3564bc8273 allow dashes in username 2013-09-27 01:08:13 +02:00
swcs 2154740550 add account registration 2013-09-27 01:03:02 +02:00
swcs 966a35e2c6 add statistics API 2013-09-27 00:12:02 +02:00
swcs 90199ebe1f add Whats Next section to readme 2013-09-22 18:26:12 +02:00
swcs 208b157465 update website 2013-09-21 21:11:52 +02:00
swcs 54a82ea215 remove retrieve file 2013-09-21 21:06:38 +02:00
swcs 5136fe0ac4 update Microsoft.Net.HTTP package; update version and docs 2013-09-21 21:06:18 +02:00
swcs 74063723df ability to retrieve all tags 2013-09-21 20:48:50 +02:00
swcs cb6fc4e113 rename Retrieve => Get; add overload for Get for filters 2013-09-21 20:20:50 +02:00
swcs f8eaf47f80 update method documentation 2013-09-21 00:06:56 +02:00
swcs a8cc4c14de invalid retrieval Tests 2013-09-20 23:20:44 +02:00
swcs d7e324129c update version 2013-09-19 18:24:56 +02:00
swcs 1912563cc3 RemoveTag method; fix tag conversion; add modify tests 2013-09-19 18:08:41 +02:00
swcs 64c74b11d7 add item retrieval by ID 2013-09-19 12:13:07 +02:00
swcs e9699caf4e remove actionresults from response due to inconsistent behaviour 2013-09-19 11:47:57 +02:00
swcs 76af7fec0e add modification tests 2013-09-19 11:47:23 +02:00
swcs 4e40aaa0dc update readme 2013-09-18 21:19:38 +02:00
swcs 242428f94c bump version 2013-09-18 21:17:56 +02:00
swcs d009afd033 correct serialization of DateTime and Boolean values 2013-09-18 21:14:07 +02:00
swcs de1e4efc70 update retrieve tests 2013-09-18 21:01:51 +02:00
swcs e198ecdd6b update docs 2013-09-17 23:28:28 +02:00
swcs fb92cb19c8 update retrieve methods - work with named parameters 2013-09-17 23:08:15 +02:00
swcs 79184d194e fix tag parameter conversion; lead image generation; add complex item test; 2013-09-17 22:48:35 +02:00
swcs 9d0fb6484f fix modification requests 2013-09-17 21:43:31 +02:00
swcs e45414bd51 remove depr. classes 2013-09-16 23:34:26 +02:00
swcs e522c8e30a simplify parameter creation; fix several deserialization issues 2013-09-16 23:34:13 +02:00
swcs 6cf9892f78 disposable base for tests; classes for other tests 2013-09-15 21:52:28 +02:00
swcs d3c40c1a76 add tests for Retrieve methods 2013-09-15 21:44:09 +02:00
swcs c01098af04 update website and docs 2013-09-15 15:46:13 +02:00
swcs 813b1ab5b0 update assembly info; create new nuspec file 2013-09-15 15:19:33 +02:00
swcs 91b18e1eab add silverlight example 2013-09-15 12:38:41 +02:00
swcs b6bd02a5cc add WP8 example 2013-09-14 19:33:38 +02:00
swcs 25a3f4ef2f add WPF example 2013-09-14 15:47:51 +02:00
swcs 6114c3af9a exception handling / validation for requests and parsing 2013-09-14 15:12:28 +02:00
swcs a507cf6d0a add custom deserializers; update data-attributes for json.net 2013-09-14 13:40:20 +02:00
swcs 25321ee107 update tests 2013-09-12 11:40:25 +02:00
swcs f9268ea6be start async + pcl implementation 2013-09-12 11:39:48 +02:00
swcs f2134b8c80 prepare Models for PCL 2013-09-11 22:31:32 +02:00
swcs c7565d7684 make components async (won't work yet) 2013-09-11 22:31:01 +02:00
swcs a4666f843c update readme 2013-09-09 20:51:50 +02:00
swcs c545152957 update readme 2013-09-06 11:36:41 +02:00
swcs 490b005002 update readme 2013-09-05 21:58:13 +02:00
swcs a07a509042 update history listing for website 2013-08-19 09:06:54 +02:00
swcs 5c7f398b51 bump version; 2013-08-16 14:02:12 +02:00
swcs 969648a395 tag modification didn't pass through due to incorrect array serialization 2013-08-16 13:45:18 +02:00
swcs c3a8e11cdf deserialization function for Uri throwed exceptions with empty strings and invalid values; 2013-08-16 09:39:35 +02:00
swcs 1a52ac7ec0 add details (tags,...) to Retrieve method called with RetrieveFilter; 2013-08-16 09:34:42 +02:00
swcs ed57295a43 update ServiceStack.Text dependency; 2013-08-16 09:23:13 +02:00
swcs f7a035b4f6 Update README.md 2013-07-29 22:22:05 +02:00
swcs 99396b9a0a update readme; 2013-07-29 22:18:41 +02:00
swcs b6741cfec6 website: add entypo; 2013-07-29 22:16:18 +02:00
swcs 127fe9577a website: remove touch-action on body; 2013-07-14 20:22:01 +02:00
swcs f04a8a409a update analytics for website; 2013-07-13 14:56:38 +02:00
swcs caa1fc1c3f remove unnecessary files .. 2013-07-13 14:37:39 +02:00
swcs b28728a0ad add nuspec file 2013-07-13 14:22:47 +02:00
swcs e40d8e60f8 update website .. 2013-07-13 14:21:53 +02:00
swcs 1d39a62cea optimize for small screens; 2013-07-13 13:19:34 +02:00
swcs b88908cd7c navigation by hash; 2013-07-13 12:51:49 +02:00
swcs 840fb611e1 fix w3c warnings; 2013-07-13 12:39:29 +02:00
swcs d1cafe65af implement navigation; 2013-07-13 12:22:56 +02:00
swcs 5a6ffcdd09 minor article style changes (font-sizes,-weights,colors); 2013-07-13 00:12:29 +02:00
swcs 207b13c4da sidebar fixed; syntax highlighting for code; social links; 2013-07-13 00:04:35 +02:00
swcs b7c84f7711 update enum namings to match naming conventions; 2013-07-12 00:15:43 +02:00
swcs c7778c1002 remove retired files; 2013-07-09 23:13:51 +02:00
swcs ca1fb8c42e update readme 2013-07-09 23:13:06 +02:00
swcs 5930ebcf9b update navgiation; 2013-07-09 23:00:09 +02:00
swcs dd001fd0f6 add navigation; nuget code; 2013-07-09 22:57:45 +02:00
swcs e647ab33b8 add main layout; 2013-07-09 22:17:55 +02:00
swcs e20609045d remove Gemfile.lock 2013-07-09 21:26:32 +02:00
swcs b895880c69 start Website for PocketSharp 2013-07-09 21:25:10 +02:00
swcs 1c6246774d wtf; branches mixed up óÒ 2013-07-08 22:38:38 +02:00
swcs df07b9ce81 Merge branch 'gh-pages' of github.com:ceee/PocketSharp 2013-07-08 22:33:48 +02:00
swcs 960a5d9ddd Create gh-pages branch via GitHub 2013-07-08 13:34:06 -07:00
swcs c36995ea2e update readme; 2013-07-07 22:33:09 +02:00
swcs 9d213d309f fix callbackUri escaping in authentication process; 2013-07-07 22:31:29 +02:00
swcs 01ab0f8bb8 move Auth Models into Response folder; remove unused usings; 2013-07-04 23:47:39 +02:00
swcs 7f38e346a2 add Tests project; 2013-07-03 23:19:47 +02:00
swcs 422ec73374 update documentation; 2013-07-02 21:15:57 +02:00
swcs 5382dd3326 update documentation; 2013-07-02 21:05:43 +02:00
swcs 761a33ebbe update documentation; 2013-07-02 20:59:06 +02:00
swcs edccc8891c update documentation; 2013-07-02 20:58:13 +02:00
swcs 719a53a9c5 fix callback encoding; callback Uri -> string; 2013-07-02 20:43:38 +02:00
98 changed files with 133162 additions and 1290 deletions
+2 -8
View File
@@ -1,21 +1,15 @@
; This file is for unifying the coding style for different editors and IDEs
; editorconfig.org
; defaults by Tobias Klika
; 2013
root = true
; default settings for all files
[*]
end_of_line = crlf ; this is git standard, so it won't convert it anymore
end_of_line = crlf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false
trim_trailing_whitespace = false
+23
View File
@@ -0,0 +1,23 @@
# Auto detect text files and perform LF normalization
* text
# Don't check these into the repo as LF to work around TeamCity bug
*.xml -text
*.targets -text
# Custom for Visual Studio
*.cs diff=csharp
*.sln merge=union
*.csproj merge=union
*.vbproj merge=union
*.fsproj merge=union
*.dbproj merge=union
# Denote all files that are truly binary and should not be modified.
*.dll binary
*.exe binary
*.png binary
*.ico binary
*.snk binary
*.pdb binary
*.svg binary
+13 -6
View File
@@ -1,9 +1,3 @@
# =========================
# Project
# =========================
PocketSharp.Console/
## Ignore Visual Studio temporary files, build results, and files generated by popular Visual Studio add-ons.
# User-specific files
@@ -105,6 +99,7 @@ publish/
# NuGet Packages Directory
## TODO: If you have NuGet Package Restore enabled, uncomment the next line
packages/
*.nupkg
# Windows Azure Build Output
csx
@@ -130,6 +125,8 @@ node_modules
tmp
_old
_tmp
Gemfile.lock
WebWorkbench.mswwsettings
# RIA/Silverlight projects
Generated_Code/
@@ -145,6 +142,9 @@ UpgradeLog*.htm
App_Data/*.mdf
App_Data/*.ldf
.vs
.nuget
# =========================
# Windows detritus
# =========================
@@ -162,3 +162,10 @@ $RECYCLE.BIN/
# Mac crap
.DS_Store
# =========================
# Project
# =========================
PocketSharp.Console/
!PocketSharp.Website/Release/
BIN
View File
Binary file not shown.
+8 -5
View File
@@ -18,9 +18,9 @@
<ItemGroup Condition=" '$(PackageSources)' == '' ">
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
<!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
<!--
<PackageSource Include="https://nuget.org/api/v2/" />
<PackageSource Include="https://www.nuget.org/api/v2/" />
<PackageSource Include="https://my-nuget-source/nuget/" />
-->
</ItemGroup>
@@ -50,9 +50,12 @@
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
<!-- Commands -->
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir "$(SolutionDir) " </RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties Configuration=$(Configuration) $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
<!-- We need to ensure packages are restored prior to assembly resolve -->
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
@@ -118,7 +121,7 @@
Log.LogMessage("Downloading latest version of NuGet.exe...");
WebClient webClient = new WebClient();
webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
return true;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

+167
View File
@@ -0,0 +1,167 @@
<<<<<<< HEAD
=======
### 4.2.0 (2015-12-05)
- Update packages
- Remove decompression from HttpClient so it works with UWP
### 4.1.6 (2014-08-28)
- Fix DateTime conversion issue (from local to UTC)
>>>>>>> simple
### 4.1.5 (2014-07-27)
- Fix StackOverflow bug in PocketItem equality overload (fixes #28)
### 4.1.4 (2014-07-18)
- Implement WebAuthenticationBroker-view toggle
### 4.1.3 (2014-06-25)
- Only dispose response if available
### 4.1.2 (2014-06-18)
- Add force param to login+registration
### 4.1.1 (2014-06-17)
- Fix batch adding bug
### 4.1.0 (2014-06-16)
- Include access to the Article View API
### 4.0.0 (2014-04-03)
- Support for Universal apps (dropped SL and WP7 support)
### 3.2.0 (2014-03-13)
- add raw JSON to each PocketItem (PR #22)
### 3.1.1 (2014-02-23)
- fix SendActions when sending _add_ requests (fixes #20)
- try to normalize URIs retrieved in video array
### 3.1.0 (2014-02-07)
- Use FullTitle if no other title props are available
- Default mobile authentication screen with toggle for desktop (fixes #17)
- Use new registration endpoint
### 3.0.2 (2013-12-27)
- assign given_url to `Uri` when item couldn't be resolved by Pocket
### 3.0.1 (2013-12-15)
- added `PreRequest` to interface
### 3.0.0 (2013-12-15)
- `cancellationToken` support for all methods
- Toggle inclusion of title in PocketArticle.Content
- Make setters for inline objects in PocketItem (images, videos, ...)
- IPocketClient interface
- PreRequest callback allows injection of `Action<string>` before every request
- `lastHeaders` and `lastRequestData` in PocketClient for better debugging
- Submit multiple actions in one request with `SendActions`
- New `IsVideo`, `IsImage` and `ResolvedId` as new properties in PocketItem
- Split PocketReader into own NuGet package
- A lot of bugfixes
### 2.2.2 (2013-11-01)
- Password validation in RegisterAccount
### 2.2.1 (2013-10-27)
- Fix NReadability parsing issue
### 2.2.0 (2013-10-26)
- Made `GetAccessCode` obsolete
- Return username after authentication with `GetUser`
### 2.1.0 (2013-10-25)
- Rename `Statistics()` to `GetUserStatistics()`
- Made `CallbackUri` public
- Added Fody/PropertyChanged
- Method `GetUsageLimits()` to retrieve API usage limits
- Add PORTABLE constant to SgmlReader
### 2.0.1 (2013-10-19)
- Catch HttpRequestExceptions and provide as InnerException for PocketException
- Read Article from URI (method overload)
### 2.0.0 (2013-10-17)
- Add Reader API _(does not use the official Article View API, which is private. The PocketReader is based on a custom PCL port of NReadability and SgmlReader)_
### 1.5.1 (2013-09-30)
- `RetrieveFilter.All` didn't work
- improve search speed
### 1.5.0 (2013-09-28)
- add statistics API
- add registration API
### 1.4.0 (2013-09-21)
- rename `Retrieve` to `Get`
- update IntelliSense documentation
- add `GetTags` method
### 1.3.0 (2013-09-19)
- get Item by ID
- tag modification bugfixes
### 1.2.1 (2013-09-18)
- correct parameter conversion for DateTime and Boolean
### 1.2.0 (2013-09-17)
- simplified retrieve methods
### 1.1.0 (2013-09-17)
- fix modification requests
### 1.0.0 (2013-09-15)
- convert to PCL
- implement async
### 0.3.2 (2013-08-16)
- tag modification fixed
- full retrieval of items for Retrieve method
### 0.3.1 (2013-07-07)
- authentication fixes
### 0.3.0 (2013-07-02)
- update authentication process
### 0.2.0 (2013-06-27)
- add, modify item
- modify tags
### 0.1.0 (2013-06-26)
- authentication
- retrieve functionality
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (c) 2013 cee, Tobias Klika
Copyright (c) 2015 cee, Tobias Klika
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
@@ -0,0 +1,8 @@
<Application
x:Class="PocketSharp.UWP.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PocketSharp.UWP"
RequestedTheme="Light">
</Application>
@@ -0,0 +1,87 @@
using System;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
namespace PocketSharp.UWP
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
if (rootFrame.Content == null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation
// parameter
rootFrame.Navigate(typeof(MainPage), e.Arguments);
}
// Ensure the current window is active
Window.Current.Activate();
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<Weavers>
<PropertyChanged />
</Weavers>
@@ -0,0 +1,38 @@
<Page
x:Class="PocketSharp.UWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:PocketSharp.UWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<Button Click="Button_Click">Load Data</Button>
</StackPanel>
<!--ContentPanel contains LongListSelector and LongListSelector ItemTemplate. Place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListView ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
<TextBlock Text="{Binding Uri}" TextWrapping="Wrap" Margin="12,-6,12,0" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Grid>
</Grid>
</Page>
@@ -0,0 +1,58 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Windows.UI.Xaml.Controls;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
namespace PocketSharp.UWP
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public ObservableCollection<PocketItem> Items { get; set; }
public MainPage()
{
InitializeComponent();
Items = new ObservableCollection<PocketItem>();
}
public async Task LoadData()
{
// !! please don't misuse this account !!
PocketClient client = new PocketClient(
consumerKey: "15396-f6f92101d72c8e270a6c9bb3",
callbackUri: "http://frontendplay.com",
accessCode: "80acf6c5-c198-03c0-b94c-e74402"
);
List<PocketSharp.Models.PocketItem> items = null;
try
{
items = (await client.Get()).ToList();
foreach (var item in items)
{
Items.Add(item);
}
}
catch (PocketException ex)
{
Debug.WriteLine(ex.Message);
}
}
private async void Button_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
await LoadData();
}
}
}
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity
Name="17071047-817c-42b4-837d-8530fd36e521"
Publisher="CN=tobi"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="17071047-817c-42b4-837d-8530fd36e521" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>PocketSharp.UWP</DisplayName>
<PublisherDisplayName>tobi</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate"/>
</Resources>
<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="PocketSharp.UWP.App">
<uap:VisualElements
DisplayName="PocketSharp.UWP"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="PocketSharp.UWP"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClient" />
</Capabilities>
</Package>
@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
<ProjectGuid>{5CBB92EC-C1A2-4108-9A23-3B73DD138953}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PocketSharp.UWP</RootNamespace>
<AssemblyName>PocketSharp.UWP</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.16299.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.16299.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PackageCertificateKeyFile>PocketSharp.UWP_TemporaryKey.pfx</PackageCertificateKeyFile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>
<Compile Include="MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="PocketSharp.UWP_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<Content Include="FodyWeavers.xml">
<SubType>Designer</SubType>
</Content>
<Content Include="Properties\Default.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainPage.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\PocketSharp\PocketSharp.csproj">
<Project>{0e22926c-7244-4a17-923c-84b46f5149c0}</Project>
<Name>PocketSharp</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">O:\PocketSharp\PocketSharp.Examples\PocketSharp.UWP\project.lock.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\tobi\.nuget\packages\;C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">ProjectJson</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.5.0</NuGetToolVersion>
</PropertyGroup>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)runtime.win10-x86.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.props" Condition="Exists('$(NuGetPackageRoot)runtime.win10-x86.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.props')" />
<Import Project="$(NuGetPackageRoot)runtime.win10-x64.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.props" Condition="Exists('$(NuGetPackageRoot)runtime.win10-x64.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.props')" />
<Import Project="$(NuGetPackageRoot)runtime.win10-arm.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.props" Condition="Exists('$(NuGetPackageRoot)runtime.win10-arm.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.uwpcoreruntimesdk\2.1.2\build\Microsoft.Net.UWPCoreRuntimeSdk.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.uwpcoreruntimesdk\2.1.2\build\Microsoft.Net.UWPCoreRuntimeSdk.props')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x86\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x86.props" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x86\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x86.props')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x64\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x64.props" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x64\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x64.props')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-arm\2.0.0\build\Microsoft.Net.Native.SharedLibrary-arm.props" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-arm\2.0.0\build\Microsoft.Net.Native.SharedLibrary-arm.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.compiler\2.0.3\build\Microsoft.Net.Native.Compiler.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.compiler\2.0.3\build\Microsoft.Net.Native.Compiler.props')" />
</ImportGroup>
</Project>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)runtime.win10-x86.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.targets" Condition="Exists('$(NuGetPackageRoot)runtime.win10-x86.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x86.Microsoft.Net.UWPCoreRuntimeSdk.targets')" />
<Import Project="$(NuGetPackageRoot)runtime.win10-x64.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.targets" Condition="Exists('$(NuGetPackageRoot)runtime.win10-x64.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-x64.Microsoft.Net.UWPCoreRuntimeSdk.targets')" />
<Import Project="$(NuGetPackageRoot)runtime.win10-arm.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.targets" Condition="Exists('$(NuGetPackageRoot)runtime.win10-arm.microsoft.net.uwpcoreruntimesdk\2.1.2\build\runtime.win10-arm.Microsoft.Net.UWPCoreRuntimeSdk.targets')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\netstandard.library\2.0.1\build\netstandard2.0\NETStandard.Library.targets" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\netstandard.library\2.0.1\build\netstandard2.0\NETStandard.Library.targets')" />
<Import Project="$(NuGetPackageRoot)fody\3.0.0\build\Fody.targets" Condition="Exists('$(NuGetPackageRoot)fody\3.0.0\build\Fody.targets')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x86\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x86.targets" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x86\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x86.targets')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x64\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x64.targets" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-x64\2.0.0\build\Microsoft.Net.Native.SharedLibrary-x64.targets')" />
<Import Project="C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-arm\2.0.0\build\Microsoft.Net.Native.SharedLibrary-arm.targets" Condition="Exists('C:\Program Files (x86)\Microsoft SDKs\NuGetPackagesFallback\microsoft.net.native.sharedlibrary-arm\2.0.0\build\Microsoft.Net.Native.SharedLibrary-arm.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.compiler\2.0.3\build\Microsoft.Net.Native.Compiler.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.compiler\2.0.3\build\Microsoft.Net.Native.Compiler.targets')" />
</ImportGroup>
</Project>
@@ -5,23 +5,15 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("PocketSharp")]
[assembly: AssemblyTitle("PocketSharp.UWP")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PocketSharp")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[assembly: AssemblyProduct("PocketSharp.UWP")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("fe3e33ad-074a-44fa-99a5-a8bf13837301")]
// Version information for an assembly consists of the following four values:
//
// Major Version
@@ -34,3 +26,4 @@ using System.Runtime.InteropServices;
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
@@ -0,0 +1,31 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>
@@ -0,0 +1,18 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "6.0.8",
"Newtonsoft.Json": "11.0.2",
"PropertyChanged.Fody": "2.4.0"
},
"frameworks": {
"uap10.0.15063": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}
File diff suppressed because it is too large Load Diff
+32
View File
@@ -0,0 +1,32 @@
using PocketSharp.Models;
using System;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class AccountTests : TestsBase
{
public AccountTests() : base() { }
[Fact]
public async Task IsAuthenticationSuccessful()
{
string requestCode = await client.GetRequestCode();
PocketUser user = await client.GetUser(requestCode);
}
[Fact]
public async Task IsRegistrationURLSuccessfullyCreated()
{
string requestCode = await client.GetRequestCode();
Uri uri = client.GenerateRegistrationUri(requestCode);
Assert.Contains(requestCode, uri.OriginalString);
Assert.Contains("force=signup", uri.OriginalString);
}
}
}
+125
View File
@@ -0,0 +1,125 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using System.Linq;
namespace PocketSharp.Tests
{
public class AddTests : TestsBase
{
public AddTests() : base() { }
[Fact]
public async Task AddSimpleItemWithUriOnly()
{
var uri = new Uri("http://frontendplay.com");
PocketItem item = await client.Add(uri);
Assert.Equal<Uri>(uri, item.Uri);
itemsToDelete.Add(item.ID);
}
[Fact]
public async Task ItemWithInstableImagesIsAdded()
{
var uri = new Uri("http://www.valoronline.com.br");
PocketItem item = await client.Add(uri);
Assert.NotNull(item);
itemsToDelete.Add(item.ID);
}
[Fact]
public async Task AddComplexItem()
{
PocketItem item = await client.Add(
uri: new Uri("http://frontendplay.com"),
tags: new string[] { "blog", "frontend", "cee" },
title: "ignored title",
tweetID: "380051788172632065"
);
List<PocketItem> items = (await client.Get()).ToList();
PocketItem itemDesired = null;
items.ForEach(itm =>
{
if (itm.ID == item.ID)
{
itemDesired = itm;
}
});
Assert.NotNull(itemDesired);
Assert.Equal(itemDesired.ID, item.ID);
Assert.Equal(3, itemDesired.Tags.Count());
itemsToDelete.Add(item.ID);
}
[Fact]
public async Task ItemViaActionsIsAdded()
{
List<PocketAction> actions = new List<PocketAction>();
actions.Add(new PocketAction()
{
Uri = new Uri("http://frontendplay.com/story/4015/string-indexer-for-text-resources-in-nancy"),
Action = "add",
Time = DateTime.Now
});
bool success = await client.SendActions(actions);
Assert.True(success);
IEnumerable<PocketItem> items = await client.Search("in nancy");
Assert.NotNull(items);
Assert.True(items.Count() > 0);
itemsToDelete.Add(items.First().ID);
}
[Fact]
public async Task ItemsViaActionsIsAdded()
{
List<PocketAction> actions = new List<PocketAction>();
actions.Add(new PocketAction()
{
Uri = new Uri("http://frontendplay.com/story/4015/string-indexer-for-text-resources-in-nancy"),
Action = "add",
Time = DateTime.Now
});
actions.Add(new PocketAction()
{
Uri = new Uri("http://frontendplay.com/story/4013/build-a-custom-razor-viewbase-in-nancy"),
Action = "add",
Time = DateTime.Now
});
bool success = await client.SendActions(actions);
Assert.True(success);
IEnumerable<PocketItem> items = await client.Search("in nancy");
Assert.NotNull(items);
Assert.True(items.Count() == 2);
itemsToDelete.AddRange(items.Select(item => item.ID));
}
}
}
+25
View File
@@ -0,0 +1,25 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using System.Linq;
namespace PocketSharp.Tests
{
public class ExploreTests : TestsBase
{
public ExploreTests() : base()
{
}
//[Fact]
//public async Task CheckPreRequestAction()
//{
// var results = await client.Explore(".net");
// Assert.NotEmpty(results);
//}
}
}
+317
View File
@@ -0,0 +1,317 @@
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using System.Linq;
namespace PocketSharp.Tests
{
public class GetTests : TestsBase
{
public GetTests() : base() { }
[Fact]
public async Task AreItemsRetrieved()
{
List<PocketItem> items = (await client.Get()).ToList();
Assert.True(items.Count > 0);
}
[Fact]
public async Task IsItemRetrievedById()
{
List<PocketItem> items = (await client.Get()).ToList();
PocketItem item = items[0];
PocketItem itemDuplicate = await client.Get(item.ID);
Assert.True(item.ID == itemDuplicate.ID);
Assert.True(item.Uri == itemDuplicate.Uri);
}
[Fact]
public async Task AreSuggestionsRetrieved()
{
var articles = await client.GetTrendingArticles();
string itemId = articles.First().ID;
List<PocketItem> suggestions = (await client.GetSuggestions(itemId)).ToList();
Assert.True(suggestions.Count > 0);
}
// [Fact]
// public async Task IsItemJsonPopulated()
// {
// List<PocketItem> items = (await client.Get()).ToList();
// string schemaJson = @"{
// 'description': 'PocketItem',
// 'type': 'object'
// }";
// JsonSchema schema = JsonSchema.Parse(schemaJson);
// foreach (var pocketItem in items)
// {
// Assert.True(!string.IsNullOrWhiteSpace(pocketItem.Json));
// var jObject = JObject.Parse(pocketItem.Json);
// Assert.True(jObject.IsValid(schema));
// }
// }
[Fact]
public async Task AreFilteredItemsRetrieved()
{
IEnumerable<PocketItem> items = await client.Get(RetrieveFilter.Favorite);
Assert.True(items.Count() > 0);
}
[Fact]
public async Task RetrieveWithMultipleFilters()
{
IEnumerable<PocketItem> items = await client.Get(
state: State.unread,
tag: "pocket",
sort: Sort.title,
since: new DateTime(2010, 12, 10),
count: 2
);
Assert.InRange<int>(items.Count(), 0, 2);
}
[Fact]
public async Task ItemContainsUri()
{
IEnumerable<PocketItem> items = await client.Get(count: 1);
Assert.True(1 == items.Count());
Assert.StartsWith("http", items.First().Uri.OriginalString);
}
[Fact]
public async Task InvalidRetrievalReturnsNoResults()
{
IEnumerable<PocketItem> items = await client.Get(
favorite: true,
search: "xoiu987a#;"
);
Assert.False(items.Count() > 0);
PocketItem item = await client.Get("99999999");
Assert.Null(item);
items = await client.Get(RetrieveFilter.Video);
Assert.False(items.Count() > 0);
}
[Fact]
public async Task SearchReturnsResult()
{
IEnumerable<PocketItem> items = await client.Search("pocket");
Assert.True(items.Count() > 0);
Assert.Contains("pocket", items.First().FullTitle.ToLower());
}
[Fact]
public async Task InvalidSearchReturnsNoResult()
{
IEnumerable<PocketItem> items = await client.Search("adsüasd-opiu2;.398dfyx");
Assert.False(items.Count() > 0);
}
[Fact]
public async Task RetrieveTagsReturnsResult()
{
IEnumerable<PocketTag> items = await client.GetTags();
Assert.True(items.Count() > 0);
}
[Fact]
public async Task SearchByTagsReturnsResult()
{
IEnumerable<PocketItem> items = await client.SearchByTag("pocket");
Assert.True(items.Count() == 1);
bool found = false;
items.First().Tags.ToList().ForEach(tag =>
{
if (tag.Name.Contains("pocket"))
{
found = true;
}
});
Assert.True(found);
}
[Fact]
public async Task InvalidSearchByTagsReturnsNoResult()
{
IEnumerable<PocketItem> items = await client.SearchByTag("adsüasd-opiu2;.398dfyx");
Assert.False(items.Count() > 0);
}
[Fact]
public async Task AreStatisticsRetrieved()
{
PocketStatistics statistics = await client.GetUserStatistics();
Assert.True(statistics.CountAll > 0);
}
[Fact]
public async Task AreLimitsRetrieved()
{
PocketLimits limits = await client.GetUsageLimits();
Assert.True(limits.RateLimitForConsumerKey > 9999);
}
[Fact]
public async Task IsNewPocketItemListGeneratorWorking()
{
IEnumerable<PocketItem> items = await client.Get(count: 1, tag: "pocket");
PocketItem item = items.First();
Assert.True(item.Tags.ToList().Find(i => i.Name == "pocket") != null);
}
[Fact]
public async Task IsSinceParameterWorkingOnAddTags()
{
DateTime since = DateTime.Now;
IEnumerable<PocketItem> items = await client.Get(state: State.all);
PocketItem itemToModify = items.First();
Assert.True(items.Count() >= 3);
items = await client.Get(state: State.all, since: since);
Assert.True(items == null || items.Count() == 0);
await client.AddTags(itemToModify, new string[] { "pocketsharp" });
items = await client.Get(state: State.all, since: since);
Assert.True(items.Count() > 0);
await client.RemoveTags(itemToModify, new string[] { "pocketsharp" });
}
[Fact]
public async Task IsSinceParameterWorkingOnFavoriteAndArchiveModification()
{
DateTime since = DateTime.Now;//1409221736
IEnumerable<PocketItem> items = await client.Get(state: State.all);
PocketItem itemToModify = items.First();
Assert.True(items.Count() >= 3);
items = await client.Get(state: State.all, since: since);
Assert.True(items == null || items.Count() == 0);
await client.Favorite(itemToModify);
items = await client.Get(state: State.all, since: since);
Assert.True(items.Count() > 0);
await client.Unfavorite(itemToModify);
since = DateTime.Now;
await client.Archive(itemToModify);
items = await client.Get(state: State.all, since: since);
Assert.True(items.Count() > 0);
await client.Unarchive(itemToModify);
}
[Fact]
public async Task IsUTCSinceParameterWorking()
{
DateTime since = DateTime.UtcNow;
IEnumerable<PocketItem> items = await client.Get(state: State.all);
PocketItem itemToModify = items.First();
items = await client.Get(state: State.all, since: since);
Assert.True(items == null || items.Count() == 0);
await client.Favorite(itemToModify);
items = await client.Get(state: State.all, since: since);
Assert.True(items.Count() > 0);
await client.Unfavorite(itemToModify);
}
[Fact]
public async Task IsSinceParameterWorkingOnAddAndDelete()
{
DateTime since = DateTime.UtcNow;
PocketItem item = await client.Add(new Uri("http://frontendplay.com"));
IEnumerable<PocketItem> items = await client.Get(state: State.all, since: since);
since = DateTime.UtcNow;
await client.Delete(item);
items = await client.Get(state: State.all, since: since);
Assert.True(items.Count() == 1 && items.First().IsDeleted);
}
[Fact]
public async Task AreUncachedItemsProperlyResolved()
{
PocketItem item = await client.Add(new Uri("http://de.ign.com/m/feature/21608/die-20-besten-kurzfilme-des-jahres-2013?bust=1"));
IEnumerable<PocketItem> items = await client.Get(state: State.all);
Assert.NotNull(item.Uri);
Assert.NotNull(items.First().Uri);
Assert.Equal(item.Uri, items.First().Uri);
itemsToDelete.Add(item.ID);
}
}
}
+56
View File
@@ -0,0 +1,56 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using System.Linq;
namespace PocketSharp.Tests
{
public class MiscTests : TestsBase
{
private int Incrementor = 0;
public MiscTests() : base()
{
client.PreRequest = method => Incrementor++;
}
[Fact]
public async Task CheckPreRequestAction()
{
IEnumerable<PocketItem> items = await client.Get(count: 1);
PocketItem item = items.First();
await client.Favorite(item);
await client.Unfavorite(item);
Assert.True(Incrementor >= 3);
}
[Fact]
public void ItemEqualityChecks()
{
PocketItem item1 = new PocketItem() { ID = "12872" };
PocketItem item2 = new PocketItem() { ID = "12872" };
PocketItem item3 = new PocketItem() { ID = "12800" };
PocketArticle article = new PocketArticle();
Assert.True(item1.Equals(item2));
Assert.False(item1.Equals(item3));
Assert.False(item1.Equals(null));
Assert.True(item1 == item2);
Assert.False(item1 == item3);
Assert.False(item1 == null);
Assert.False(item1 != item2);
Assert.True(item1 != item3);
Assert.True(item1 != null);
Assert.False(item1.Equals(article));
Assert.True(new List<PocketItem>() { item1 }.IndexOf(item2) > -1);
}
}
}
+102
View File
@@ -0,0 +1,102 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class ModifyTagsTests : TestsBase
{
public ModifyTagsTests() : base() { }
[Fact]
public async Task AreTagsAddedAndDeletedToAnItem()
{
PocketItem item = await Setup();
Assert.True(await client.AddTags(item, new string[] { "test_tag", "test_tag2" }));
item = await GetItemById(item.ID);
Assert.True(item.Tags.Count() >= 2);
Assert.NotNull(item.Tags.Single<PocketTag>(tag => tag.Name == "test_tag"));
Assert.NotNull(item.Tags.Single<PocketTag>(tag => tag.Name == "test_tag2"));
Assert.True(await client.RemoveTags(item, new string[] { "test_tag", "test_tag2" }));
item = await GetItemById(item.ID);
Assert.Null(item.Tags.SingleOrDefault<PocketTag>(tag => tag.Name == "test_tag"));
Assert.Null(item.Tags.SingleOrDefault<PocketTag>(tag => tag.Name == "test_tag2"));
}
[Fact]
public async Task AreAllTagsRemovedFromItem()
{
PocketItem item = await Setup();
Assert.True(await client.AddTags(item, new string[] { "test_tag", "test_tag2" }));
item = await GetItemById(item.ID);
Assert.True(item.Tags.Count() >= 2);
Assert.True(await client.RemoveTags(item));
item = await GetItemById(item.ID);
Assert.Null(item.Tags);
}
[Fact]
public async Task AreTagsReplaced()
{
PocketItem item = await Setup();
Assert.True(await client.ReplaceTags(item.ID, new string[] { "test_tag", "test_tag2" }));
item = await GetItemById(item.ID);
Assert.Equal(2, item.Tags.Count());
Assert.NotNull(item.Tags.SingleOrDefault<PocketTag>(tag => tag.Name == "test_tag"));
Assert.NotNull(item.Tags.SingleOrDefault<PocketTag>(tag => tag.Name == "test_tag2"));
}
private async Task<PocketItem> Setup()
{
PocketItem item = await client.Add(
uri: new Uri("https://github.com"),
tags: new string[] { "github", "code", "social" }
);
itemsToDelete.Add(item.ID);
return await GetItemById(item.ID);
}
private async Task<PocketItem> GetItemById(string id, bool archive = false)
{
List<PocketItem> items = (await client.Get(state: archive ? State.archive : State.unread)).ToList();
PocketItem itemDesired = null;
items.ForEach(itm =>
{
if (itm.ID == id)
{
itemDesired = itm;
}
});
return itemDesired;
}
}
}
+154
View File
@@ -0,0 +1,154 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class ModifyTests : TestsBase
{
public ModifyTests() : base() { }
[Fact]
public async Task IsAnItemArchivedAndUnarchived()
{
PocketItem item = await Setup();
Assert.True(await client.Archive(item));
item = await GetItemById(item.ID, true);
Assert.True(item.IsArchive);
Assert.True(await client.Unarchive(item));
item = await GetItemById(item.ID);
Assert.False(item.IsArchive);
}
[Fact]
public async Task IsAnItemFavoritedAndUnfavorited()
{
PocketItem item = await Setup();
Assert.True(await client.Favorite(item));
item = await GetItemById(item.ID);
Assert.True(item.IsFavorite);
Assert.True(await client.Unfavorite(item));
item = await GetItemById(item.ID);
Assert.False(item.IsFavorite);
}
[Fact]
public async Task IsAnItemDeleted()
{
PocketItem item = await Setup();
Assert.True(await client.Delete(item));
item = await GetItemById(item.ID);
Assert.Null(item);
}
[Fact]
public async Task AreMultipleActionsSent()
{
PocketItem item = await Setup();
bool success = await client.SendActions(new List<PocketAction>()
{
new PocketAction() { Action = "favorite", ID = item.ID },
new PocketAction() { Action = "tags_add", ID = item.ID, Tags = new string[] { "new_tag", "another_tag" } },
new PocketAction() { Action = "archive", ID = item.ID }
});
Assert.True(success);
item = await client.Get(item.ID);
Assert.True(item.IsFavorite);
Assert.True(item.IsArchive);
Assert.NotNull(item.Tags.Single<PocketTag>(tag => tag.Name == "new_tag"));
Assert.NotNull(item.Tags.Single<PocketTag>(tag => tag.Name == "another_tag"));
}
[Fact]
public async Task AreMultipleAddActionsSent()
{
PocketItem item = await Setup();
bool success = await client.SendActions(new List<PocketAction>()
{
new PocketAction() { Action = "add", Uri = new Uri("http://msdn.microsoft.com/en-us/library/windows/apps/jj841126.aspx") },
new PocketAction() { Action = "add", Uri = new Uri("http://pokiapp.com/changelog") }
});
Assert.True(success);
}
[Fact]
public async Task AreMultipleActionsOnOneItemPerformed()
{
PocketItem item = await Setup();
bool success = await client.SendActions(new List<PocketAction>()
{
new PocketAction() { Action = "unarchive", ID = item.ID },
new PocketAction() { Action = "archive", ID = item.ID },
new PocketAction() { Action = "unfavorite", ID = item.ID }
});
Assert.True(success);
item = await client.Get(item.ID);
Assert.False(item.IsFavorite);
Assert.True(item.IsArchive);
}
private async Task<PocketItem> Setup()
{
PocketItem item = await client.Add(
uri: new Uri("https://github.com"),
tags: new string[] { "github", "code", "social" }
);
itemsToDelete.Add(item.ID);
return await GetItemById(item.ID);
}
private async Task<PocketItem> GetItemById(string id, bool archive = false)
{
List<PocketItem> items = (await client.Get(state: archive ? State.archive : State.unread)).ToList();
PocketItem itemDesired = null;
items.ForEach(itm =>
{
if (itm.ID == id)
{
itemDesired = itm;
}
});
return itemDesired;
}
}
}
@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<None Remove="url-10000.csv" />
<None Remove="url-100000.csv" />
</ItemGroup>
<ItemGroup>
<Content Include="url-10000.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="url-100000.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PocketSharp\PocketSharp.csproj" />
</ItemGroup>
</Project>
+131
View File
@@ -0,0 +1,131 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class StressTests : TestsBase
{
private static IEnumerable<string> urls;
private static string[] tags = new string[] { "css", "js", "csharp", "windows", "microsoft" };
public StressTests()
: base()
{
// !! please don't misuse this account !!
client = new PocketClient(
consumerKey: "20000-786d0bc8c39294e9829111d6",
callbackUri: "http://frontendplay.com",
accessCode: "9b8ecb6b-7801-1a5c-7b39-2ba05b"
);
urls = File.ReadAllLines("../../url-100000.csv").Select(item => item.Split(',')[1]);
}
[Fact]
public async Task Are100ItemsRetrievedProperly()
{
IEnumerable<PocketItem> items = await client.Get(count: 100, state: State.all);
Assert.True(items.Count() == 100);
}
[Fact]
public async Task Are1000ItemsRetrievedProperly()
{
IEnumerable<PocketItem> items = await client.Get(count: 1000, state: State.all);
Assert.True(items.Count() == 1000);
}
[Fact]
public async Task Are2500ItemsRetrievedProperly()
{
IEnumerable<PocketItem> items = await client.Get(count: 2500, state: State.all);
Assert.True(items.Count() == 2500);
}
[Fact]
public async Task Are5000ItemsRetrievedProperly()
{
IEnumerable<PocketItem> items = await client.Get(count: 5000, state: State.all);
Assert.True(items.Count() == 5000);
}
[Fact]
public async Task IsSearchSuccessfullyOnBigList()
{
IEnumerable<PocketItem> items = await client.Get(search: "google");
Assert.True(items.Count() > 0);
Assert.True(items.First().Title.ToLower().Contains("google") || items.First().Uri.ToString().ToLower().Contains("google"));
}
[Fact]
public async Task IsTagSearchSuccessfullyOnBigList()
{
IEnumerable<PocketItem> items = await client.SearchByTag(tags[0]);
Assert.True(items.Count() > 1);
bool found = false;
items.First().Tags.ToList().ForEach(tag =>
{
if (tag.Name.Contains(tags[0]))
{
found = true;
}
});
Assert.True(found);
}
[Fact]
public async Task RetrieveTagsReturnsResultOnBigList()
{
List<PocketTag> items = (await client.GetTags()).ToList();
items.ForEach(tag =>
{
Assert.Contains(tag.Name, tags);
});
Assert.Equal(items.Count, tags.Length);
}
private async Task FillAccount(int offset, int count)
{
int r;
int r2;
string[] tag;
Random rnd = new Random();
var items = urls.Skip(offset).Take(count)
.Select((value, idx) => new { Value = value, Index = idx })
.GroupBy(item => item.Index / 100, item => item.Value)
.Cast<IEnumerable<string>>();
foreach (IEnumerable<string> urlGroup in items)
{
await Task.WhenAll(urlGroup.Select(url =>
{
r = rnd.Next(tags.Length);
r2 = rnd.Next(tags.Length);
tag = new string[] { tags[r], tags[r2] };
return client.Add(new Uri("http://" + url), tag);
}));
}
}
//[Fact]
//public async Task Fillll()
//{
// await FillAccount(11000, 89999);
//}
}
}
+53
View File
@@ -0,0 +1,53 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class TestsBase : IDisposable
{
protected PocketClient client;
protected List<string> itemsToDelete = new List<string>();
// setup
public TestsBase()
{
// !! please don't misuse this account !!
client = new PocketClient(
consumerKey: "15396-f6f92101d72c8e270a6c9bb3",
callbackUri: "http://frontendplay.com",
accessCode: "80acf6c5-c198-03c0-b94c-e74402"
);
}
// teardown
public void Dispose()
{
itemsToDelete.ForEach(async id =>
{
await client.Delete(id);
});
}
// async throws
public static async Task ThrowsAsync<TException>(Func<Task> func)
{
var expected = typeof(TException);
Type actual = null;
try
{
await func();
}
catch (Exception e)
{
actual = e.GetType();
}
Assert.Equal(expected, actual);
}
}
}
+25
View File
@@ -0,0 +1,25 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class TrendingTests : TestsBase
{
[Fact]
public async Task AreTrendingArticlesReturned()
{
var articles = await client.GetTrendingArticles();
Assert.NotEmpty(articles);
}
[Fact]
public async Task AreTrendingTopicsReturned()
{
var topics = await client.GetTrendingTopics();
Assert.NotEmpty(topics);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.29.0" newVersion="4.2.29.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+82 -12
View File
@@ -1,26 +1,96 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketSharp", "PocketSharp\PocketSharp.csproj", "{1A291041-ADD8-467C-A6E4-0ACA26328CDF}"
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PocketSharp.Examples", "PocketSharp.Examples", "{AFD4E3F1-B23C-4924-BA5B-D917FBADB8FA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketSharp.Console", "PocketSharp.Console\PocketSharp.Console.csproj", "{81B7D587-A189-4785-BDFE-CA8A9ABA0760}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{19DD45B5-B849-49E7-89D6-16C89B9B96C7}"
ProjectSection(SolutionItems) = preProject
.nuget\NuGet.Config = .nuget\NuGet.Config
.nuget\NuGet.exe = .nuget\NuGet.exe
.nuget\NuGet.targets = .nuget\NuGet.targets
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketSharp.UWP", "PocketSharp.Examples\PocketSharp.UWP\PocketSharp.UWP.csproj", "{5CBB92EC-C1A2-4108-9A23-3B73DD138953}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PocketSharp", "PocketSharp\PocketSharp.csproj", "{0E22926C-7244-4A17-923C-84B46F5149C0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PocketSharp.Tests", "PocketSharp.Tests\PocketSharp.Tests.csproj", "{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1A291041-ADD8-467C-A6E4-0ACA26328CDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1A291041-ADD8-467C-A6E4-0ACA26328CDF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1A291041-ADD8-467C-A6E4-0ACA26328CDF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A291041-ADD8-467C-A6E4-0ACA26328CDF}.Release|Any CPU.Build.0 = Release|Any CPU
{81B7D587-A189-4785-BDFE-CA8A9ABA0760}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{81B7D587-A189-4785-BDFE-CA8A9ABA0760}.Debug|Any CPU.Build.0 = Debug|Any CPU
{81B7D587-A189-4785-BDFE-CA8A9ABA0760}.Release|Any CPU.ActiveCfg = Release|Any CPU
{81B7D587-A189-4785-BDFE-CA8A9ABA0760}.Release|Any CPU.Build.0 = Release|Any CPU
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|Any CPU.ActiveCfg = Debug|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|Any CPU.Build.0 = Debug|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|Any CPU.Deploy.0 = Debug|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|ARM.ActiveCfg = Debug|ARM
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|ARM.Build.0 = Debug|ARM
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|ARM.Deploy.0 = Debug|ARM
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|x64.ActiveCfg = Debug|x64
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|x64.Build.0 = Debug|x64
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|x64.Deploy.0 = Debug|x64
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|x86.ActiveCfg = Debug|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|x86.Build.0 = Debug|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Debug|x86.Deploy.0 = Debug|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|Any CPU.ActiveCfg = Release|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|ARM.ActiveCfg = Release|ARM
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|ARM.Build.0 = Release|ARM
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|ARM.Deploy.0 = Release|ARM
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|x64.ActiveCfg = Release|x64
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|x64.Build.0 = Release|x64
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|x64.Deploy.0 = Release|x64
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|x86.ActiveCfg = Release|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|x86.Build.0 = Release|x86
{5CBB92EC-C1A2-4108-9A23-3B73DD138953}.Release|x86.Deploy.0 = Release|x86
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|ARM.ActiveCfg = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|ARM.Build.0 = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|x64.ActiveCfg = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|x64.Build.0 = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|x86.ActiveCfg = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Debug|x86.Build.0 = Debug|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|Any CPU.Build.0 = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|ARM.ActiveCfg = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|ARM.Build.0 = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|x64.ActiveCfg = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|x64.Build.0 = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|x86.ActiveCfg = Release|Any CPU
{0E22926C-7244-4A17-923C-84B46F5149C0}.Release|x86.Build.0 = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|ARM.ActiveCfg = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|ARM.Build.0 = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|x64.ActiveCfg = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|x64.Build.0 = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|x86.ActiveCfg = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Debug|x86.Build.0 = Debug|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|Any CPU.Build.0 = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|ARM.ActiveCfg = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|ARM.Build.0 = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|x64.ActiveCfg = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|x64.Build.0 = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|x86.ActiveCfg = Release|Any CPU
{3BAA93AD-3B5C-47C4-816B-F29A1E6D1C2D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{5CBB92EC-C1A2-4108-9A23-3B73DD138953} = {AFD4E3F1-B23C-4924-BA5B-D917FBADB8FA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6B433CE4-D4DE-4360-80A1-DE2DB143DF0D}
EndGlobalSection
EndGlobal
+160
View File
@@ -0,0 +1,160 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Retrieves the requestCode from Pocket, which is used to generate the Authentication URI to authenticate the user
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="System.NullReferenceException">Authentication methods need a callbackUri on initialization of the PocketClient class</exception>
/// <exception cref="PocketException"></exception>
public async Task<string> GetRequestCode(CancellationToken cancellationToken = default(CancellationToken))
{
// check if request code is available
if (CallbackUri == null)
{
throw new NullReferenceException("Authentication methods need a callbackUri on initialization of the PocketClient class");
}
// do request
RequestCode response = await Request<RequestCode>("oauth/request", cancellationToken, new Dictionary<string, string>()
{
{ "redirect_uri", CallbackUri }
}, false);
// save code to client
RequestCode = response.Code;
// generate redirection URI and return
return RequestCode;
}
/// <summary>
/// Generate Authentication URI from requestCode
/// </summary>
/// <param name="requestCode">The requestCode. If no requestCode is supplied, the property from the PocketClient intialization is used.</param>
/// <returns>A valid URI to redirect the user to.</returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
public Uri GenerateAuthenticationUri(string requestCode = null)
{
// check if request code is available
if (RequestCode == null && requestCode == null)
{
throw new NullReferenceException("Call GetRequestCode() first to receive a request_code");
}
// override property with given param if available
if (requestCode != null)
{
RequestCode = requestCode;
}
return new Uri(String.Format(authentificationUri, RequestCode, CallbackUri, isMobileClient ? "1" : "0", "login", useInsideWebAuthenticationBroker ? "1" : "0"));
}
/// <summary>
/// Generate registration URI from requestCode
/// Follow the steps as with GenerateAuthenticationUri, but for unregistered users
/// </summary>
/// <param name="requestCode">The requestCode. If no requestCode is supplied, the property from the PocketClient intialization is used.</param>
/// <returns>A valid URI to redirect the user to.</returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
public Uri GenerateRegistrationUri(string requestCode = null)
{
// check if request code is available
if (RequestCode == null && requestCode == null)
{
throw new NullReferenceException("Call GetRequestCode() first to receive a request_code");
}
// override property with given param if available
if (requestCode != null)
{
RequestCode = requestCode;
}
return new Uri(String.Format(authentificationUri, RequestCode, CallbackUri, isMobileClient ? "1" : "0", "signup", useInsideWebAuthenticationBroker ? "1" : "0"));
}
/// <summary>
/// Requests the access code and username after authentication
/// The access code has to permanently be stored within the users session, and should be passed in the constructor for all future PocketClient initializations.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="requestCode">The request code.</param>
/// <returns>
/// The authenticated user
/// </returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
public async Task<PocketUser> GetUser(string requestCode = null, CancellationToken cancellationToken = default(CancellationToken))
{
// check if request code is available
if (RequestCode == null && requestCode == null)
{
throw new NullReferenceException("Call GetRequestCode() first to receive a request_code");
}
// override property with given param if available
if (requestCode != null)
{
RequestCode = requestCode;
}
// do request
GetUserResponse response = await Request<GetUserResponse>("oauth/authorize", cancellationToken, new Dictionary<string, string>()
{
{ "code", RequestCode },
{ "account", "1" }
}, false);
string avatar = response.Account?.Profile?.Avatar_url;
PocketUser user = new PocketUser()
{
Username = response.Username,
Code = response.Access_token,
Id = response.Account?.User_id,
Email = response.Account?.Email,
FirstName = response.Account?.First_name,
LastName = response.Account?.Last_name,
Followers = response.Account?.Profile?.Follower_count ?? 0,
Follows = response.Account?.Profile?.Follow_count ?? 0,
Avatar = avatar != null ? new Uri(avatar, UriKind.Absolute) : null,
IsDefaultAvatar = avatar == null || avatar.Contains("pocket-profile-images."),
Description = response.Account?.Profile?.Description
};
// save code to client
AccessCode = user.Code;
return user;
}
/// <summary>
/// Get a new GUID from the Pocket API.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The GUID
/// </returns>
public async Task<string> GetGuid(CancellationToken cancellationToken = default(CancellationToken))
{
GuidResponse response = await Request<GuidResponse>("guid", cancellationToken, requireAuth: false);
return response.Guid;
}
}
}
+22 -12
View File
@@ -1,5 +1,7 @@
using PocketSharp.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
@@ -15,9 +17,25 @@ namespace PocketSharp
/// <param name="tags">A comma-separated list of tags to apply to the item</param>
/// <param name="title">This can be included for cases where an item does not have a title, which is typical for image or PDF URLs. If Pocket detects a title from the content of the page, this parameter will be ignored.</param>
/// <param name="tweetID">If you are adding Pocket support to a Twitter client, please send along a reference to the tweet status id. This allows Pocket to show the original tweet alongside the article.</param>
/// <returns></returns>
public PocketItem Add(Uri uri, string[] tags = null, string title = null, string tweetID = null)
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// A simple representation of the saved item which doesn't contain all data (is only returned by calling the Retrieve method)
/// </returns>
/// <exception cref="System.FormatException">(1) Uri should be absolute.</exception>
/// <exception cref="PocketException"></exception>
public async Task<PocketItem> Add(
Uri uri,
string[] tags = null,
string title = null,
string tweetID = null,
CancellationToken cancellationToken = default(CancellationToken)
)
{
if (!uri.IsAbsoluteUri)
{
throw new FormatException("(1) Uri should be absolute.");
}
AddParameters parameters = new AddParameters()
{
Uri = uri,
@@ -25,18 +43,10 @@ namespace PocketSharp
Title = title,
TweetID = tweetID
};
return Get<Add>("add", parameters.Convert(), true).Item;
}
Add response = await Request<Add>("add", cancellationToken, parameters.Convert());
/// <summary>
/// Adds a new item to pocket
/// </summary>
/// <param name="uri">The URL of the item you want to save</param>
/// <returns></returns>
public PocketItem Add(Uri uri)
{
return Add(uri, null, null, null);
return response.Item;
}
}
}
@@ -1,86 +0,0 @@
using PocketSharp.Models.Authentification;
using System;
using System.Collections.Generic;
using RestSharp;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Retrieves the requestCode from Pocket.
/// </summary>
/// <returns></returns>
public string GetRequestCode()
{
// check if request code is available
if (CallbackUri == null)
{
throw new APIException("Authentication methods need a callbackUri on initialization of the PocketClient class");
}
// do request
RequestCode response = Get<RequestCode>("oauth/request", Utilities.CreateParamInList("redirect_uri", CallbackUri));
// save code to client
RequestCode = response.Code;
// generate redirection URI and return
return RequestCode;
}
/// <summary>
/// Generate Authentication URI from requestCode
/// </summary>
/// <param name="requestCode">The requestCode.</param>
/// <returns></returns>
public Uri GenerateAuthenticationUri(string requestCode = null)
{
// check if request code is available
if(RequestCode == null && requestCode == null)
{
throw new APIException("Call GetRequestCode() first to receive a request_code");
}
// override property with given param if available
if(requestCode != null)
{
RequestCode = requestCode;
}
return new Uri(string.Format(authentificationUri, RequestCode, Uri.EscapeDataString(CallbackUri.ToString())));
}
/// <summary>
/// Requests the access code after authentification
/// </summary>
/// <returns></returns>
public string GetAccessCode(string requestCode = null)
{
// check if request code is available
if(RequestCode == null && requestCode == null)
{
throw new APIException("Call GetRequestCode() first to receive a request_code");
}
// override property with given param if available
if(requestCode != null)
{
RequestCode = requestCode;
}
// do request
AccessCode response = Get<AccessCode>("oauth/authorize", Utilities.CreateParamInList("code", RequestCode));
// save code to client
AccessCode = response.Code;
return AccessCode;
}
}
}
+101
View File
@@ -0,0 +1,101 @@
//using HtmlAgilityPack;
//using PocketSharp.Models;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Threading;
//using System.Threading.Tasks;
//using System.Web;
//namespace PocketSharp
//{
// /// <summary>
// /// PocketClient
// /// </summary>
// public partial class PocketClient
// {
// /// <summary>
// /// Term to use for trending articles in the Explore() method
// /// </summary>
// const string EXPLORE_TRENDING = "trending";
// /// <summary>
// /// Term to use for must-read articles in the Explore() method
// /// </summary>
// const string EXPLORE_MUST_READS = "must-reads";
// /// <summary>
// /// Explore Pocket and find interesting articles by a certain topic
// /// </summary>
// /// <param name="topic">Term or topic to get articles for</param>
// /// <param name="cancellationToken"></param>
// /// <returns></returns>
// async Task<IEnumerable<PocketExploreItem>> Explore(string topic, CancellationToken cancellationToken = default(CancellationToken))
// {
// List<PocketExploreItem> items = new List<PocketExploreItem>();
// string html = await RequestAsString("https://getpocket.com/explore/" + HttpUtility.UrlEncode(topic), cancellationToken);
// var document = new HtmlDocument();
// document.LoadHtml(html);
// IEnumerable<HtmlNode> nodes = document.DocumentNode.SelectNodesByClass("media_item");
// if (nodes == null || !nodes.Any())
// {
// return items;
// }
// for (int i = 0; i < nodes.Count(); i++)
// {
// HtmlNode node = nodes.ElementAt(i);
// PocketExploreItem item = new PocketExploreItem();
// item.ID = node.Id;
// HtmlNode title = node.SelectNodeByClass("title")?.FirstChild;
// if (title == null)
// {
// continue;
// }
// // get uri
// string uri = title.GetAttributeValue("data-saveurl", null);
// item.Uri = new Uri(uri);
// // get image
// string imageUri = node.SelectNodeByClass("item_image")?.GetAttributeValue("data-thumburl", null);
// if (!String.IsNullOrEmpty(imageUri))
// {
// PocketImage image = new PocketImage();
// image.Uri = new Uri(imageUri);
// image.ID = "0";
// image.ItemID = item.ID;
// item.Images = new List<PocketImage>() { image };
// }
// // get basic infos
// item.Title = title.InnerText;
// item.Excerpt = node.SelectNodeByClass("excerpt")?.InnerText;
// item.IsTrending = node.SelectNodeByClass("flag-trending") != null;
// // save count
// string saveCountStr = node.SelectNodeByClass("save_count")?.InnerText?.Split(' ')?.FirstOrDefault();
// int saveCount = 0;
// Int32.TryParse(saveCountStr, out saveCount);
// item.SaveCount = saveCount;
// // add published date
// DateTime publishedDate = DateTime.Now;
// if (DateTime.TryParse(node.SelectNodeByClass("read_time")?.InnerText, out publishedDate))
// {
// item.PublishedTime = publishedDate;
// }
// items.Add(item);
// }
// return items;
// }
// }
//}
+288
View File
@@ -0,0 +1,288 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Retrieves items from pocket
/// with the given filters
/// </summary>
/// <param name="state">The state.</param>
/// <param name="favorite">The favorite.</param>
/// <param name="tag">The tag.</param>
/// <param name="contentType">Type of the content.</param>
/// <param name="sort">The sort.</param>
/// <param name="search">The search.</param>
/// <param name="domain">The domain.</param>
/// <param name="since">The since.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketItem>> Get(
State? state = null,
bool? favorite = null,
string tag = null,
ContentType? contentType = null,
Sort? sort = null,
string search = null,
string domain = null,
DateTime? since = null,
int? count = null,
int? offset = null,
CancellationToken cancellationToken = default(CancellationToken)
)
{
RetrieveParameters parameters = new RetrieveParameters()
{
State = state,
Favorite = favorite,
Tag = tag,
ContentType = contentType,
Sort = sort,
DetailType = DetailType.complete,
Search = search,
Domain = domain,
Since = since.HasValue ? ((DateTime)since).ToUniversalTime() : since,
Count = count,
Offset = offset,
Version = 2
};
return (await Request<Retrieve>("get", cancellationToken, parameters.Convert())).Items ?? new List<PocketItem>();
}
/// <summary>
/// Retrieves an item by a given ID
/// Note: The Pocket API contains no method, which allows to retrieve a single item, so all items are retrieved and filtered locally by the ID.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<PocketItem> Get(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return (await Get(
cancellationToken: cancellationToken,
state: State.all
)).SingleOrDefault<PocketItem>(item => item.ID == itemID);
}
/// <summary>
/// Retrieves all items by a given filter
/// </summary>
/// <param name="filter">The filter.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketItem>> Get(RetrieveFilter filter, CancellationToken cancellationToken = default(CancellationToken))
{
RetrieveParameters parameters = new RetrieveParameters();
switch (filter)
{
case RetrieveFilter.Article:
parameters.ContentType = ContentType.article;
break;
case RetrieveFilter.Image:
parameters.ContentType = ContentType.image;
break;
case RetrieveFilter.Video:
parameters.ContentType = ContentType.video;
break;
case RetrieveFilter.Favorite:
parameters.Favorite = true;
break;
case RetrieveFilter.Unread:
parameters.State = State.unread;
break;
case RetrieveFilter.Archive:
parameters.State = State.archive;
break;
case RetrieveFilter.All:
parameters.State = State.all;
break;
}
parameters.DetailType = DetailType.complete;
return (await Request<Retrieve>("get", cancellationToken, parameters.Convert())).Items;
}
/// <summary>
/// Converts a raw JSON response to a PocketItem list
/// </summary>
/// <param name="itemsJSON">The raw JSON response.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public IEnumerable<PocketItem> ConvertJsonToList(string itemsJSON)
{
return DeserializeJson<Retrieve>(itemsJSON).Items;
}
/// <summary>
/// Retrieves all available tags.
/// Note: The Pocket API contains no method, which allows to retrieve all tags, so all items are retrieved and the associated tags extracted.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketTag>> GetTags(CancellationToken cancellationToken = default(CancellationToken))
{
IEnumerable<PocketItem> items = await Get(
cancellationToken: cancellationToken,
state: State.all
);
return items
.Where(item => item.Tags != null)
.SelectMany(item => item.Tags)
.GroupBy(item => item.Name)
.Select(item => item.First())
.ToList<PocketTag>();
}
/// <summary>
/// Retrieves items by tag
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketItem>> SearchByTag(string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await Get(
state: State.all,
cancellationToken: cancellationToken,
tag: tag
);
}
/// <summary>
/// Retrieves items which match the specified search string in title and URI
/// </summary>
/// <param name="searchString">The search string.</param>
/// <param name="tag">Filter by tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentOutOfRangeException">Search string length has to be a minimum of 2 chars</exception>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketItem>> Search(string searchString, string tag = null, CancellationToken cancellationToken = default(CancellationToken))
{
if (String.IsNullOrEmpty(searchString) || searchString.Length < 2)
{
throw new ArgumentOutOfRangeException("Search string length has to be a minimum of 2 chars");
}
return await Get(
state: State.all,
search: searchString,
tag: tag,
cancellationToken: cancellationToken
);
}
/// <summary>
/// Retrieves the article content from an URI
/// WARNING:
/// You have to pass the parseUri in the PocketClient ctor for this method to work.
/// This is a private API and can only be used by authenticated users.
/// </summary>
/// <param name="uri">The article URI.</param>
/// <param name="includeImages">Include images into content or use placeholder.</param>
/// <param name="includeVideos">Include videos into content or use placeholder.</param>
/// <param name="forceRefresh">Force refresh of the content (don't use cache).</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<PocketArticle> GetArticle(Uri uri, bool includeImages = true, bool includeVideos = true, bool forceRefresh = false, CancellationToken cancellationToken = default(CancellationToken))
{
Dictionary<string, string> parameters = new Dictionary<string, string>()
{
{ "url", uri.OriginalString },
{ "images", includeImages ? "1" : "0" },
{ "videos", includeVideos ? "1" : "0" },
{ "refresh", forceRefresh ? "1" : "0" },
{ "output", "json" }
};
return await Request<PocketArticle>("", cancellationToken, parameters, false, true);
}
/// <summary>
/// Get article suggestions for an existing Pocket item.
/// </summary>
/// <param name="itemId">Get suggestions based on this item.</param>
/// <param name="count">Requested item count.</param>
/// <param name="languageCode">Two-letter language code for language-specific results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketItem>> GetSuggestions(string itemId, int count = 3, string languageCode = "en", CancellationToken cancellationToken = default(CancellationToken))
{
Dictionary<string, string> parameters = new Dictionary<string, string>()
{
{ "resolved_id", itemId },
{ "version", "1" },
{ "locale_lang", languageCode },
{ "count", count.ToString() }
};
return (await Request<Retrieve>("getSuggestedItems", cancellationToken, parameters)).Items ?? new List<PocketItem>();
}
}
/// <summary>
/// Filter for simple retrieve requests
/// </summary>
public enum RetrieveFilter
{
/// <summary>
/// All types
/// </summary>
All,
/// <summary>
/// Only unread items
/// </summary>
Unread,
/// <summary>
/// Archived items
/// </summary>
Archive,
/// <summary>
/// Favorited items
/// </summary>
Favorite,
/// <summary>
/// Only articles
/// </summary>
Article,
/// <summary>
/// Only videos
/// </summary>
Video,
/// <summary>
/// Only images
/// </summary>
Image
}
}
+75 -23
View File
@@ -1,4 +1,8 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
@@ -7,14 +11,44 @@ namespace PocketSharp
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Sends multiple actions in one request.
/// See: http://getpocket.com/developer/docs/v3/modify
/// </summary>
/// <param name="actions">The actions.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> SendActions(IEnumerable<PocketAction> actions, CancellationToken cancellationToken = default(CancellationToken))
{
return await Send(actions, cancellationToken);
}
/// <summary>
/// Sends an action.
/// See: http://getpocket.com/developer/docs/v3/modify
/// </summary>
/// <param name="action">The action.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> SendAction(PocketAction action, CancellationToken cancellationToken = default(CancellationToken))
{
return await Send(new List<PocketAction>() { action }, cancellationToken);
}
/// <summary>
/// Archives the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Archive(int itemID)
/// <exception cref="PocketException"></exception>
public async Task<bool> Archive(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionDefault(itemID, "archive");
return await SendDefault(cancellationToken, itemID, "archive");
}
@@ -22,10 +56,12 @@ namespace PocketSharp
/// Archives the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Archive(PocketItem item)
/// <exception cref="PocketException"></exception>
public async Task<bool> Archive(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return Archive(item.ID);
return await Archive(item.ID, cancellationToken);
}
@@ -33,10 +69,12 @@ namespace PocketSharp
/// Un-archives the specified item (alias for Readd).
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Unarchive(int itemID)
/// <exception cref="PocketException"></exception>
public async Task<bool> Unarchive(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionDefault(itemID, "readd");
return await SendDefault(cancellationToken, itemID, "readd");
}
@@ -44,10 +82,12 @@ namespace PocketSharp
/// Unarchives the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Unarchive(PocketItem item)
/// <exception cref="PocketException"></exception>
public async Task<bool> Unarchive(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return Unarchive(item.ID);
return await Unarchive(item.ID, cancellationToken);
}
@@ -55,10 +95,12 @@ namespace PocketSharp
/// Favorites the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Favorite(int itemID)
/// <exception cref="PocketException"></exception>
public async Task<bool> Favorite(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionDefault(itemID, "favorite");
return await SendDefault(cancellationToken, itemID, "favorite");
}
@@ -66,10 +108,12 @@ namespace PocketSharp
/// Favorites the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Favorite(PocketItem item)
/// <exception cref="PocketException"></exception>
public async Task<bool> Favorite(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return Favorite(item.ID);
return await Favorite(item.ID, cancellationToken);
}
@@ -77,10 +121,12 @@ namespace PocketSharp
/// Un-favorites the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Unfavorite(int itemID)
/// <exception cref="PocketException"></exception>
public async Task<bool> Unfavorite(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionDefault(itemID, "unfavorite");
return await SendDefault(cancellationToken, itemID, "unfavorite");
}
@@ -88,48 +134,54 @@ namespace PocketSharp
/// Un-favorites the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool Unfavorite(PocketItem item)
/// <exception cref="PocketException"></exception>
public async Task<bool> Unfavorite(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return Unfavorite(item.ID);
return await Unfavorite(item.ID, cancellationToken);
}
/// <summary>
/// Deletes the specified item.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="itemID">The item ID.</param>
/// <returns></returns>
public bool Delete(int itemID)
/// <exception cref="PocketException"></exception>
public async Task<bool> Delete(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionDefault(itemID, "delete");
return await SendDefault(cancellationToken, itemID, "delete");
}
/// <summary>
/// Deletes the specified item.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="item">The item.</param>
/// <returns></returns>
public bool Delete(PocketItem item)
public async Task<bool> Delete(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return Delete(item.ID);
return await Delete(item.ID, cancellationToken);
}
/// <summary>
/// Puts an action
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="itemID">The item ID.</param>
/// <param name="action">The action.</param>
/// <returns></returns>
protected bool PutSendActionDefault(int itemID, string action)
protected async Task<bool> SendDefault(CancellationToken cancellationToken, string itemID, string action)
{
return PutSendAction(new ActionParameter()
return await Send(new PocketAction()
{
Action = action,
ID = itemID
});
}, cancellationToken);
}
}
}
+132 -81
View File
@@ -1,4 +1,6 @@
using PocketSharp.Models;
using PocketSharp.Models;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
@@ -8,146 +10,195 @@ namespace PocketSharp
public partial class PocketClient
{
/// <summary>
/// Adds the specified tags.
/// Adds the specified tags to an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool AddTags(int itemID, string[] tags)
/// <exception cref="PocketException"></exception>
public async Task<bool> AddTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionForTags(itemID, "tags_add", tags);
return await SendTags(cancellationToken, itemID, "tags_add", tags);
}
/// <summary>
/// Adds the specified tags.
/// Adds the specified tags to an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool AddTags(PocketItem item, string[] tags)
/// <exception cref="PocketException"></exception>
public async Task<bool> AddTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return AddTags(item.ID, tags);
return await AddTags(item.ID, tags, cancellationToken);
}
/// <summary>
/// Removes the specified tags.
/// Removes the specified tags from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool RemoveTags(int itemID, string[] tags)
/// <exception cref="PocketException"></exception>
public async Task<bool> RemoveTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendActionForTags(itemID, "tags_remove", tags);
return await SendTags(cancellationToken, itemID, "tags_remove", tags);
}
/// <summary>
/// Removes the specified tags.
/// Removes the specified tags from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> RemoveTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await RemoveTags(item.ID, tags, cancellationToken);
}
/// <summary>
/// Removes a tag from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> RemoveTag(string itemID, string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendTags(cancellationToken, itemID, "tags_remove", new string[] { tag });
}
/// <summary>
/// Removes a tag from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> RemoveTag(PocketItem item, string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await RemoveTag(item.ID, tag, cancellationToken);
}
/// <summary>
/// Clears all tags from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> RemoveTags(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(cancellationToken, itemID, "tags_clear");
}
/// <summary>
/// Clears all tags from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> RemoveTags(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await RemoveTags(item.ID, cancellationToken);
}
/// <summary>
/// Deletes a tag. This will remove it from all affected items too.
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> DeleteTag(string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await Send(new PocketAction()
{
Action = "tag_delete",
Tag = tag
}, cancellationToken);
}
/// <summary>
/// Replaces all existing tags with the given tags in an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<bool> ReplaceTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendTags(cancellationToken, itemID, "tags_replace", tags);
}
/// <summary>
/// Replaces all existing tags with the given new ones in an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool RemoveTags(PocketItem item, string[] tags)
/// <exception cref="PocketException"></exception>
public async Task<bool> ReplaceTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return RemoveTags(item.ID, tags);
return await ReplaceTags(item.ID, tags, cancellationToken);
}
/// <summary>
/// Clears all tags.
/// Renames a tag. This affects all items with this tag.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <returns></returns>
public bool RemoveTags(int itemID)
{
return PutSendActionDefault(itemID, "tags_clear");
}
/// <summary>
/// Clears all tags.
/// </summary>
/// <param name="item">The item.</param>
/// <returns></returns>
public bool RemoveTags(PocketItem item)
{
return RemoveTags(item.ID);
}
/// <summary>
/// Replaces all existing tags with new ones.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <returns></returns>
public bool ReplaceTags(int itemID, string[] tags)
{
return PutSendActionForTags(itemID, "tags_replace", tags);
}
/// <summary>
/// Replaces all existing tags with new ones.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tags.</param>
/// <returns></returns>
public bool ReplaceTags(PocketItem item, string[] tags)
{
return ReplaceTags(item.ID, tags);
}
/// <summary>
/// Renames a tag.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="oldTag">The old tag.</param>
/// <param name="newTag">The new tag name.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public bool RenameTag(int itemID, string oldTag, string newTag)
/// <exception cref="PocketException"></exception>
public async Task<bool> RenameTag(string oldTag, string newTag, CancellationToken cancellationToken = default(CancellationToken))
{
return PutSendAction(new ActionParameter()
return await Send(new PocketAction()
{
Action = "tag_rename",
ID = itemID,
OldTag = oldTag,
NewTag = newTag
});
}
/// <summary>
/// Renames a tag.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="oldTag">The old tag.</param>
/// <param name="newTag">The new tag name.</param>
/// <returns></returns>
public bool RenameTag(PocketItem item, string oldTag, string newTag)
{
return RenameTag(item.ID, oldTag, newTag);
}, cancellationToken);
}
/// <summary>
/// Puts the send action for tags.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="itemID">The item ID.</param>
/// <param name="action">The action.</param>
/// <param name="tags">The tags.</param>
/// <returns></returns>
protected bool PutSendActionForTags(int itemID, string action, string[] tags)
protected async Task<bool> SendTags(CancellationToken cancellationToken, string itemID, string action, string[] tags)
{
return PutSendAction(new ActionParameter()
return await Send(new PocketAction()
{
Action = action,
ID = itemID,
Tags = tags
});
}, cancellationToken);
}
}
}
-126
View File
@@ -1,126 +0,0 @@
using PocketSharp.Models;
using System.Collections.Generic;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Retrieves all items from pocket
/// </summary>
/// <param name="parameters">parameters, which are mapped to the officials from http://getpocket.com/developer/docs/v3/retrieve </param>
/// <returns></returns>
public List<PocketItem> Retrieve(RetrieveParameters parameters)
{
return Get<Retrieve>("get", parameters.Convert(), true).Items;
}
/// <summary>
/// Retrieves all items with a filter from pocket
/// </summary>
/// <param name="filter">The filter.</param>
/// <returns></returns>
public List<PocketItem> Retrieve(RetrieveFilter filter = RetrieveFilter.All)
{
RetrieveParameters parameters = new RetrieveParameters();
switch(filter)
{
case RetrieveFilter.Article:
parameters.ContentType = ContentTypeEnum.article;
break;
case RetrieveFilter.Image:
parameters.ContentType = ContentTypeEnum.image;
break;
case RetrieveFilter.Video:
parameters.ContentType = ContentTypeEnum.video;
break;
case RetrieveFilter.Favorite:
parameters.Favorite = true;
break;
case RetrieveFilter.Unread:
parameters.State = StateEnum.unread;
break;
case RetrieveFilter.Archive:
parameters.State = StateEnum.archive;
break;
}
//parameters.DetailType = DetailTypeEnum.complete;
return Get<Retrieve>("get", parameters.Convert(), true).Items;
}
/// <summary>
/// Retrieves items by tag from pocket
/// </summary>
/// <param name="tag">The tag.</param>
/// <returns></returns>
public List<PocketItem> SearchByTag(string tag)
{
RetrieveParameters parameters = new RetrieveParameters()
{
Tag = tag,
DetailType = DetailTypeEnum.complete
};
return Get<Retrieve>("get", parameters.Convert(), true).Items;
}
/// <summary>
/// Retrieves items from pocket which match the specified search string in title or content
/// </summary>
/// <param name="searchString">The search string.</param>
/// <returns></returns>
public List<PocketItem> Search(string searchString)
{
RetrieveParameters parameters = new RetrieveParameters()
{
Search = searchString,
DetailType = DetailTypeEnum.complete
};
return Get<Retrieve>("get", parameters.Convert(), true).Items;
}
}
/// <summary>
/// Filter for simple retrieve requests
/// </summary>
public enum RetrieveFilter
{
/// <summary>
/// All types
/// </summary>
All,
/// <summary>
/// Only unread items
/// </summary>
Unread,
/// <summary>
/// Archived items
/// </summary>
Archive,
/// <summary>
/// Favorited items
/// </summary>
Favorite,
/// <summary>
/// Only articles
/// </summary>
Article,
/// <summary>
/// Only videos
/// </summary>
Video,
/// <summary>
/// Only images
/// </summary>
Image
}
}
+57
View File
@@ -0,0 +1,57 @@
using PocketSharp.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Statistics from the user account.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<PocketStatistics> GetUserStatistics(CancellationToken cancellationToken = default(CancellationToken))
{
return await Request<PocketStatistics>("stats", cancellationToken);
}
/// <summary>
/// Returns API usage statistics.
/// If a request was made before, the data is returned synchronously from the cache.
/// Note: This method only works for authenticated users with a given AccessCode.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<PocketLimits> GetUsageLimits(CancellationToken cancellationToken = default(CancellationToken))
{
string rateLimitForConsumerKey = TryGetHeaderValue(lastHeaders, "X-Limit-Key-Limit");
if (rateLimitForConsumerKey == null)
{
// this is the fastest way to do a non-failing request to receive the correct headers
await Get(
cancellationToken: cancellationToken,
count: 1
);
}
return new PocketLimits()
{
RateLimitForConsumerKey = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-Key-Limit")),
RemainingCallsForConsumerKey = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-Key-Remaining")),
SecondsUntilLimitResetsForConsumerKey = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-Key-Reset")),
RateLimitForUser = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-User-Limit")),
RemainingCallsForUser = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-User-Remaining")),
SecondsUntilLimitResetsForUser = Convert.ToInt32(TryGetHeaderValue(lastHeaders, "X-Limit-User-Reset"))
};
}
}
}
+48
View File
@@ -0,0 +1,48 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
{
/// <summary>
/// Get trending articles on Pocket.
/// </summary>
/// <param name="count">Article count.</param>
/// <param name="languageCode">Two-letter language code for language-specific results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketItem>> GetTrendingArticles(int count = 20, string languageCode = "en", CancellationToken cancellationToken = default(CancellationToken))
{
return (await Request<Retrieve>("getGlobalRecs", cancellationToken, new Dictionary<string, string>()
{
{ "locale_lang", languageCode },
{ "count", count.ToString() },
{ "version", "2" }
}, false)).Items ?? new List<PocketItem>();
}
/// <summary>
/// Get trending topics on Pocket.
/// </summary>
/// <param name="languageCode">Two-letter language code for language-specific results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
public async Task<IEnumerable<PocketTopic>> GetTrendingTopics(string languageCode = "en", CancellationToken cancellationToken = default(CancellationToken))
{
return (await Request<TopicsResponse>("getTrendingTopics", cancellationToken, new Dictionary<string, string>()
{
{ "locale_lang", languageCode },
{ "version", "2" }
}, false)).Items ?? new List<PocketTopic>();
}
}
}
+512
View File
@@ -0,0 +1,512 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
public interface IPocketClient
{
#region properties
/// <summary>
/// callback URLi for API calls
/// </summary>
/// <value>
/// The callback URI.
/// </value>
string CallbackUri { get; set; }
/// <summary>
/// Accessor for the Pocket API key
/// see: http://getpocket.com/developer
/// </summary>
/// <value>
/// The consumer key.
/// </value>
string ConsumerKey { get; set; }
/// <summary>
/// Code retrieved on authentification
/// </summary>
/// <value>
/// The request code.
/// </value>
string RequestCode { get; set; }
/// <summary>
/// Code retrieved on authentification-success
/// </summary>
/// <value>
/// The access code.
/// </value>
string AccessCode { get; set; }
/// <summary>
/// Action which is executed before every request
/// </summary>
/// <value>
/// The pre request callback.
/// </value>
Action<string> PreRequest { get; set; }
#endregion
#region account methods
/// <summary>
/// Retrieves the requestCode from Pocket, which is used to generate the Authentication URI to authenticate the user
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="System.NullReferenceException">Authentication methods need a callbackUri on initialization of the PocketClient class</exception>
/// <exception cref="PocketException"></exception>
Task<string> GetRequestCode(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Generate Authentication URI from requestCode
/// </summary>
/// <param name="requestCode">The requestCode. If no requestCode is supplied, the property from the PocketClient intialization is used.</param>
/// <returns>
/// A valid URI to redirect the user to.
/// </returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
Uri GenerateAuthenticationUri(string requestCode = null);
/// <summary>
/// Requests the access code and username after authentication
/// The access code has to permanently be stored within the users session, and should be passed in the constructor for all future PocketClient initializations.
/// </summary>
/// <param name="requestCode">The request code.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The authenticated user
/// </returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
Task<PocketUser> GetUser(string requestCode = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Generate registration URI from requestCode
/// </summary>
/// <param name="requestCode">The requestCode. If no requestCode is supplied, the property from the PocketClient intialization is used.</param>
/// <returns>A valid URI to redirect the user to.</returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
Uri GenerateRegistrationUri(string requestCode = null);
/// <summary>
/// Get a new GUID from the Pocket API.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// The GUID
/// </returns>
Task<string> GetGuid(CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region add methods
/// <summary>
/// Adds a new item to pocket
/// </summary>
/// <param name="uri">The URL of the item you want to save</param>
/// <param name="tags">A comma-separated list of tags to apply to the item</param>
/// <param name="title">This can be included for cases where an item does not have a title, which is typical for image or PDF URLs. If Pocket detects a title from the content of the page, this parameter will be ignored.</param>
/// <param name="tweetID">If you are adding Pocket support to a Twitter client, please send along a reference to the tweet status id. This allows Pocket to show the original tweet alongside the article.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>
/// A simple representation of the saved item which doesn't contain all data (is only returned by calling the Retrieve method)
/// </returns>
/// <exception cref="System.FormatException">(1) Uri should be absolute.</exception>
/// <exception cref="PocketException"></exception>
Task<PocketItem> Add(Uri uri, string[] tags = null, string title = null, string tweetID = null, CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region get methods
/// <summary>
/// Retrieves items from pocket
/// with the given filters
/// </summary>
/// <param name="state">The state.</param>
/// <param name="favorite">The favorite.</param>
/// <param name="tag">The tag.</param>
/// <param name="contentType">Type of the content.</param>
/// <param name="sort">The sort.</param>
/// <param name="search">The search.</param>
/// <param name="domain">The domain.</param>
/// <param name="since">The since.</param>
/// <param name="count">The count.</param>
/// <param name="offset">The offset.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketItem>> Get(
State? state = null,
bool? favorite = null,
string tag = null,
ContentType? contentType = null,
Sort? sort = null,
string search = null,
string domain = null,
DateTime? since = null,
int? count = null,
int? offset = null,
CancellationToken cancellationToken = default(CancellationToken)
);
/// <summary>
/// Retrieves an item by a given ID
/// Note: The Pocket API contains no method, which allows to retrieve a single item, so all items are retrieved and filtered locally by the ID.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<PocketItem> Get(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Retrieves all items by a given filter
/// </summary>
/// <param name="filter">The filter.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketItem>> Get(RetrieveFilter filter, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Converts a raw JSON response to a PocketItem list
/// </summary>
/// <param name="itemsJSON">The raw JSON response.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
IEnumerable<PocketItem> ConvertJsonToList(string itemsJSON);
/// <summary>
/// Retrieves all available tags.
/// Note: The Pocket API contains no method, which allows to retrieve all tags, so all items are retrieved and the associated tags extracted.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketTag>> GetTags(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Retrieves items by tag
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketItem>> SearchByTag(string tag, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Retrieves items which match the specified search string in title and URI
/// </summary>
/// <param name="searchString">The search string.</param>
/// <param name="tag">Filter by tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentOutOfRangeException">Search string length has to be a minimum of 2 chars</exception>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketItem>> Search(string searchString, string tag = null, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Retrieves the article content from an URI
/// WARNING:
/// You have to pass the parseUri in the PocketClient ctor for this method to work.
/// This is a private API and can only be used by authenticated users.
/// </summary>
/// <param name="tag">The article URI.</param>
/// <param name="includeImages">Include images into content or use placeholder.</param>
/// <param name="includeVideos">Include videos into content or use placeholder.</param>
/// <param name="forceRefresh">Force refresh of the content (don't use cache).</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<PocketArticle> GetArticle(Uri uri, bool includeImages = true, bool includeVideos = true, bool forceRefresh = false, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Get article suggestions for an existing Pocket item.
/// </summary>
/// <param name="itemId">Get suggestions based on this item.</param>
/// <param name="count">Requested item count.</param>
/// <param name="languageCode">Two-letter language code for language-specific results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketItem>> GetSuggestions(string itemId, int count = 3, string languageCode = "en", CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region modify methods
/// <summary>
/// Sends multiple actions in one request.
/// See: http://getpocket.com/developer/docs/v3/modify
/// </summary>
/// <param name="actions">The actions.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> SendActions(IEnumerable<PocketAction> actions, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Archives the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Archive(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Archives the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Archive(PocketItem item, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Un-archives the specified item (alias for Readd).
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Unarchive(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Unarchives the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Unarchive(PocketItem item, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Favorites the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Favorite(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Favorites the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Favorite(PocketItem item, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Un-favorites the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Unfavorite(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Un-favorites the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Unfavorite(PocketItem item, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Deletes the specified item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> Delete(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Deletes the specified item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
Task<bool> Delete(PocketItem item, CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region modify tags methods
/// <summary>
/// Adds the specified tags to an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> AddTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Adds the specified tags to an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> AddTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Removes the specified tags from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RemoveTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Removes the specified tags from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RemoveTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Removes a tag from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RemoveTag(string itemID, string tag, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Removes a tag from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RemoveTag(PocketItem item, string tag, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Clears all tags from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RemoveTags(string itemID, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Clears all tags from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RemoveTags(PocketItem item, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Deletes a tag. This will remove it from all affected items too.
/// </summary>
/// <param name="tag">The tag.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> DeleteTag(string tag, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Replaces all existing tags with the given tags in an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> ReplaceTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Replaces all existing tags with the given new ones in an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tags.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> ReplaceTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Renames a tag. This affects all items with this tag.
/// </summary>
/// <param name="oldTag">The old tag.</param>
/// <param name="newTag">The new tag name.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<bool> RenameTag(string oldTag, string newTag, CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region statistics methods
/// <summary>
/// Statistics from the user account.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<PocketStatistics> GetUserStatistics(CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Returns API usage statistics.
/// If a request was made before, the data is returned synchronously from the cache.
/// Note: This method only works for authenticated users with a given AccessCode.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<PocketLimits> GetUsageLimits(CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region explore/trending methods
/// <summary>
/// Get trending articles on Pocket.
/// Requires an active GUID from GetGuid() and will therefore make two HTTP requests.
/// </summary>
/// <param name="count">Article count.</param>
/// <param name="languageCode">Two-letter language code for language-specific results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketItem>> GetTrendingArticles(int count = 20, string languageCode = "en", CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Get trending topics on Pocket.
/// Requires an active GUID from GetGuid() and will therefore make two HTTP requests.
/// </summary>
/// <param name="languageCode">Two-letter language code for language-specific results.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
Task<IEnumerable<PocketTopic>> GetTrendingTopics(string languageCode = "en", CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Explore Pocket and find interesting articles by a certain topic
/// </summary>
/// <param name="topic">Term or topic to get articles for</param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
// Task<IEnumerable<PocketExploreItem>> Explore(string topic, CancellationToken cancellationToken = default(CancellationToken));
#endregion
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
void Dispose();
}
}
-79
View File
@@ -1,79 +0,0 @@
using RestSharp;
using RestSharp.Deserializers;
using ServiceStack.Text;
using System;
namespace PocketSharp
{
/// <summary>
/// Custom JSON Deserializer which implements ServiceStack.Text
/// </summary>
internal class JsonDeserializer : IDeserializer
{
public const string JsonContentType = "application/json";
/// <summary>
/// Deserializes the specified response.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="response">The response.</param>
/// <returns></returns>
public T Deserialize<T>(IRestResponse response)
{
return JsonSerializer.DeserializeFromString<T>(response.Content);
}
/// <summary>
/// Adds custom deserialization for specific types.
/// </summary>
public static void AddCustomDeserialization()
{
// generate correct Uri format
JsConfig<Uri>.DeSerializeFn = value => new Uri(value);
// create DateTime from UNIX timestamp input
JsConfig<DateTime?>.DeSerializeFn = value =>
{
if (value == "0") return null;
return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(Convert.ToDouble(value)).ToLocalTime();
};
}
/// <summary>
/// Gets or sets the date format.
/// </summary>
/// <value>
/// The date format.
/// </value>
public string DateFormat { get; set; }
/// <summary>
/// Gets or sets the namespace.
/// </summary>
/// <value>
/// The namespace.
/// </value>
public string Namespace { get; set; }
/// <summary>
/// Gets or sets the root element.
/// </summary>
/// <value>
/// The root element.
/// </value>
public string RootElement { get; set; }
/// <summary>
/// Gets the type of the content.
/// </summary>
/// <value>
/// The type of the content.
/// </value>
public string ContentType
{
get { return JsonContentType; }
}
}
}
@@ -1,29 +0,0 @@
using System.Runtime.Serialization;
namespace PocketSharp.Models.Authentification
{
/// <summary>
/// Access Code
/// </summary>
[DataContract]
internal class AccessCode
{
/// <summary>
/// Gets or sets the code.
/// </summary>
/// <value>
/// The code.
/// </value>
[DataMember(Name = "access_token")]
public string Code { get; set; }
/// <summary>
/// Gets or sets the username.
/// </summary>
/// <value>
/// The username.
/// </value>
[DataMember]
public string Username { get; set; }
}
}
@@ -1,86 +0,0 @@
using System;
using System.Collections.Generic;
namespace PocketSharp.Models
{
/// <summary>
/// All parameters which can be passed for a modify action
/// </summary>
public class ActionParameter
{
/// <summary>
/// Gets or sets the action.
/// </summary>
/// <value>
/// The action.
/// </value>
public string Action { get; set; }
/// <summary>
/// Gets or sets the ID.
/// </summary>
/// <value>
/// The ID.
/// </value>
public int ID { get; set; }
/// <summary>
/// Gets or sets the time.
/// </summary>
/// <value>
/// The time.
/// </value>
public DateTime? Time { get; set; }
// specific params
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>
/// The tags.
/// </value>
public string[] Tags { get; set; }
/// <summary>
/// Gets or sets the old tag.
/// </summary>
/// <value>
/// The old tag.
/// </value>
public string OldTag { get; set; }
/// <summary>
/// Gets or sets the new tag.
/// </summary>
/// <value>
/// The new tag.
/// </value>
public string NewTag { get; set; }
/// <summary>
/// Converts this instance to a parameter list.
/// </summary>
/// <returns></returns>
public object Convert()
{
Dictionary<string, object> parameters = new Dictionary<string, object>
{
{ "item_id", ID },
{ "action", Action }
};
if (Time != null)
parameters.Add("time", Utilities.GetUnixTimestamp(Time));
if (Tags != null)
parameters.Add("tags", String.Join(",", Tags));
if (OldTag != null)
parameters.Add("old_tag", OldTag);
if (NewTag != null)
parameters.Add("new_tag", NewTag);
return parameters;
}
}
}
+8 -19
View File
@@ -1,13 +1,13 @@
using RestSharp;
using System;
using System.Collections.Generic;
using System;
using System.Runtime.Serialization;
namespace PocketSharp.Models
{
/// <summary>
/// All parameters which can be passed to add a new item
/// </summary>
public class AddParameters
[DataContract]
internal class AddParameters : Parameters
{
/// <summary>
/// Gets or sets the URI.
@@ -15,6 +15,7 @@ namespace PocketSharp.Models
/// <value>
/// The URI.
/// </value>
[DataMember(Name="url")]
public Uri Uri { get; set; }
/// <summary>
@@ -23,6 +24,7 @@ namespace PocketSharp.Models
/// <value>
/// The title.
/// </value>
[DataMember(Name="title")]
public string Title { get; set; }
/// <summary>
@@ -31,6 +33,7 @@ namespace PocketSharp.Models
/// <value>
/// The tags.
/// </value>
[DataMember(Name="tags")]
public string[] Tags { get; set; }
/// <summary>
@@ -39,21 +42,7 @@ namespace PocketSharp.Models
/// <value>
/// The tweet ID.
/// </value>
[DataMember(Name="tweet_id")]
public string TweetID { get; set; }
/// <summary>
/// Converts this instance to a parameter list.
/// </summary>
/// <returns></returns>
public List<Parameter> Convert()
{
return new List<Parameter>()
{
Utilities.CreateParam("url", Uri.ToString() ),
Utilities.CreateParam("title", Title),
Utilities.CreateParam("tags", String.Join(",", Tags)),
Utilities.CreateParam("tweet_id", TweetID)
};
}
}
}
@@ -1,13 +1,13 @@
using RestSharp;
using ServiceStack.Text;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace PocketSharp.Models
{
/// <summary>
/// All parameters which can be passed to modify an item
/// </summary>
public class ModifyParameters
[DataContract]
internal class ModifyParameters : Parameters
{
/// <summary>
/// Gets or sets the actions.
@@ -15,23 +15,7 @@ namespace PocketSharp.Models
/// <value>
/// The actions.
/// </value>
public List<ActionParameter> Actions { get; set; }
/// <summary>
/// Converts this instance to a parameter list.
/// </summary>
/// <returns></returns>
public List<Parameter> Convert()
{
List<object> actions = new List<object>();
Actions.ForEach(action => actions.Add(action.Convert()));
return new List<Parameter>()
{
Utilities.CreateParam("actions", JsonSerializer.SerializeToString(actions))
};
}
[DataMember(Name = "actions")]
public IEnumerable<Dictionary<string, string>> Actions { get; set; }
}
}
@@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.Linq;
using System.Collections;
namespace PocketSharp.Models
{
/// <summary>
/// Parameter
/// </summary>
internal class Parameters
{
/// <summary>
/// Converts an object to a list of HTTP Post parameters.
/// </summary>
/// <returns></returns>
public Dictionary<string, string> Convert()
{
// store HTTP parameters here
Dictionary<string, string> parameterDict = new Dictionary<string, string>();
// get object properties
IEnumerable<MemberInfo> properties = this.GetType()
.GetTypeInfo()
.DeclaredMembers
.Where(p => p.CustomAttributes.FirstOrDefault(a => a.AttributeType == typeof(DataMemberAttribute)) != null);
// gather attributes of object
foreach (MemberInfo memberInfo in properties)
{
DataMemberAttribute attribute = (DataMemberAttribute)memberInfo.GetCustomAttributes(typeof(DataMemberAttribute), false).FirstOrDefault();
string name = attribute.Name ?? memberInfo.Name.ToLower();
object value = null;
if (memberInfo is FieldInfo)
{
value = ((FieldInfo)memberInfo).GetValue(this);
}
else
{
value = ((PropertyInfo)memberInfo).GetValue(this, null);
}
// invalid parameter
if (value == null)
{
continue;
}
// convert array to comma-seperated list
if (value is IEnumerable && value.GetType().GetElementType() == typeof(string))
{
value = string.Join(",", ((IEnumerable)value).Cast<object>().Select(x => x.ToString()).ToArray());
}
// convert booleans
if (value is bool)
{
value = System.Convert.ToBoolean(value) ? "1" : "0";
}
// convert DateTime to UNIX timestamp
if (value is DateTime)
{
value = (int)((DateTime)value - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds;
}
parameterDict.Add(name, value.ToString());
}
return parameterDict;
}
}
}
@@ -1,13 +1,13 @@
using RestSharp;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace PocketSharp.Models
{
/// <summary>
/// All parameters which can be passed for item retrieval
/// </summary>
public class RetrieveParameters
[DataContract]
internal class RetrieveParameters : Parameters
{
/// <summary>
/// Gets or sets the state.
@@ -15,7 +15,8 @@ namespace PocketSharp.Models
/// <value>
/// The state.
/// </value>
public StateEnum? State { get; set; }
[DataMember(Name = "state")]
public State? State { get; set; }
/// <summary>
/// Gets or sets the favorite.
@@ -23,6 +24,7 @@ namespace PocketSharp.Models
/// <value>
/// The favorite.
/// </value>
[DataMember(Name = "favorite")]
public bool? Favorite { get; set; }
/// <summary>
@@ -31,6 +33,7 @@ namespace PocketSharp.Models
/// <value>
/// The tag.
/// </value>
[DataMember(Name = "tag")]
public string Tag { get; set; }
/// <summary>
@@ -39,7 +42,8 @@ namespace PocketSharp.Models
/// <value>
/// The type of the content.
/// </value>
public ContentTypeEnum? ContentType { get; set; }
[DataMember(Name = "contentType")]
public ContentType? ContentType { get; set; }
/// <summary>
/// Gets or sets the sort.
@@ -47,7 +51,8 @@ namespace PocketSharp.Models
/// <value>
/// The sort.
/// </value>
public SortEnum? Sort { get; set; }
[DataMember(Name = "sort")]
public Sort? Sort { get; set; }
/// <summary>
/// Gets or sets the type of the detail.
@@ -55,7 +60,8 @@ namespace PocketSharp.Models
/// <value>
/// The type of the detail.
/// </value>
public DetailTypeEnum? DetailType { get; set; }
[DataMember(Name="detailType")]
public DetailType? DetailType { get; set; }
/// <summary>
/// Gets or sets the search.
@@ -63,6 +69,7 @@ namespace PocketSharp.Models
/// <value>
/// The search.
/// </value>
[DataMember(Name = "search")]
public string Search { get; set; }
/// <summary>
@@ -71,6 +78,7 @@ namespace PocketSharp.Models
/// <value>
/// The domain.
/// </value>
[DataMember(Name = "domain")]
public string Domain { get; set; }
/// <summary>
@@ -79,6 +87,7 @@ namespace PocketSharp.Models
/// <value>
/// The since.
/// </value>
[DataMember(Name = "since")]
public DateTime? Since { get; set; }
/// <summary>
@@ -87,6 +96,7 @@ namespace PocketSharp.Models
/// <value>
/// The count.
/// </value>
[DataMember(Name = "count")]
public int? Count { get; set; }
/// <summary>
@@ -95,37 +105,24 @@ namespace PocketSharp.Models
/// <value>
/// The offset.
/// </value>
[DataMember(Name = "offset")]
public int? Offset { get; set; }
/// <summary>
/// Converts this instance to a parameter list.
/// Gets or sets the version.
/// </summary>
/// <returns></returns>
public List<Parameter> Convert()
{
return new List<Parameter>()
{
Utilities.CreateParam("state", State != null ? State.ToString() : null ),
Utilities.CreateParam("favorite", Favorite != null ? (bool)Favorite ? "1" : "0" : null),
Utilities.CreateParam("tag", Tag),
Utilities.CreateParam("contentType", ContentType != null ? ContentType.ToString() : null),
Utilities.CreateParam("sort", Sort != null ? Sort.ToString() : null),
Utilities.CreateParam("detailType", DetailType != null ? DetailType.ToString() : null),
Utilities.CreateParam("search", Search),
Utilities.CreateParam("domain", Domain),
Utilities.CreateParam("since", Utilities.GetUnixTimestamp(Since)),
Utilities.CreateParam("count", Count),
Utilities.CreateParam("offset", Offset)
};
}
/// <value>
/// The version.
/// </value>
[DataMember(Name = "version")]
public int? Version { get; set; }
}
/// <summary>
/// Item states
/// </summary>
public enum StateEnum
public enum State
{
/// <summary>
/// Only unread items
@@ -144,7 +141,7 @@ namespace PocketSharp.Models
/// <summary>
/// Sorting
/// </summary>
public enum SortEnum
public enum Sort
{
/// <summary>
/// Newest first
@@ -167,7 +164,7 @@ namespace PocketSharp.Models
/// <summary>
/// Item types
/// </summary>
public enum ContentTypeEnum
public enum ContentType
{
/// <summary>
/// Articles
@@ -186,7 +183,7 @@ namespace PocketSharp.Models
/// <summary>
/// Item data
/// </summary>
public enum DetailTypeEnum
public enum DetailType
{
/// <summary>
/// Necessary data
+140
View File
@@ -0,0 +1,140 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace PocketSharp.Models
{
/// <summary>
/// All parameters which can be passed for a send action
/// </summary>
[DataContract]
public class PocketAction
{
/// <summary>
/// Gets or sets the action.
/// </summary>
/// <value>
/// The action.
/// </value>
[DataMember(Name = "action")]
public string Action { get; set; }
/// <summary>
/// Gets or sets the PocketItem ID.
/// </summary>
/// <value>
/// The ID.
/// </value>
[DataMember(Name = "item_id")]
public string ID { get; set; }
/// <summary>
/// Gets or sets the URI (for adding a new item).
/// </summary>
/// <value>
/// The URI.
/// </value>
[DataMember(Name = "url")]
public Uri Uri { get; set; }
/// <summary>
/// Gets or sets the Title (for adding a new item).
/// </summary>
/// <value>
/// The Title.
/// </value>
[DataMember(Name = "title")]
public string Title { get; set; }
/// <summary>
/// Gets or sets the associated Tweet ID.
/// </summary>
/// <value>
/// The Tweet ID.
/// </value>
[DataMember(Name = "ref_id")]
public string TweetID { get; set; }
/// <summary>
/// Gets or sets the time.
/// </summary>
/// <value>
/// The time.
/// </value>
[DataMember(Name = "time")]
public DateTime? Time { get; set; }
// specific params
/// <summary>
/// Gets or sets the tags.
/// </summary>
/// <value>
/// The tags.
/// </value>
[DataMember(Name = "tags")]
public string[] Tags { get; set; }
/// <summary>
/// Gets or sets the old tag.
/// </summary>
/// <value>
/// The old tag.
/// </value>
[DataMember(Name = "old_tag")]
public string OldTag { get; set; }
/// <summary>
/// Gets or sets the new tag.
/// </summary>
/// <value>
/// The new tag.
/// </value>
[DataMember(Name = "new_tag")]
public string NewTag { get; set; }
/// <summary>
/// Gets or sets the tag.
/// </summary>
/// <value>
/// The old tag.
/// </value>
[DataMember(Name = "tag")]
public string Tag { get; set; }
/// <summary>
/// Converts this instance to a parameter list.
/// </summary>
/// <returns></returns>
internal Dictionary<string, object> Convert()
{
Dictionary<string, object> parameters = new Dictionary<string, object>
{
{ "action", Action }
};
if (!String.IsNullOrEmpty(ID) && ID != "0")
parameters.Add("item_id", ID.ToString());
if (Time != null)
parameters.Add("time", Time != null ? Utilities.GetUnixTimestamp(Time).ToString() : null);
if (Tags != null)
parameters.Add("tags", Tags);
if (OldTag != null)
parameters.Add("old_tag", OldTag);
if (NewTag != null)
parameters.Add("new_tag", NewTag);
if (Tag != null)
parameters.Add("tag", Tag);
if (!String.IsNullOrEmpty(Title))
parameters.Add("title", Title);
if (!String.IsNullOrEmpty(TweetID))
parameters.Add("ref_id", TweetID);
if (Uri != null)
parameters.Add("url", Uri.OriginalString);
return parameters;
}
}
}
+160
View File
@@ -0,0 +1,160 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace PocketSharp.Models
{
/// <summary>
/// Article
/// </summary>
[JsonObject]
public class PocketArticle
{
/// <summary>
/// Gets or sets the response Code (200 = OK).
/// </summary>
/// <value>
/// The response Code.
/// </value>
[JsonProperty("responseCode")]
public string ResponseCode { get; set; }
/// <summary>
/// Gets or sets the ID.
/// </summary>
/// <value>
/// The ID.
/// </value>
[JsonProperty("resolved_id")]
public string ID { get; set; }
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// The URI.
/// </value>
[JsonProperty("resolvedUrl")]
public Uri Uri { get; set; }
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// The URI.
/// </value>
[JsonProperty("timePublished")]
public DateTime? PublishedTime { get; set; }
/// <summary>
/// Gets or sets the word count.
/// </summary>
/// <value>
/// The word count.
/// </value>
[JsonProperty("wordCount")]
public int WordCount { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is article.
/// </summary>
/// <value>
/// <c>true</c> if this instance is article; otherwise, <c>false</c>.
/// </value>
[JsonProperty("isArticle")]
public bool IsArticle { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is video.
/// </summary>
/// <value>
/// <c>true</c> if this instance is video; otherwise, <c>false</c>.
/// </value>
[JsonProperty("isVideo")]
public bool IsVideo { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is index.
/// </summary>
/// <value>
/// <c>true</c> if this instance is index; otherwise, <c>false</c>.
/// </value>
[JsonProperty("isIndex")]
public bool IsIndex { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance used fallback.
/// </summary>
/// <value>
/// <c>true</c> if this instance used fallback; otherwise, <c>false</c>.
/// </value>
[JsonProperty("usedFallback")]
public bool UsedFallback { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance requires login.
/// </summary>
/// <value>
/// <c>true</c> if this instance requires login; otherwise, <c>false</c>.
/// </value>
[JsonProperty("requiresLogin")]
public bool RequiresLogin { get; set; }
/// <summary>
/// Gets or sets the images.
/// </summary>
/// <value>
/// The images.
/// </value>
[JsonProperty("images")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketImage>))]
public IEnumerable<PocketImage> Images { get; set; }
/// <summary>
/// Gets or sets the videos.
/// </summary>
/// <value>
/// The videos.
/// </value>
[JsonProperty("videos")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketVideo>))]
public IEnumerable<PocketVideo> Videos { get; set; }
/// <summary>
/// Gets or sets the authors.
/// </summary>
/// <value>
/// The authors.
/// </value>
[JsonProperty("authors")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketAuthor>))]
public IEnumerable<PocketAuthor> Authors { get; set; }
/// <summary>
/// Gets or sets the article title.
/// </summary>
/// <value>
/// The Title.
/// </value>
[JsonProperty("title")]
public string Title { get; set; }
/// <summary>
/// Gets or sets the Excerpt.
/// </summary>
/// <value>
/// The Excerpt.
/// </value>
[JsonProperty("excerpt")]
public string Excerpt { get; set; }
/// <summary>
/// Gets or sets the Content.
/// </summary>
/// <value>
/// The Content.
/// </value>
[JsonProperty("article")]
public string Content { get; set; }
}
}
+6 -6
View File
@@ -1,12 +1,12 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using System;
namespace PocketSharp.Models
{
/// <summary>
/// Author
/// </summary>
[DataContract]
[JsonObject]
public class PocketAuthor
{
/// <summary>
@@ -15,7 +15,7 @@ namespace PocketSharp.Models
/// <value>
/// The ID.
/// </value>
[DataMember(Name = "author_id")]
[JsonProperty("author_id")]
public string ID { get; set; }
/// <summary>
@@ -24,7 +24,7 @@ namespace PocketSharp.Models
/// <value>
/// The name.
/// </value>
[DataMember]
[JsonProperty]
public string Name { get; set; }
/// <summary>
@@ -33,7 +33,7 @@ namespace PocketSharp.Models
/// <value>
/// The URI.
/// </value>
[DataMember(Name = "url")]
[JsonProperty("url")]
public Uri Uri { get; set; }
}
}
+9
View File
@@ -0,0 +1,9 @@
namespace PocketSharp.Models
{
internal enum PocketBoolean
{
No = 0,
Yes = 1,
IsType = 2
}
}
+203
View File
@@ -0,0 +1,203 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace PocketSharp.Models
{
/// <summary>
/// Explore item containing all available data
/// </summary>
[JsonObject]
[DebuggerDisplay("Uri = {Uri}, Title = {Title}")]
public class PocketExploreItem : IComparable
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
/// <value>
/// The ID.
/// </value>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>
/// The title.
/// </value>
public string Title { get; set; }
/// <summary>
/// Gets or sets the excerpt.
/// </summary>
/// <value>
/// The excerpt.
/// </value>
public string Excerpt { get; set; }
/// <summary>
/// Gets or sets the published time.
/// </summary>
/// <value>
/// The time when the article was published.
/// </value>
public DateTime? PublishedTime { get; set; }
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// The URI.
/// </value>
[JsonIgnore]
public Uri Uri { get; set; }
/// <summary>
/// Gets or sets the save count.
/// </summary>
/// <value>
/// The save count.
/// </value>
public int SaveCount { get; set; }
/// <summary>
/// Gets or sets the images.
/// </summary>
/// <value>
/// The images.
/// </value>
[JsonConverter(typeof(ObjectToArrayConverter<PocketImage>))]
public IEnumerable<PocketImage> Images { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is trending.
/// </summary>
/// <value>
/// <c>true</c> if this instance is trending; otherwise, <c>false</c>.
/// </value>
public bool IsTrending { get; set; }
/// <summary>
/// Gets the lead image.
/// </summary>
/// <value>
/// The lead image.
/// </value>
[JsonIgnore]
public PocketImage LeadImage
{
get { return Images != null && Images.Count() > 0 ? Images.First() : null; }
}
/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary>
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>
/// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="obj" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="obj" />. Greater than zero This instance follows <paramref name="obj" /> in the sort order.
/// </returns>
int IComparable.CompareTo(object obj)
{
PocketExploreItem item = (PocketExploreItem)obj;
if (!PublishedTime.HasValue)
{
return 1;
}
if (!item.PublishedTime.HasValue)
{
return -1;
}
return DateTime.Compare(PublishedTime.Value, item.PublishedTime.Value);
}
/// <summary>
/// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
PocketExploreItem item = obj as PocketExploreItem;
if (item == null)
{
return false;
}
return ID == item.ID;
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="a">A.</param>
/// <param name="b">The b.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==(PocketExploreItem a, PocketExploreItem b)
{
if (Object.ReferenceEquals(a, b))
{
return true;
}
PocketExploreItem itemA = (PocketExploreItem)a;
PocketExploreItem itemB = (PocketExploreItem)b;
if ((Object)itemA == null || (Object)itemB == null)
{
return false;
}
return itemA.ID == itemB.ID;
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="a">A.</param>
/// <param name="b">The b.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=(PocketExploreItem a, PocketExploreItem b)
{
return !(a == b);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return ID.GetHashCode();
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
return ID;
}
}
}
+16 -7
View File
@@ -1,12 +1,12 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using System;
namespace PocketSharp.Models
{
/// <summary>
/// Image
/// </summary>
[DataContract]
[JsonObject]
public class PocketImage
{
/// <summary>
@@ -15,16 +15,25 @@ namespace PocketSharp.Models
/// <value>
/// The ID.
/// </value>
[DataMember(Name = "image_id")]
[JsonProperty("image_id")]
public string ID { get; set; }
/// <summary>
/// Gets or sets the Item ID.
/// </summary>
/// <value>
/// The Item ID.
/// </value>
[JsonProperty("item_id")]
public string ItemID { get; set; }
/// <summary>
/// Gets or sets the caption.
/// </summary>
/// <value>
/// The caption.
/// </value>
[DataMember]
[JsonProperty]
public string Caption { get; set; }
/// <summary>
@@ -33,7 +42,7 @@ namespace PocketSharp.Models
/// <value>
/// The credit.
/// </value>
[DataMember]
[JsonProperty]
public string Credit { get; set; }
/// <summary>
@@ -42,7 +51,7 @@ namespace PocketSharp.Models
/// <value>
/// The URI.
/// </value>
[DataMember(Name = "src")]
[JsonProperty("src")]
public Uri Uri { get; set; }
}
}
+304 -86
View File
@@ -1,6 +1,8 @@
using System;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Diagnostics;
using System.Linq;
namespace PocketSharp.Models
{
@@ -8,8 +10,9 @@ namespace PocketSharp.Models
/// Item containing all available data
/// see: http://getpocket.com/developer/docs/v3/retrieve
/// </summary>
[DataContract]
public class PocketItem
[JsonObject]
[DebuggerDisplay("Uri = {Uri}, Title = {Title}")]
public class PocketItem : IComparable
{
/// <summary>
/// Gets or sets the ID.
@@ -17,8 +20,44 @@ namespace PocketSharp.Models
/// <value>
/// The ID.
/// </value>
[DataMember(Name = "item_id")]
public int ID { get; set; }
[JsonProperty("item_id")]
public string ID { get; set; }
/// <summary>
/// Gets or sets the resolved identifier.
/// </summary>
/// <value>
/// The resolved identifier.
/// </value>
[JsonProperty("resolved_id")]
public string ResolvedId { get; set; }
/// <summary>
/// Gets or sets the normal URI.
/// </summary>
/// <value>
/// The normal URI.
/// </value>
[JsonProperty("normal_url")]
private Uri _NormalUri { get; set; }
/// <summary>
/// Gets or sets the given URI.
/// </summary>
/// <value>
/// The given URI.
/// </value>
[JsonProperty("given_url")]
private Uri _GivenUri { get; set; }
/// <summary>
/// Gets or sets the resolved URI.
/// </summary>
/// <value>
/// The resolved URI.
/// </value>
[JsonProperty("resolved_url")]
private Uri _ResolvedUri { get; set; }
/// <summary>
/// Gets or sets the URI.
@@ -26,8 +65,12 @@ namespace PocketSharp.Models
/// <value>
/// The URI.
/// </value>
[DataMember(Name = "resolved_url")]
public Uri Uri { get; set; }
[JsonIgnore]
public Uri Uri
{
get { return _ResolvedUri ?? _GivenUri ?? _NormalUri; }
set { _NormalUri = value; _ResolvedUri = value; _GivenUri = value; }
}
/// <summary>
/// Gets or sets the title.
@@ -35,8 +78,30 @@ namespace PocketSharp.Models
/// <value>
/// The title.
/// </value>
[DataMember(Name = "resolved_title")]
public string Title { get; set; }
[JsonProperty("resolved_title")]
private string _ResolvedTitle { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>
/// The title.
/// </value>
[JsonProperty("title")]
private string _InternalTitle { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>
/// The title.
/// </value>
[JsonIgnore]
public string Title
{
get { return _InternalTitle ?? _ResolvedTitle ?? FullTitle; }
set { _InternalTitle = value; _ResolvedTitle = value; }
}
/// <summary>
/// Gets or sets the full title.
@@ -44,7 +109,7 @@ namespace PocketSharp.Models
/// <value>
/// The full title.
/// </value>
[DataMember(Name = "given_title")]
[JsonProperty("given_title")]
public string FullTitle { get; set; }
/// <summary>
@@ -53,7 +118,7 @@ namespace PocketSharp.Models
/// <value>
/// The excerpt.
/// </value>
[DataMember]
[JsonProperty]
public string Excerpt { get; set; }
/// <summary>
@@ -62,7 +127,7 @@ namespace PocketSharp.Models
/// <value>
/// The status.
/// </value>
[DataMember]
[JsonProperty]
public int Status { get; set; }
/// <summary>
@@ -71,7 +136,7 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if this instance is favorite; otherwise, <c>false</c>.
/// </value>
[DataMember(Name = "favorite")]
[JsonProperty("favorite")]
public bool IsFavorite { get; set; }
/// <summary>
@@ -80,7 +145,7 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if this instance is archive; otherwise, <c>false</c>.
/// </value>
[IgnoreDataMember]
[JsonIgnore]
public bool IsArchive { get { return Status == 1; } }
/// <summary>
@@ -89,7 +154,7 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if this instance is deleted; otherwise, <c>false</c>.
/// </value>
[IgnoreDataMember]
[JsonIgnore]
public bool IsDeleted { get { return Status == 2; } }
/// <summary>
@@ -98,7 +163,7 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if this instance is article; otherwise, <c>false</c>.
/// </value>
[DataMember(Name = "is_article")]
[JsonProperty("is_article")]
public bool IsArticle { get; set; }
/// <summary>
@@ -107,8 +172,8 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if this instance has image; otherwise, <c>false</c>.
/// </value>
[DataMember(Name = "has_image")]
public bool HasImage { get; set; }
[JsonProperty("has_image")]
private PocketBoolean? _HasImage { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance has video.
@@ -116,8 +181,68 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if this instance has video; otherwise, <c>false</c>.
/// </value>
[DataMember(Name = "has_video")]
public bool HasVideo { get; set; }
[JsonProperty("has_video")]
private PocketBoolean? _HasVideo { get; set; }
/// <summary>
/// Gets a value indicating whether [has image].
/// </summary>
/// <value>
/// <c>true</c> if [has image]; otherwise, <c>false</c>.
/// </value>
[JsonIgnore]
public bool HasImage
{
get
{
return _HasImage == PocketBoolean.Yes || _HasImage == PocketBoolean.IsType;
}
}
/// <summary>
/// Gets a value indicating whether [has video].
/// </summary>
/// <value>
/// <c>true</c> if [has video]; otherwise, <c>false</c>.
/// </value>
[JsonIgnore]
public bool HasVideo
{
get
{
return _HasVideo == PocketBoolean.Yes || _HasVideo == PocketBoolean.IsType;
}
}
/// <summary>
/// Gets a value indicating whether [is video].
/// </summary>
/// <value>
/// <c>true</c> if [is video]; otherwise, <c>false</c>.
/// </value>
[JsonIgnore]
public bool IsVideo
{
get
{
return _HasVideo == PocketBoolean.IsType;
}
}
/// <summary>
/// Gets a value indicating whether [is image].
/// </summary>
/// <value>
/// <c>true</c> if [is image]; otherwise, <c>false</c>.
/// </value>
[JsonIgnore]
public bool IsImage
{
get
{
return _HasImage == PocketBoolean.IsType;
}
}
/// <summary>
/// Gets or sets the word count.
@@ -125,7 +250,7 @@ namespace PocketSharp.Models
/// <value>
/// The word count.
/// </value>
[DataMember(Name = "word_count")]
[JsonProperty("word_count")]
public int WordCount { get; set; }
/// <summary>
@@ -134,7 +259,7 @@ namespace PocketSharp.Models
/// <value>
/// The sort.
/// </value>
[DataMember(Name = "sort_id")]
[JsonProperty("sort_id")]
public int Sort { get; set; }
@@ -144,7 +269,7 @@ namespace PocketSharp.Models
/// <value>
/// The add time.
/// </value>
[DataMember(Name = "time_added")]
[JsonProperty("time_added")]
public DateTime? AddTime { get; set; }
/// <summary>
@@ -153,7 +278,7 @@ namespace PocketSharp.Models
/// <value>
/// The update time.
/// </value>
[DataMember(Name = "time_updated")]
[JsonProperty("time_updated")]
public DateTime? UpdateTime { get; set; }
/// <summary>
@@ -162,7 +287,7 @@ namespace PocketSharp.Models
/// <value>
/// The read time.
/// </value>
[DataMember(Name = "time_read")]
[JsonProperty("time_read")]
public DateTime? ReadTime { get; set; }
/// <summary>
@@ -171,70 +296,78 @@ namespace PocketSharp.Models
/// <value>
/// The favorite time.
/// </value>
[DataMember(Name = "time_favorited")]
[JsonProperty("time_favorited")]
public DateTime? FavoriteTime { get; set; }
/// <summary>
/// Gets or sets the _ tag dictionary.
/// Gets or sets the published time.
/// </summary>
/// <value>
/// The _ tag dictionary.
/// The time when the article was published.
/// </value>
[DataMember(Name = "tags")]
public Dictionary<string, PocketTag> _TagDictionary { get; set; }
[JsonProperty("date_published")]
public DateTime? PublishedTime { get; set; }
/// <summary>
/// Gets or sets the _ image dictionary.
/// </summary>
/// <value>
/// The _ image dictionary.
/// </value>
[DataMember(Name = "images")]
public Dictionary<string, PocketImage> _ImageDictionary { get; set; }
/// <summary>
/// Gets or sets the _ video dictionary.
/// </summary>
/// <value>
/// The _ video dictionary.
/// </value>
[DataMember(Name = "videos")]
public Dictionary<string, PocketVideo> _VideoDictionary { get; set; }
/// <summary>
/// Gets or sets the _ author dictionary.
/// </summary>
/// <value>
/// The _ author dictionary.
/// </value>
[DataMember(Name = "authors")]
public Dictionary<string, PocketAuthor> _AuthorDictionary { get; set; }
/// <summary>
/// Gets the tags.
/// Gets or sets the tags as comma-separated strings.
/// </summary>
/// <value>
/// The tags.
/// </value>
[IgnoreDataMember]
public List<PocketTag> Tags
[JsonIgnore]
public string TagsString
{
get { return Utilities.DictionaryToList<PocketTag>(_TagDictionary); }
get { return Tags != null ? String.Join(",", Tags.Select(tag => tag.Name)) : ""; }
}
/// <summary>
/// Gets the images.
/// Gets or sets the tags.
/// </summary>
/// <value>
/// The tags.
/// </value>
[JsonProperty("tags")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketTag>))]
public IEnumerable<PocketTag> Tags { get; set; }
/// <summary>
/// Gets or sets the images.
/// </summary>
/// <value>
/// The images.
/// </value>
[IgnoreDataMember]
public List<PocketImage> Images
{
get { return Utilities.DictionaryToList<PocketImage>(_ImageDictionary); }
}
[JsonProperty("images")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketImage>))]
public IEnumerable<PocketImage> Images { get; set; }
/// <summary>
/// Gets or sets the videos.
/// </summary>
/// <value>
/// The videos.
/// </value>
[JsonProperty("videos")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketVideo>))]
public IEnumerable<PocketVideo> Videos { get; set; }
/// <summary>
/// Gets or sets the authors.
/// </summary>
/// <value>
/// The authors.
/// </value>
[JsonProperty("authors")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketAuthor>))]
public IEnumerable<PocketAuthor> Authors { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is trending.
/// </summary>
/// <value>
/// <c>true</c> if this instance is trending; otherwise, <c>false</c>.
/// </value>
[JsonProperty("trending")]
public bool IsTrending { get; set; }
/// <summary>
/// Gets the lead image.
@@ -242,34 +375,119 @@ namespace PocketSharp.Models
/// <value>
/// The lead image.
/// </value>
[IgnoreDataMember]
[JsonIgnore]
public PocketImage LeadImage
{
get { return Images != null ? Images[0] : null; }
get { return Images != null && Images.Count() > 0 ? Images.First() : null; }
}
/// <summary>
/// Gets the videos.
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary>
/// <value>
/// The videos.
/// </value>
[IgnoreDataMember]
public List<PocketVideo> Videos
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>
/// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="obj" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="obj" />. Greater than zero This instance follows <paramref name="obj" /> in the sort order.
/// </returns>
int IComparable.CompareTo(object obj)
{
get { return Utilities.DictionaryToList<PocketVideo>(_VideoDictionary); }
PocketItem item = (PocketItem)obj;
if (!AddTime.HasValue)
{
return 1;
}
if (!item.AddTime.HasValue)
{
return -1;
}
return DateTime.Compare(AddTime.Value, item.AddTime.Value);
}
/// <summary>
/// Gets the authors.
/// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
/// </summary>
/// <value>
/// The authors.
/// </value>
[IgnoreDataMember]
public List<PocketAuthor> Authors
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
get { return Utilities.DictionaryToList<PocketAuthor>(_AuthorDictionary); }
if (obj == null)
{
return false;
}
PocketItem item = obj as PocketItem;
if (item == null)
{
return false;
}
return ID == item.ID;
}
/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="a">A.</param>
/// <param name="b">The b.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==(PocketItem a, PocketItem b)
{
if (Object.ReferenceEquals(a, b))
{
return true;
}
PocketItem itemA = (PocketItem)a;
PocketItem itemB = (PocketItem)b;
if ((Object)itemA == null || (Object)itemB == null)
{
return false;
}
return itemA.ID == itemB.ID;
}
/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="a">A.</param>
/// <param name="b">The b.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=(PocketItem a, PocketItem b)
{
return !(a == b);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
return ID.GetHashCode();
}
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
return ID;
}
}
}
+65
View File
@@ -0,0 +1,65 @@
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// API Limitation Statistics
/// </summary>
[JsonObject]
public class PocketLimits
{
/// <summary>
/// Gets or sets the rate limit.
/// </summary>
/// <value>
/// Rate limit for current consumer key.
/// </value>
[JsonProperty("X-Limit-Key-Limit")]
public int RateLimitForConsumerKey { get; set; }
/// <summary>
/// Gets or sets the remaining calls.
/// </summary>
/// <value>
/// Remaining calls for current consumer key.
/// </value>
[JsonProperty("X-Limit-Key-Remaining")]
public int RemainingCallsForConsumerKey { get; set; }
/// <summary>
/// Gets or sets the reset seconds.
/// </summary>
/// <value>
/// Seconds until limit resets for current consumer key.
/// </value>
[JsonProperty("X-Limit-Key-Reset")]
public int SecondsUntilLimitResetsForConsumerKey { get; set; }
/// <summary>
/// Gets or sets the rate limit.
/// </summary>
/// <value>
/// Rate limit for current user.
/// </value>
[JsonProperty("X-Limit-User-Limit")]
public int RateLimitForUser { get; set; }
/// <summary>
/// Gets or sets the remaining calls.
/// </summary>
/// <value>
/// Remaining calls for current user.
/// </value>
[JsonProperty("X-Limit-User-Remaining")]
public int RemainingCallsForUser { get; set; }
/// <summary>
/// Gets or sets the reset seconds.
/// </summary>
/// <value>
/// Seconds until limit resets for current user.
/// </value>
[JsonProperty("X-Limit-User-Reset")]
public int SecondsUntilLimitResetsForUser { get; set; }
}
}
+38
View File
@@ -0,0 +1,38 @@
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Statistics
/// </summary>
[JsonObject]
public class PocketStatistics
{
/// <summary>
/// Gets or sets all items.
/// </summary>
/// <value>
/// All items count.
/// </value>
[JsonProperty("count_list")]
public int CountAll { get; set; }
/// <summary>
/// Gets or sets all read items.
/// </summary>
/// <value>
/// Read items count.
/// </value>
[JsonProperty("count_read")]
public int CountRead { get; set; }
/// <summary>
/// Gets or sets all unread items.
/// </summary>
/// <value>
/// Unread items count.
/// </value>
[JsonProperty("count_unread")]
public int CountUnread { get; set; }
}
}
+12 -3
View File
@@ -1,11 +1,11 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Tag
/// </summary>
[DataContract]
[JsonObject]
public class PocketTag
{
/// <summary>
@@ -14,7 +14,16 @@ namespace PocketSharp.Models
/// <value>
/// The name.
/// </value>
[DataMember(Name = "tag")]
[JsonProperty("tag")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the item iD.
/// </summary>
/// <value>
/// The name.
/// </value>
[JsonProperty("item_id")]
public string ItemID { get; set; }
}
}
+39
View File
@@ -0,0 +1,39 @@
using Newtonsoft.Json;
using System;
namespace PocketSharp.Models
{
/// <summary>
/// Topic
/// </summary>
[JsonObject]
public class PocketTopic
{
/// <summary>
/// Gets or sets the category.
/// </summary>
/// <value>
/// The topic category.
/// </value>
[JsonProperty("category")]
public string Category { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name of the topic.
/// </value>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// Link to the topic listing on Pocket.
/// </value>
[JsonProperty("url")]
public Uri Uri { get; set; }
}
}
+67
View File
@@ -0,0 +1,67 @@
using Newtonsoft.Json;
using System;
namespace PocketSharp.Models
{
/// <summary>
/// Access Code
/// </summary>
[JsonObject]
public class PocketUser
{
/// <summary>
/// Pocket user id.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The access code.
/// </summary>
public string Code { get; set; }
/// <summary>
/// Pocket username.
/// </summary>
public string Username { get; set; }
/// <summary>
/// Email address.
/// </summary>
public string Email { get; set; }
/// <summary>
/// First name.
/// </summary>
public string FirstName { get; set; }
/// <summary>
/// Last name.
/// </summary>
public string LastName { get; set; }
/// <summary>
/// Profile avatar.
/// </summary>
public Uri Avatar { get; set; }
/// <summary>
/// Is default avatar.
/// </summary>
public bool IsDefaultAvatar { get; set; } = true;
/// <summary>
/// Follower count.
/// </summary>
public int Followers { get; set; }
/// <summary>
/// Follow count.
/// </summary>
public int Follows { get; set; }
/// <summary>
/// Profile text.
/// </summary>
public string Description { get; set; }
}
}
+25 -6
View File
@@ -1,12 +1,12 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using System;
namespace PocketSharp.Models
{
/// <summary>
/// Video
/// </summary>
[DataContract]
[JsonObject]
public class PocketVideo
{
/// <summary>
@@ -15,16 +15,25 @@ namespace PocketSharp.Models
/// <value>
/// The ID.
/// </value>
[DataMember(Name = "video_id")]
[JsonProperty("video_id")]
public string ID { get; set; }
/// <summary>
/// Gets or sets the Item ID.
/// </summary>
/// <value>
/// The Item ID.
/// </value>
[JsonProperty("item_id")]
public string ItemID { get; set; }
/// <summary>
/// Gets or sets the external ID.
/// </summary>
/// <value>
/// The external ID.
/// </value>
[DataMember(Name = "vid")]
[JsonProperty("vid")]
public string ExternalID { get; set; }
/// <summary>
@@ -33,7 +42,17 @@ namespace PocketSharp.Models
/// <value>
/// The URI.
/// </value>
[DataMember(Name = "src")]
[JsonProperty("src")]
public Uri Uri { get; set; }
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// The URI.
/// </value>
[JsonProperty("type")]
[JsonConverter(typeof(VideoTypeConverter))]
public PocketVideoType Type { get; set; }
}
}
+11
View File
@@ -0,0 +1,11 @@
namespace PocketSharp.Models
{
public enum PocketVideoType
{
Unknown = 7,
YouTube = 1,
Vimeo = 2,
HTML = 5,
Flash = 6
}
}
+3 -3
View File
@@ -1,11 +1,11 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Add Response
/// </summary>
[DataContract]
[JsonObject]
internal class Add : ResponseBase
{
/// <summary>
@@ -14,7 +14,7 @@ namespace PocketSharp.Models
/// <value>
/// The item.
/// </value>
[DataMember]
[JsonProperty]
public PocketItem Item { get; set; }
}
}
+49
View File
@@ -0,0 +1,49 @@
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Response from the GetUser() method
/// </summary>
[JsonObject]
internal class GetUserResponse
{
public string Access_token { get; set; }
public string Username { get; set; }
public GetUserAccountResponse Account { get; set; }
}
[JsonObject]
internal class GetUserAccountResponse
{
public string Email { get; set; }
public string First_name { get; set; }
public string Last_name { get; set; }
public string User_id { get; set; }
//public bool Premium_on_trial { get; set; }
//public bool Premium_status { get; set; }
public GetUserAccountProfileResponse Profile { get; set; }
}
[JsonObject]
internal class GetUserAccountProfileResponse
{
public string Avatar_url { get; set; }
public int Follow_count { get; set; }
public int Follower_count { get; set; }
public string Description { get; set; }
}
}
+20
View File
@@ -0,0 +1,20 @@
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Guid
/// </summary>
[JsonObject]
internal class GuidResponse
{
/// <summary>
/// Gets or sets the GUID.
/// </summary>
/// <value>
/// The GUID.
/// </value>
[JsonProperty]
public string Guid { get; set; }
}
}
+4 -4
View File
@@ -1,11 +1,11 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Modify Response
/// </summary>
[DataContract]
[JsonObject]
internal class Modify : ResponseBase
{
/// <summary>
@@ -14,7 +14,7 @@ namespace PocketSharp.Models
/// <value>
/// The action results.
/// </value>
[DataMember(Name = "action_results")]
public bool[] ActionResults { get; set; }
//[JsonProperty("action_results")]
//public bool[] ActionResults { get; set; }
}
}
@@ -1,11 +1,11 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace PocketSharp.Models.Authentification
namespace PocketSharp.Models
{
/// <summary>
/// Request Code
/// </summary>
[DataContract]
[JsonObject]
internal class RequestCode
{
/// <summary>
@@ -14,7 +14,7 @@ namespace PocketSharp.Models.Authentification
/// <value>
/// The code.
/// </value>
[DataMember]
[JsonProperty]
public string Code { get; set; }
/// <summary>
@@ -23,7 +23,7 @@ namespace PocketSharp.Models.Authentification
/// <value>
/// The state.
/// </value>
[DataMember]
[JsonProperty]
public string State { get; set; }
}
}
+3 -3
View File
@@ -1,11 +1,11 @@
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace PocketSharp.Models
{
/// <summary>
/// Base for Responses
/// </summary>
[DataContract]
[JsonObject]
internal class ResponseBase
{
/// <summary>
@@ -14,7 +14,7 @@ namespace PocketSharp.Models
/// <value>
/// <c>true</c> if status is OK; otherwise, <c>false</c>.
/// </value>
[DataMember(Name = "status")]
[JsonProperty("status")]
public bool Status { get; set; }
}
}
+10 -20
View File
@@ -1,12 +1,13 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace PocketSharp.Models
{
/// <summary>
/// Item Response
/// </summary>
[DataContract]
[JsonObject]
internal class Retrieve : ResponseBase
{
/// <summary>
@@ -15,7 +16,7 @@ namespace PocketSharp.Models
/// <value>
/// The complete.
/// </value>
[DataMember(Name = "complete")]
[JsonProperty("complete")]
public int Complete { get; set; }
/// <summary>
@@ -24,17 +25,8 @@ namespace PocketSharp.Models
/// <value>
/// The since.
/// </value>
[DataMember]
public int Since { get; set; }
/// <summary>
/// Gets or sets the _ item dictionary.
/// </summary>
/// <value>
/// The _ item dictionary.
/// </value>
[DataMember(Name = "list")]
public Dictionary<string, PocketItem> _ItemDictionary { get; set; }
[JsonProperty("since")]
public DateTime Since { get; set; }
/// <summary>
/// Gets the items.
@@ -42,10 +34,8 @@ namespace PocketSharp.Models
/// <value>
/// The items.
/// </value>
[IgnoreDataMember]
public List<PocketItem> Items
{
get { return Utilities.DictionaryToList<PocketItem>(_ItemDictionary); }
}
[JsonProperty("list")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketItem>))]
public IEnumerable<PocketItem> Items { get; set; }
}
}
+22
View File
@@ -0,0 +1,22 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace PocketSharp.Models
{
/// <summary>
/// Topics Response
/// </summary>
[JsonObject]
internal class TopicsResponse : ResponseBase
{
/// <summary>
/// Gets the topics.
/// </summary>
/// <value>
/// The topics.
/// </value>
[JsonProperty("topics")]
public IEnumerable<PocketTopic> Items { get; set; }
}
}
+378 -114
View File
@@ -1,69 +1,148 @@
using PocketSharp.Models;
using RestSharp;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
public partial class PocketClient : IPocketClient, IDisposable
{
/// <summary>
/// REST client used for the API communication
/// </summary>
protected readonly RestClient _restClient;
protected readonly HttpClient httpClient;
/// <summary>
/// Caches HTTP headers from last response
/// </summary>
public HttpResponseHeaders lastHeaders;
/// <summary>
/// Caches JSON data from last response
/// </summary>
public string lastResponseData;
/// <summary>
/// The base URL for the Pocket API
/// </summary>
protected static Uri baseUri = new Uri("https://getpocket.com/v3/");
protected static string baseUri = "https://getpocket.com/v3/";
/// <summary>
/// The base URL for Pocket reader requests
/// </summary>
protected static string parserUri = null;
/// <summary>
/// The authentification URL
/// </summary>
protected string authentificationUri = "https://getpocket.com/auth/authorize?request_token={0}&redirect_uri={1}";
protected string authentificationUri = "https://getpocket.com/auth/authorize?request_token={0}&redirect_uri={1}&mobile={2}&force={3}&webauthenticationbroker={4}";
/// <summary>
/// callback URL for API calls
/// Indicates, whether this client is used for mobile or desktop
/// </summary>
protected Uri CallbackUri { get; set; }
protected bool isMobileClient = true;
/// <summary>
/// Indicates, whether this client is used inside a broker (on Windows 8)
/// </summary>
protected bool useInsideWebAuthenticationBroker = true;
/// <summary>
/// Indicates, whether the last HTTP response is cached
/// </summary>
protected bool cacheHTTPResponseData;
/// <summary>
/// callback URLi for API calls
/// </summary>
/// <value>
/// The callback URI.
/// </value>
public string CallbackUri { get; set; }
/// <summary>
/// Accessor for the Pocket API key
/// see: http://getpocket.com/developer
/// </summary>
/// <value>
/// The consumer key.
/// </value>
public string ConsumerKey { get; set; }
/// <summary>
/// Returns all associated data from the last request
/// </summary>
public IRestResponse LastRequestData { get; private set; }
/// <summary>
/// Code retrieved on authentification
/// </summary>
/// <value>
/// The request code.
/// </value>
public string RequestCode { get; set; }
/// <summary>
/// Code retrieved on authentification-success
/// </summary>
/// <value>
/// The access code.
/// </value>
public string AccessCode { get; set; }
/// <summary>
/// Action which is executed before every request
/// </summary>
/// <value>
/// The pre request callback.
/// </value>
public Action<string> PreRequest { get; set; }
/// <summary>
/// Action which is executed after every request
/// </summary>
/// <value>
/// The after request callback.
/// </value>
public Action<string> AfterRequest { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PocketClient"/> class.
/// Initializes a new instance of the <see cref="PocketClient" /> class.
/// </summary>
/// <param name="consumerKey">The API key</param>
/// <param name="accessCode">Provide an access code if the user is already authenticated</param>
/// <param name="callbackUri">The callback URL is called by Pocket after authentication</param>
public PocketClient(string consumerKey, string accessCode = null, Uri callbackUri = null)
/// <param name="handler">The HttpMessage handler.</param>
/// <param name="timeout">Request timeout (in seconds).</param>
/// <param name="isMobileClient">Indicates, whether this client is used for mobile or desktop</param>
/// <param name="useInsideWebAuthenticationBroker">Indicates, whether this client is used inside a broker (on Windows 8), see: http://getpocket.com/developer/docs/getstarted/windows8 </param>
/// <param name="parserUri">Enables the wrapper for the private Text Parser API</param>
/// <param name="cacheHTTPResponseData">Caches the last HTTP response in public properties</param>
public PocketClient(
string consumerKey,
string accessCode = null,
string callbackUri = null,
HttpMessageHandler handler = null,
int? timeout = null,
bool isMobileClient = true,
bool useInsideWebAuthenticationBroker = false,
Uri parserUri = null,
bool cacheHTTPResponseData = true)
{
// assign public properties
ConsumerKey = consumerKey;
this.isMobileClient = isMobileClient;
this.useInsideWebAuthenticationBroker = useInsideWebAuthenticationBroker;
this.cacheHTTPResponseData = cacheHTTPResponseData;
PocketClient.parserUri = parserUri?.OriginalString;
// assign access code if submitted
if (accessCode != null)
{
@@ -73,58 +152,22 @@ namespace PocketSharp
// assign callback uri if submitted
if (callbackUri != null)
{
CallbackUri = callbackUri;
CallbackUri = Uri.EscapeUriString(callbackUri.ToString());
}
// initialize REST client
_restClient = new RestClient(baseUri.ToString());
httpClient = new HttpClient(handler ?? new HttpClientHandler());
// add default parameters to each request
_restClient.AddDefaultParameter("consumer_key", ConsumerKey);
if (timeout.HasValue)
{
httpClient.Timeout = TimeSpan.FromSeconds(timeout.Value);
}
// Pocket needs this specific Accept header :-S
_restClient.AddDefaultHeader("Accept", "*/*");
httpClient.DefaultRequestHeaders.Add("Accept", "*/*");
// defines the response format (according to the Pocket docs)
_restClient.AddDefaultHeader("X-Accept", "application/json");
// custom JSON deserializer (ServiceStack.Text)
_restClient.AddHandler("application/json", new JsonDeserializer());
// add custom deserialization lambdas
JsonDeserializer.AddCustomDeserialization();
}
/// <summary>
/// Makes a HTTP REST request to the API
/// </summary>
/// <param name="request">The request.</param>
/// <returns></returns>
protected string Request(RestRequest request)
{
IRestResponse response = _restClient.Execute(request);
LastRequestData = response;
ValidateResponse(response);
return response.Content;
}
/// <summary>
/// Makes a typed HTTP REST request to the API
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="request">The request.</param>
/// <returns></returns>
protected T Request<T>(RestRequest request) where T : new()
{
IRestResponse<T> response = _restClient.Execute<T>(request);
LastRequestData = response;
ValidateResponse(response);
return response.Data;
httpClient.DefaultRequestHeaders.Add("X-Accept", "application/json");
}
@@ -133,53 +176,231 @@ namespace PocketSharp
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="method">Requested method (path after /v3/)</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="parameters">Additional POST parameters</param>
/// <param name="requireAuth">if set to <c>true</c> [require auth].</param>
/// <returns></returns>
/// <exception cref="APIException">No access token available. Use authentification first.</exception>
protected T Get<T>(string method, List<Parameter> parameters = null, bool requireAuth = false) where T : class, new()
/// <exception cref="PocketException">No access token available. Use authentification first.</exception>
protected async Task<T> Request<T>(
string method,
CancellationToken cancellationToken,
Dictionary<string, string> parameters = null,
bool requireAuth = true,
bool isReaderRequest = false) where T : class, new()
{
if (requireAuth && AccessCode == null)
{
throw new APIException("No access token available. Use authentification first.");
throw new PocketException("SDK error: No access token available. Use authentication first.");
}
string httpBase = isReaderRequest ? parserUri : baseUri;
if (isReaderRequest && String.IsNullOrEmpty(parserUri))
{
throw new PocketException("Please pass a valid parserUri in the PocketClient ctor.");
}
// every single Pocket API endpoint requires HTTP POST data
var request = new RestRequest(method, Method.POST);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, httpBase + method);
HttpResponseMessage response = null;
string responseString = null;
if (parameters == null)
{
parameters = new Dictionary<string, string>();
}
// add consumer key to each request
parameters.Add("consumer_key", ConsumerKey);
// add access token (necessary for all requests except authentification)
if (AccessCode != null)
if (AccessCode != null && requireAuth)
{
request.AddParameter("access_token", AccessCode);
parameters.Add("access_token", AccessCode);
}
// enumeration for params
if (parameters != null)
// content of the request
request.Content = new FormUrlEncodedContent(parameters);
// call pre request action
PreRequest?.Invoke(method);
// make async request
try
{
parameters.ForEach(delegate(Parameter param)
response = await httpClient.SendAsync(request, cancellationToken);
// validate HTTP response
ValidateResponse(response);
// cache headers
if (cacheHTTPResponseData)
{
request.AddParameter(param);
});
lastHeaders = response.Headers;
}
// read response
responseString = await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException exc)
{
throw new PocketException(exc.Message, exc);
}
catch (PocketException exc)
{
throw exc;
}
finally
{
request.Dispose();
if (response != null)
{
response.Dispose();
}
}
// do the request
return Request<T>(request);
// call after request action
AfterRequest?.Invoke(responseString);
// cache response
if (cacheHTTPResponseData)
{
lastResponseData = responseString;
}
return DeserializeJson<T>(responseString);
}
/// <summary>
/// Puts an action
/// Fetches a string from a resource
/// </summary>
/// <param name="uri">URI</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
protected async Task<string> RequestAsString(string uri, CancellationToken cancellationToken)
{
// every single Pocket API endpoint requires HTTP POST data
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, uri);
HttpResponseMessage response = null;
string responseString = null;
// call pre request action
PreRequest?.Invoke(uri);
// make async request
try
{
response = await httpClient.GetAsync(uri, cancellationToken);
// validate HTTP response
ValidateResponse(response);
// cache headers
if (cacheHTTPResponseData)
{
lastHeaders = response.Headers;
}
// read response
responseString = await response.Content.ReadAsStringAsync();
}
catch (HttpRequestException exc)
{
throw new PocketException(exc.Message, exc);
}
catch (PocketException exc)
{
throw exc;
}
finally
{
request.Dispose();
if (response != null)
{
response.Dispose();
}
}
// call after request action
AfterRequest?.Invoke(responseString);
// cache response
if (cacheHTTPResponseData)
{
lastResponseData = responseString;
}
return responseString;
}
/// <summary>
/// Converts JSON to Pocket objects
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="json">Raw JSON response</param>
/// <returns></returns>
/// <exception cref="PocketException">Parse error.</exception>
protected T DeserializeJson<T>(string json) where T : class, new()
{
json = json.Replace("[]", "{}");
// deserialize object
T parsedResponse = JsonConvert.DeserializeObject<T>(
json,
new JsonSerializerSettings
{
Error = (object sender, ErrorEventArgs args) =>
{
throw new PocketException(String.Format("Parse error: {0}", args.ErrorContext.Error.Message));
},
Converters =
{
new PocketItemConverter(),
new BoolConverter(),
new UnixDateTimeConverter(),
new NullableIntConverter(),
new UriConverter()
}
}
);
return parsedResponse;
}
/// <summary>
/// Sends a list of actions
/// </summary>
/// <param name="actionParameters">The action parameters.</param>
/// <returns></returns>
internal async Task<bool> Send(IEnumerable<PocketAction> actionParameters, CancellationToken cancellationToken)
{
foreach (PocketAction action in actionParameters)
{
action.Time = action.Time.HasValue ? ((DateTime)action.Time).ToUniversalTime() : action.Time;
}
Dictionary<string, string> parameters = new Dictionary<string, string>() {{
"actions", JsonConvert.SerializeObject(actionParameters.Select(action => action.Convert()))
}};
return (await Request<Modify>("send", cancellationToken, parameters)).Status;
}
/// <summary>
/// Sends an action
/// </summary>
/// <param name="actionParameter">The action parameter.</param>
/// <returns></returns>
protected bool PutSendAction(ActionParameter actionParameter)
internal async Task<bool> Send(PocketAction actionParameter, CancellationToken cancellationToken)
{
ModifyParameters parameters = new ModifyParameters()
{
Actions = new List<ActionParameter>() { actionParameter }
};
return Get<Modify>("send", parameters.Convert(), true).Status;
return await Send(new List<PocketAction>() { actionParameter }, cancellationToken);
}
@@ -188,47 +409,90 @@ namespace PocketSharp
/// </summary>
/// <param name="response">The response.</param>
/// <returns></returns>
/// <exception cref="APIException">
/// <exception cref="PocketException">
/// Error retrieving response
/// </exception>
protected void ValidateResponse(IRestResponse response)
protected void ValidateResponse(HttpResponseMessage response)
{
if (response.StatusCode != HttpStatusCode.OK)
// no error found
if (response.StatusCode == HttpStatusCode.OK)
{
// get pocket error headers
Parameter error = response.Headers[1];
Parameter errorCode = response.Headers[2];
string exceptionString = response.Content;
bool isPocketError = error.Name == "X-Error";
// update message to include pocket response data
if (isPocketError)
{
exceptionString = exceptionString + "\nPocketResponse: (" + errorCode.Value + ") " + error.Value;
}
// create exception
APIException exception = new APIException(exceptionString, response.ErrorException);
if (isPocketError)
{
// add custom pocket fields
exception.PocketError = error.Value.ToString();
exception.PocketErrorCode = Convert.ToInt32(errorCode.Value);
// add to generic exception data
exception.Data.Add(error.Name, error.Value);
exception.Data.Add(errorCode.Name, errorCode.Value);
}
throw exception;
return;
}
else if (response.ErrorException != null)
string exceptionString = response.ReasonPhrase;
bool isPocketError = response.Headers.Contains("X-Error");
// fetch custom pocket headers
string error = TryGetHeaderValue(response.Headers, "X-Error");
int errorCode = Convert.ToInt32(TryGetHeaderValue(response.Headers, "X-Error-Code"));
// create exception strings
if (isPocketError)
{
throw new APIException("Error retrieving response", response.ErrorException);
exceptionString = String.Format("Pocket error: {0} ({1}) ", error, errorCode);
}
else
{
exceptionString = String.Format("Request error: {0} ({1})", response.ReasonPhrase, (int)response.StatusCode);
}
// create exception
PocketException exception = new PocketException(exceptionString);
if (isPocketError)
{
// add custom pocket fields
exception.PocketError = error;
exception.PocketErrorCode = errorCode;
// add to generic exception data
exception.Data.Add("X-Error", error);
exception.Data.Add("X-Error-Code", errorCode);
}
throw exception;
}
/// <summary>
/// Tries to fetch a header value.
/// </summary>
/// <param name="headers">The headers.</param>
/// <param name="key">The key.</param>
/// <returns></returns>
protected string TryGetHeaderValue(HttpResponseHeaders headers, string key)
{
string result = null;
if (headers == null || String.IsNullOrEmpty(key))
{
return null;
}
foreach (var header in headers)
{
if (header.Key == key)
{
var headerEnumerator = header.Value.GetEnumerator();
headerEnumerator.MoveNext();
result = headerEnumerator.Current;
break;
}
}
return result;
}
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
httpClient.Dispose();
lastHeaders = null;
}
}
}
+17 -86
View File
@@ -1,91 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1A291041-ADD8-467C-A6E4-0ACA26328CDF}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PocketSharp</RootNamespace>
<AssemblyName>PocketSharp</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\PocketSharp.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TargetFramework>netstandard2.0</TargetFramework>
<Version>5.0.0</Version>
<Authors>Tobias Klika</Authors>
<Company>brothers</Company>
<RepositoryUrl>https://github.com/ceee/PocketSharp</RepositoryUrl>
<Copyright>Copyright by brothers, 2019</Copyright>
<PackageTags>PocketAPI Pocket API PocketSharp Tobias Klika cee Scott Lovegrove scottisafool NReadability SgmlReader Reader Article SDK Pockem</PackageTags>
<Description>PocketSharp is a .NET Standard library that integrates the Pocket API v3.</Description>
<PackageReleaseNotes><![CDATA[
For full release notes see https://github.com/ceee/PocketSharp/blob/master/CHANGELOG.md
]]></PackageReleaseNotes>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<Reference Include="RestSharp">
<HintPath>..\packages\RestSharp.104.1\lib\net4\RestSharp.dll</HintPath>
</Reference>
<Reference Include="ServiceStack.Text">
<HintPath>..\packages\ServiceStack.Text.3.9.49\lib\net35\ServiceStack.Text.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
</ItemGroup>
<ItemGroup>
<Compile Include="APIException.cs" />
<Compile Include="Components\Add.cs" />
<Compile Include="Components\Authentification.cs" />
<Compile Include="Components\Modify.cs" />
<Compile Include="Components\ModifyTags.cs" />
<Compile Include="Components\Retrieve.cs" />
<Compile Include="JsonDeserializer.cs" />
<Compile Include="Models\Authentification\AccessCode.cs" />
<Compile Include="Models\Authentification\RequestCode.cs" />
<Compile Include="Models\Parameters\AddParameters.cs" />
<Compile Include="Models\PocketAuthor.cs" />
<Compile Include="Models\PocketImage.cs" />
<Compile Include="Models\PocketVideo.cs" />
<Compile Include="Models\Response\Add.cs" />
<Compile Include="Models\Response\Modify.cs" />
<Compile Include="Models\Parameters\ActionParameter.cs" />
<Compile Include="Models\Parameters\ModifyParameters.cs" />
<Compile Include="Models\Parameters\RetrieveParameters.cs" />
<Compile Include="Models\PocketItem.cs" />
<Compile Include="Models\PocketTag.cs" />
<Compile Include="Models\Response\ResponseBase.cs" />
<Compile Include="Models\Response\Retrieve.cs" />
<Compile Include="PocketClient.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities.cs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<license type="expression">MIT</license>
<projectUrl>https://github.com/ceee/PocketSharp</projectUrl>
<iconUrl>https://raw.github.com/ceee/PocketSharp/master/Assets/pocketsharp.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<language>en-US</language>
<releaseNotes>$releaseNotes$</releaseNotes>
<copyright>$copyright$</copyright>
<tags>$tags$</tags>
</metadata>
</package>
-78
View File
@@ -1,78 +0,0 @@

using RestSharp;
using System;
using System.Collections.Generic;
namespace PocketSharp
{
/// <summary>
/// General utilities
/// </summary>
internal class Utilities
{
/// <summary>
/// converts DateTime to an UNIX timestamp
/// </summary>
/// <param name="dateTime">The date.</param>
/// <returns>UNIX timestamp</returns>
public static int? GetUnixTimestamp(DateTime? dateTime)
{
if (dateTime == null)
{
return null;
}
return (int)((DateTime)dateTime - new DateTime(1970, 1, 1)).TotalSeconds;
}
/// <summary>
/// Creates a Parameter object.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="value">The value.</param>
/// <param name="type">The type.</param>
/// <returns></returns>
public static Parameter CreateParam(string name, object value, ParameterType type = ParameterType.GetOrPost)
{
return new Parameter() { Name = name, Value = value, Type = type };
}
/// <summary>
/// Creates a Parameter object within a list.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="value">The value.</param>
/// <param name="type">The type.</param>
/// <returns></returns>
public static List<Parameter> CreateParamInList(string name, object value, ParameterType type = ParameterType.GetOrPost)
{
return new List<Parameter>() { CreateParam(name, value, type) };
}
/// <summary>
/// Convert a dictionary to a list
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="items">The items.</param>
/// <returns></returns>
public static List<T> DictionaryToList<T>(Dictionary<string, T> items) where T : new()
{
if (items == null)
{
return null;
}
var itemEnumerator = items.GetEnumerator();
List<T> list = new List<T>();
while (itemEnumerator.MoveNext())
{
list.Add(itemEnumerator.Current.Value);
}
return list;
}
}
}
@@ -0,0 +1,22 @@
//using HtmlAgilityPack;
//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//namespace PocketSharp
//{
// internal static class HtmlNodeExtensions
// {
// public static IEnumerable<HtmlNode> SelectNodesByClass(this HtmlNode node, string className)
// {
// return node.Descendants().Where(x => x.HasClass(className));
// }
// public static HtmlNode SelectNodeByClass(this HtmlNode node, string className)
// {
// return node.Descendants().FirstOrDefault(x => x.HasClass(className));
// }
// }
//}
+260
View File
@@ -0,0 +1,260 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using PocketSharp.Models;
namespace PocketSharp
{
public class BoolConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((bool)value) ? 1 : 0);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return reader.Value == null ? false : (reader.Value.ToString() == "1");
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(bool);
}
}
public class UnixDateTimeConverter : DateTimeConverterBase
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
DateTime date = ((DateTime)value).ToUniversalTime();
DateTime epoc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var delta = date.Subtract(epoc);
writer.WriteValue((int)Math.Truncate(delta.TotalSeconds));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value.ToString() == "0")
{
return null;
}
if (reader.Value.ToString().StartsWith("-"))
{
return null;
}
double value;
if (!Double.TryParse(reader.Value.ToString(), out value))
{
DateTime date;
if (DateTime.TryParse(reader.Value.ToString(), out date))
{
return date;
}
return null;
}
return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(value);
}
}
public class NullableIntConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
int result = 0;
if (reader.Value != null)
{
result = Convert.ToInt32(reader.Value);
}
return result;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(int);
}
}
public class UriConverter : JsonConverter
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.String)
{
return null;
}
string value = reader.Value.ToString();
if (Uri.IsWellFormedUriString(value, UriKind.Absolute))
{
return new Uri(value);
}
else if (value.StartsWith("//") && Uri.IsWellFormedUriString("http:" + value, UriKind.Absolute))
{
return new Uri("http:" + value);
}
else if (value.StartsWith("www.") && Uri.IsWellFormedUriString("http://" + value, UriKind.Absolute))
{
return new Uri("http://" + value);
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
}
else if (value is Uri)
{
writer.WriteValue(((Uri)value).OriginalString);
}
}
public override bool CanConvert(Type objectType)
{
return objectType.Equals(typeof(Uri));
}
}
public class ObjectToArrayConverter<T> : CustomCreationConverter<IEnumerable<T>> where T : new()
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject;
List<T> results = new List<T>();
// object is an array
if (reader.TokenType == JsonToken.StartArray)
{
return serializer.Deserialize<IEnumerable<T>>(reader);
}
else if (reader.TokenType == JsonToken.Null)
{
return null;
}
else if (reader.TokenType == JsonToken.String)
{
return null;
}
try
{
jObject = JObject.Load(reader);
}
catch
{
return null;
}
// Populate the object properties
foreach (KeyValuePair<string, JToken> item in jObject)
{
results.Add(
serializer.Deserialize<T>(item.Value.CreateReader())
);
}
return results;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override IEnumerable<T> Create(Type objectType)
{
return new List<T>();
}
}
public class PocketItemConverter : CustomCreationConverter<PocketItem>
{
public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)
{
var jObject = JObject.ReadFrom(reader);
var pocketItem = new PocketItem();
serializer.Populate(jObject.CreateReader(), pocketItem);
//pocketItem.Json = jObject.ToString();
return pocketItem;
}
public override PocketItem Create(Type objectType)
{
return new PocketItem();
}
}
public class VideoTypeConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(((PocketVideoType)value).ToString());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.Value == null)
{
return PocketVideoType.Unknown;
}
string nr = reader.Value.ToString();
if (nr == "1")
{
return PocketVideoType.YouTube;
}
if (nr == "2" || nr == "3" || nr == "4")
{
return PocketVideoType.Vimeo;
}
if (nr == "5")
{
return PocketVideoType.HTML;
}
if (nr == "6")
{
return PocketVideoType.Flash;
}
return PocketVideoType.Unknown;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(int) || objectType == typeof(string);
}
}
}
@@ -0,0 +1,7 @@

namespace PocketSharp
{
public class PocketAuthException : PocketException
{
}
}
@@ -1,12 +1,11 @@
using System;
using System.Runtime.Serialization;
namespace PocketSharp
{
/// <summary>
/// custom Pocket API Exceptions
/// </summary>
public class APIException : Exception
public class PocketException : Exception
{
/// <summary>
/// Gets or sets the pocket error code.
@@ -26,35 +25,26 @@ namespace PocketSharp
/// <summary>
/// Initializes a new instance of the <see cref="APIException"/> class.
/// Initializes a new instance of the <see cref="PocketException"/> class.
/// </summary>
public APIException()
public PocketException()
: base() { }
/// <summary>
/// Initializes a new instance of the <see cref="APIException"/> class.
/// Initializes a new instance of the <see cref="PocketException"/> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public APIException(string message)
public PocketException(string message)
: base(message) { }
/// <summary>
/// Initializes a new instance of the <see cref="APIException"/> class.
/// Initializes a new instance of the <see cref="PocketException"/> class.
/// </summary>
/// <param name="message">The error message that explains the reason for the exception.</param>
/// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
public APIException(string message, Exception innerException)
public PocketException(string message, Exception innerException)
: base(message, innerException) { }
/// <summary>
/// Initializes a new instance of the <see cref="APIException"/> class.
/// </summary>
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds the serialized object data about the exception being thrown.</param>
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains contextual information about the source or destination.</param>
protected APIException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
}
}
@@ -0,0 +1,7 @@

namespace PocketSharp
{
public class PocketLimitException : PocketException
{
}
}
@@ -0,0 +1,7 @@

namespace PocketSharp
{
public class PocketRequestException : PocketException
{
}
}
+28
View File
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
namespace PocketSharp
{
/// <summary>
/// General utilities
/// </summary>
internal class Utilities
{
/// <summary>
/// converts DateTime to an UNIX timestamp
/// </summary>
/// <param name="dateTime">The date.</param>
/// <returns>
/// UNIX timestamp
/// </returns>
public static int? GetUnixTimestamp(DateTime? dateTime)
{
if (dateTime == null)
{
return null;
}
return (int)((DateTime)dateTime - new DateTime(1970, 1, 1)).TotalSeconds;
}
}
}
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="RestSharp" version="104.1" targetFramework="net40" />
<package id="ServiceStack.Text" version="3.9.49" targetFramework="net40" />
</packages>
+32 -210
View File
@@ -1,42 +1,37 @@
# PocketSharp
![PocketSharp](https://raw.github.com/ceee/PocketSharp/master/Assets/github-header.png)
> This project is work in progress. Be aware of this!
**PocketSharp** is a .NET Standard library that integrates the [Pocket API v3](http://getpocket.com/developer).
PocketSharp is a C#.NET class library, that integrates the [Pocket API v3](http://getpocket.com/developer).
## Install PocketSharp using [NuGet](https://www.nuget.org/packages/PocketSharp/)
_If you don't know [Pocket](http://getpocket.com), be sure to check it out. It's an awesome service, which lets you save articles, videos, ... in the cloud and access it from all your devices._
```
Install-Package PocketSharp
```
PocketSharp consists of 4 parts:
- Authentication
- Retrieve
- Modify
- Add
## Documentation
See [wiki](https://github.com/ceee/PocketSharp/wiki)
## Where's the Article View API?
You can either use the open source [ReadSharp](https://github.com/ceee/ReadSharp) parser or if you want to use the official API by Pocket, you have to request access to it.<br>
Afterwards you can use the access information to query the endpoint with PocketSharp. Instructions [here](https://github.com/ceee/PocketSharp/wiki/Article-parser).
---
## Usage Example
## Usage Example:
Request a [Consumer Key on Pocket.](http://getpocket.com/developer/apps/)
Include the PocketSharp namespace and it's associated models (you will need them later):
A search for items containing `CSS`:
```csharp
using PocketSharp;
using PocketSharp.Models;
```
PocketClient client = new PocketClient("[YOUR_CONSUMER_KEY]", "[YOUR_ACCESS_CODE]");
Initialize PocketClient with:
List<PocketItem> items = await client.Search("css");
```csharp
PocketClient _client = new PocketClient("[YOUR_CONSUMER_KEY]", "[YOUR_ACCESS_CODE]");
```
Do a simple request - e.g. a search for `CSS`:
```csharp
_client.Search("css").ForEach(
item => Console.WriteLine(item.ID + " | " + item.Title)
items.ForEach(
item => Debug.WriteLine(item.ID + " | " + item.Title)
);
```
@@ -46,193 +41,20 @@ Which will output:
345541438 | Editr - HTML, CSS, JavaScript playground
251743431 | CSS Architecture
343693149 | CSS3 Transitions - Thank God We Have A Specification!
...
## Create an instance
Constructor:
```csharp
PocketClient(string consumerKey, string accessCode = null, Uri callbackUri = null)
```
`consumerKey`: The API key
<br>
`accessCode`: Provide an access code if the user is already authenticated
<br>
`callbackUri`: The callback URL is called by Pocket after authentication
Example:
```csharp
PocketClient _client = new PocketClient(
consumerKey: "123498237423498723498723",
callbackUri: new Uri("http://ceecore.com"),
accessCode: "097809-oi987-izi8-jk98-oiuu89"
);
```
You can change the _Access Code_ after initialization:
```csharp
_client.AccessCode = "[YOU_ACCESS_CODE]";
```
**Before authentication** you will need to provide the `callbackUri` for authentication requests.
<br>
**After authentication** you will need to provide the `accessCode`.
## Authentication
In order to communicate with a Pocket User, you will need a consumer key (which is generated by [creating a new application on Pocket](http://getpocket.com/developer/apps/)) and an **Access Code**.
This is a 3-step process:
1) Receive the **request code** and **authentication URI** from the library by calling `string GetRequestCode()`:
```csharp
string requestCode = _client.GetRequestCode();
Uri authenticationUri = _client.GenerateAuthenticationUri();
```
The _request code_ is stored internally, but you can also provide it as param in `GenerateAuthenticationUri(string requestCode = null)`.
2) Next you need to redirect the user to the `authenticationUri`, which displays a prompt to grant permissions for the application. After the user granted or denied, he/she is redirected to the `callbackUri`.
3) Call `string GetAccessCode(string requestCode = null)`
```csharp
string accessCode = _client.GetAccessCode();
```
Again, the received _access code_ is stored internally.
Note that `GetAccessCode` can only be called with an existing _request code_. If you need to re-authenticate a user, start again with Step 1).
#### Important
**Be sure to permanently store the _Access Code_ for your user.**
<br>
Without it you would always have to redo the authentication process.
## Retrieve
Find items by a tag:
```csharp
List<PocketItem> items = _client.SearchByTag("tutorial");
```
Find items by a search string:
```csharp
List<PocketItem> items = _client.Search("css");
```
Find items by a filter:
```csharp
List<PocketItem> items = _client.Retrieve(RetrieveFilter.Favorite); // only favorites
```
The RetrieveFilter Enum is specified as follows:
```csharp
enum RetrieveFilter { All, Unread, Archive, Favorite, Article, Video, Image }
```
#### Custom Parameters
You can create a completely custom parameter list for retrieval with the POCO `RetrieveParameters`:
```csharp
var parameters = new RetrieveParameters()
{
Count = 50,
Offset = 100,
Sort = SortEnum.oldest
...
};
List<PocketItem> items = _client.Retrieve(parameters);
```
## Add
Adds a new item to your pocket list.
Accepts four parameters, with `uri` being required.
```csharp
PocketItem Add(Uri uri, string[] tags = null, string title = null, string tweetID = null)
```
Example:
```csharp
PocketItem newItem = _client.Add(
new Uri("http://www.neowin.net/news/full-build-2013-conference-sessions-listing-revealed"),
new string[] { "microsoft", "neowin", "build" }
);
```
The title can be included for cases where an item does not have a title, which is typical for image or PDF URLs. If Pocket detects a title from the content of the page, this parameter will be ignored.
If you are adding Pocket support to a Twitter client, please send along a reference to the tweet status id (with the tweetID). This allows Pocket to show the original tweet alongside the article.
## Modify
All Modify methods accept either the itemID (as int) or a `PocketItem` as parameter.
Archive the specified item:
bool isSuccess = _client.Archive(myPocketItem);
Un-archive the specified item:
bool isSuccess = _client.Unarchive(myPocketItem);
Favorites the specified item:
bool isSuccess = _client.Favorite(myPocketItem);
Un-favorites the specified item:
bool isSuccess = _client.Unfavorite(myPocketItem);
Deletes the specified item:
bool isSuccess = _client.Delete(myPocketItem);
#### Modify tags
Add tags to the specified item:
bool isSuccess = _client.AddTags(myPocketItem, new string[] { "css", "2013" });
Remove tags from the specified item:
bool isSuccess = _client.RemoveTags(myPocketItem, new string[] { "css", "2013" });
Remove all tags from the specified item:
bool isSuccess = _client.RemoveTags(myPocketItem);
Replaces all existing tags with new ones for the specified item:
bool isSuccess = _client.ReplaceTags(myPocketItem, new string[] { "css", "2013" });
Renames a tag for the specified item:
bool isSuccess = _client.RenameTag(myPocketItem, "oldTagName", "newTagName");
...
---
## Release History
## Dependencies
- 2013-07-01 v0.3.0-pre update authentication process _(breaking)_
- 2013-06-27 v0.2.0 add, modify item & modify tags
- 2013-06-26 v0.1.0 authentication & retrieve functionality
- [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json/)
## Contributors
| [![twitter/artistandsocial](http://gravatar.com/avatar/9c61b1f4307425f12f05d3adb930ba66?s=70)](http://twitter.com/artistandsocial "Follow @artistandsocial on Twitter") |
|---|
| [Tobias Klika @ceee](https://github.com/ceee) |
| [![ceee](http://gravatar.com/avatar/9c61b1f4307425f12f05d3adb930ba66?s=70)](https://github.com/ceee "Tobias Klika") | [![ScottIsAFool](http://gravatar.com/avatar/6df656872a87b09a7470feb4867ed927?s=70)](https://github.com/ScottIsAFool "Scott Lovegrove") |
|---|---|
| [ceee](https://github.com/ceee) | [ScottIsAFool](https://github.com/ScottIsAFool) |
## License
[MIT License](https://github.com/ceee/PocketSharp/blob/master/LICENSE-MIT)