54 Commits

Author SHA1 Message Date
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
60 changed files with 111816 additions and 572 deletions
+16 -3
View File
@@ -1,3 +1,16 @@
### 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
@@ -9,13 +22,13 @@
### 2.2.0 (2013-10-26)
- Made `GetAccessCode` obsolete
- Return username after authentication with `GetUser` (thanks to [ScottIsAFool](https://github.com/ScottIsAFool))
- Return username after authentication with `GetUser`
### 2.1.0 (2013-10-25)
- Rename `Statistics()` to `GetUserStatistics()`
- Made `CallbackUri` public (thanks to [ScottIsAFool](https://github.com/ScottIsAFool))
- Added Fody/PropertyChanged (thanks to [ScottIsAFool](https://github.com/ScottIsAFool))
- Made `CallbackUri` public
- Added Fody/PropertyChanged
- Method `GetUsageLimits()` to retrieve API usage limits
- Add PORTABLE constant to SgmlReader
@@ -7,10 +7,10 @@
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Button Content="Load Items" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="380" Height="34" Click="Button_Click"/>
<Grid x:Name="LayoutRoot" Background="White">
<Button Content="Load Items" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="380" Height="34" Click="Button_Click"/>
<sdk:DataGrid x:Name="Content" HorizontalAlignment="Left" Height="241" Margin="10,49,0,0" VerticalAlignment="Top" Width="380" FrozenColumnCount="2"/>
</Grid>
</Grid>
</UserControl>
@@ -1,16 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace PocketSharp.Silverlight
{
@@ -39,7 +31,7 @@ namespace PocketSharp.Silverlight
PocketClient client = new PocketClient(
consumerKey: "15396-f6f92101d72c8e270a6c9bb3",
callbackUri: "http://frontendplay.com",
accessCode: "2c62cd50-b78a-5558-918b-65adae"
accessCode: "80acf6c5-c198-03c0-b94c-e74402"
);
List<PocketSharp.Models.PocketItem> items = null;
@@ -78,6 +78,17 @@
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Bcl.1.1.3\lib\sl5\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Runtime, Version=2.6.3.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Bcl.1.1.3\lib\sl5\System.Runtime.dll</HintPath>
@@ -4,11 +4,11 @@
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.5.19.0" newVersion="2.5.19.0" />
<bindingRedirect oldVersion="0.0.0.0-2.6.3.0" newVersion="2.6.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.5.19.0" newVersion="2.5.19.0" />
<bindingRedirect oldVersion="0.0.0.0-2.6.3.0" newVersion="2.6.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
@@ -3,4 +3,5 @@
<package id="Microsoft.Bcl" version="1.1.3" targetFramework="sl50" />
<package id="Microsoft.Bcl.Async" version="1.0.16" targetFramework="sl50" />
<package id="Microsoft.Bcl.Build" version="1.0.10" targetFramework="sl50" />
<package id="Microsoft.Net.Http" version="2.2.18" targetFramework="sl50" />
</packages>
+9 -19
View File
@@ -1,20 +1,10 @@
<Application
x:Class="PocketSharp.WP8.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
<!--Application Resources-->
<Application.Resources>
<local:LocalizedStrings xmlns:local="clr-namespace:PocketSharp.WP8" x:Key="LocalizedStrings"/>
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService
Launching="Application_Launching" Closing="Application_Closing"
Activated="Application_Activated" Deactivated="Application_Deactivated"/>
</Application.ApplicationLifetimeObjects>
<Application x:Class="PocketSharp.WP8.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d1p1:Ignorable="d" xmlns:d1p1="http://schemas.openxmlformats.org/markup-compatibility/2006">
<!--Application Resources-->
<Application.Resources>
<local:LocalizedStrings xmlns:local="clr-namespace:PocketSharp.WP8" x:Key="LocalizedStrings" />
</Application.Resources>
<Application.ApplicationLifetimeObjects>
<!--Required object that handles lifetime events for the application-->
<shell:PhoneApplicationService Launching="Application_Launching" Closing="Application_Closing" Activated="Application_Activated" Deactivated="Application_Deactivated" />
</Application.ApplicationLifetimeObjects>
</Application>
@@ -14,59 +14,33 @@
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<!--Data context is set to sample data above and LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Data context is set to sample data above and LayoutRoot contains the root grid where all other page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- LOCALIZATION NOTE:
To localize the displayed strings copy their values to appropriately named
keys in the app's neutral language resource file (AppResources.resx) then
replace the hard-coded text value between the attributes' quotation marks
with the binding clause whose path points to that string name.
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
<Button Click="Button_Click">Load Data</Button>
</StackPanel>
For example:
Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource LocalizedStrings}}"
This binding points to the template's string resource named "ApplicationTitle".
Adding supported languages in the Project Properties tab will create a
new resx file per language that can carry the translated values of your
UI strings. The binding in these examples will cause the value of the
attributes to be drawn from the .resx file that matches the
CurrentUICulture of the app at run time.
-->
<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel contains LongListSelector and LongListSelector ItemTemplate. Place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="MainLongListSelector_SelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
<!--Uncomment to see an alignment grid to help ensure your controls are
aligned on common boundaries. The image has a top margin of -32px to
account for the System Tray. Set this to 0 (or remove the margin altogether)
if the System Tray is hidden.
Before shipping remove this XAML and the image itself.-->
<!--<Image Source="/Assets/AlignmentGrid.png" VerticalAlignment="Top" Height="800" Width="480" Margin="0,-32,0,0" Grid.Row="0" Grid.RowSpan="2" IsHitTestVisible="False" />-->
<!--ContentPanel contains LongListSelector and LongListSelector ItemTemplate. Place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<phone:LongListSelector x:Name="MainLongListSelector" Margin="0,0,-12,0" ItemsSource="{Binding Items}" SelectionChanged="MainLongListSelector_SelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,0,0,17">
<TextBlock Text="{Binding LineOne}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock Text="{Binding LineTwo}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
@@ -1,15 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Microsoft.Phone.Controls;
using PocketSharp.WP8.ViewModels;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using PocketSharp.WP8.Resources;
using PocketSharp.WP8.ViewModels;
using System.Threading.Tasks;
namespace PocketSharp.WP8
{
@@ -22,18 +16,12 @@ namespace PocketSharp.WP8
// Set the data context of the LongListSelector control to the sample data
DataContext = App.ViewModel;
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
// Load data for the ViewModel Items
protected async override void OnNavigatedTo(NavigationEventArgs e)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!App.ViewModel.IsDataLoaded)
{
await App.ViewModel.LoadData();
}
}
// Handle selection changed on LongListSelector
@@ -50,20 +38,9 @@ namespace PocketSharp.WP8
MainLongListSelector.SelectedItem = null;
}
// Sample code for building a localized ApplicationBar
//private void BuildLocalizedApplicationBar()
//{
// // Set the page's ApplicationBar to a new instance of ApplicationBar.
// ApplicationBar = new ApplicationBar();
// // Create a new button and set the text value to the localized string from AppResources.
// ApplicationBarIconButton appBarButton = new ApplicationBarIconButton(new Uri("/Assets/AppBar/appbar.add.rest.png", UriKind.Relative));
// appBarButton.Text = AppResources.AppBarButtonText;
// ApplicationBar.Buttons.Add(appBarButton);
// // Create a new menu item with the localized string from AppResources.
// ApplicationBarMenuItem appBarMenuItem = new ApplicationBarMenuItem(AppResources.AppBarMenuItemText);
// ApplicationBar.MenuItems.Add(appBarMenuItem);
//}
private async void Button_Click(object sender, RoutedEventArgs e)
{
await App.ViewModel.LoadData();
}
}
}
@@ -130,6 +130,7 @@
</DesignData>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="Properties\AppManifest.xml" />
<None Include="Properties\WMAppManifest.xml">
<SubType>Designer</SubType>
@@ -178,6 +179,17 @@
<Reference Include="Microsoft.Threading.Tasks.Extensions.Phone">
<HintPath>..\..\packages\Microsoft.Bcl.Async.1.0.16\lib\wp8\Microsoft.Threading.Tasks.Extensions.Phone.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.18\lib\sl4-windowsphone71\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.18\lib\sl4-windowsphone71\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=1.5.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Net.Http.2.2.18\lib\sl4-windowsphone71\System.Net.Http.Primitives.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).$(TargetFrameworkVersion).Overrides.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)\Microsoft.$(TargetFrameworkIdentifier).CSharp.targets" />
@@ -196,4 +208,9 @@
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<Import Project="..\..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
</Project>
@@ -1,11 +1,10 @@
using System;
using PocketSharp.WP8.Resources;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using PocketSharp.WP8.Resources;
using PocketSharp;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Threading.Tasks;
namespace PocketSharp.WP8.ViewModels
{
@@ -68,14 +67,14 @@ namespace PocketSharp.WP8.ViewModels
PocketClient client = new PocketClient(
consumerKey: "15396-f6f92101d72c8e270a6c9bb3",
callbackUri: "http://frontendplay.com",
accessCode: "2c62cd50-b78a-5558-918b-65adae"
accessCode: "80acf6c5-c198-03c0-b94c-e74402"
);
List<PocketSharp.Models.PocketItem> items = null;
try
{
items = await client.Get().ConfigureAwait(false);
items = await client.Get();
items.ForEach(item =>
{
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.6" targetFramework="wp80" />
<package id="Microsoft.Bcl.Build" version="1.0.13" targetFramework="wp80" />
<package id="Microsoft.Net.Http" version="2.2.18" targetFramework="wp80" />
</packages>
@@ -1,9 +1,7 @@
using System.Windows;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Collections.Generic;
using System;
using System.Windows;
namespace PocketSharp.Wpf
{
@@ -35,7 +33,7 @@ namespace PocketSharp.Wpf
PocketClient client = new PocketClient(
consumerKey: "15396-f6f92101d72c8e270a6c9bb3",
callbackUri: "http://frontendplay.com",
accessCode: "2c62cd50-b78a-5558-918b-65adae"
accessCode: "80acf6c5-c198-03c0-b94c-e74402"
);
List<PocketSharp.Models.PocketItem> items = null;
+35
View File
@@ -0,0 +1,35 @@
using PocketSharp.Models;
using System;
using System.Threading.Tasks;
namespace PocketSharp
{
public interface IPocketReader
{
/// <summary>
/// Reads article content from the given URI.
/// This method does not use the official Article View API, which is private.
/// The PocketReader is based on a custom PCL port of NReadability and SgmlReader.
/// </summary>
/// <param name="uri">An URI.</param>
/// <param name="bodyOnly">if set to <c>true</c> [only body is returned].</param>
/// <param name="noHeadline">if set to <c>true</c> [no headline (h1) is included].</param>
/// <returns>A Pocket article with extracted content and title.</returns>
/// <exception cref="PocketRequestException"></exception>
Task<PocketArticle> Read(Uri uri, bool bodyOnly = true, bool noHeadline = false);
/// <summary>
/// Reads article content from the given PocketItem.
/// This method does not use the official Article View API, which is private.
/// The PocketReader is based on a custom PCL port of NReadability and SgmlReader.
/// </summary>
/// <param name="item">The pocket item.</param>
/// <param name="bodyOnly">if set to <c>true</c> [only body is returned].</param>
/// <param name="noHeadline">if set to <c>true</c> [no headline (h1) is included].</param>
/// <returns>
/// A Pocket article with extracted content and title.
/// </returns>
/// <exception cref="PocketRequestException"></exception>
Task<PocketArticle> Read(PocketItem item, bool bodyOnly = true, bool noHeadline = false);
}
}
@@ -1,17 +1,22 @@
using PocketSharp.Ports.NReadability;
using PocketSharp.Models;
using PocketSharp.Ports.NReadability;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using PocketSharp.Models;
namespace PocketSharp
{
/// <summary>
/// PocketReader
/// </summary>
public class PocketReader
public class PocketReader : IPocketReader
{
/// <summary>
/// Used UserAgent for HTTP request
/// </summary>
protected string _userAgent = "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0; ARM; Mobile; Touch{0}) like Gecko";
/// <summary>
/// REST client used for HTML retrieval
/// </summary>
@@ -19,25 +24,39 @@ namespace PocketSharp
/// <summary>
/// Initializes a new instance of the <see cref="PocketReader"/> class.
/// Initializes a new instance of the <see cref="PocketReader" /> class.
/// </summary>
public PocketReader()
/// <param name="userAgent">Custom UserAgent string.</param>
/// <param name="handler">The HttpMessage handler.</param>
/// <param name="timeout">Request timeout (in seconds).</param>
public PocketReader(string userAgent = null, HttpMessageHandler handler = null, int? timeout = null)
{
// override user agent
if (!string.IsNullOrEmpty(userAgent))
{
_userAgent = userAgent;
}
// initialize HTTP client
_httpClient = new HttpClient(new HttpClientHandler()
_httpClient = new HttpClient(handler ?? new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
AllowAutoRedirect = true
});
if (timeout.HasValue)
{
_httpClient.Timeout = TimeSpan.FromSeconds(timeout.Value);
}
// add accept types
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");
// add accepted encodings
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept-Encoding", "gzip,deflate");
// add user agent (default for Opera with PocketSharp identifier appended)
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.4 Safari/537.36 OPR/18.0.1284.2 PocketSharp/2.2");
// add user agent
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", string.Format(_userAgent, "; PocketSharp/3.0"));
}
@@ -48,15 +67,18 @@ namespace PocketSharp
/// The PocketReader is based on a custom PCL port of NReadability and SgmlReader.
/// </summary>
/// <param name="uri">An URI.</param>
/// <returns>A Pocket article with extracted content and title.</returns>
/// <exception cref="PocketRequestException"></exception>
public async Task<PocketArticle> Read(Uri uri)
/// <param name="bodyOnly">if set to <c>true</c> [only body is returned].</param>
/// <param name="noHeadline">if set to <c>true</c> [no headline (h1) is included].</param>
/// <returns>
/// A Pocket article with extracted content and title.
/// </returns>
public async Task<PocketArticle> Read(Uri uri, bool bodyOnly = true, bool noHeadline = false)
{
return await Read(new PocketItem()
{
ID = 0,
ID = null,
Uri = uri
});
}, bodyOnly, noHeadline);
}
@@ -67,9 +89,13 @@ namespace PocketSharp
/// The PocketReader is based on a custom PCL port of NReadability and SgmlReader.
/// </summary>
/// <param name="item">The pocket item.</param>
/// <returns>A Pocket article with extracted content and title.</returns>
/// <param name="bodyOnly">if set to <c>true</c> [only body is returned].</param>
/// <param name="noHeadline">if set to <c>true</c> [no headline (h1) is included].</param>
/// <returns>
/// A Pocket article with extracted content and title.
/// </returns>
/// <exception cref="PocketRequestException"></exception>
public async Task<PocketArticle> Read(PocketItem item)
public async Task<PocketArticle> Read(PocketItem item, bool bodyOnly = true, bool noHeadline = false)
{
// initialize transcoder
NReadabilityTranscoder transcoder = new NReadabilityTranscoder(
@@ -90,18 +116,19 @@ namespace PocketSharp
Url = item.Uri.ToString(),
DomSerializationParams = new DomSerializationParams()
{
BodyOnly = true,
BodyOnly = bodyOnly,
NoHeadline = noHeadline,
PrettyPrint = true,
DontIncludeContentTypeMetaElement = true,
DontIncludeMobileSpecificMetaElements = true,
DontIncludeDocTypeMetaElement = true,
DontIncludeDocTypeMetaElement = false,
DontIncludeGeneratorMetaElement = true
}
};
// process/transcode HTML
TranscodingResult transcodingResult = transcoder.Transcode(transcodingInput);
return new PocketArticle()
{
Content = transcodingResult.ExtractedContent,
@@ -0,0 +1,96 @@
<?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')" />
<PropertyGroup>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PocketSharp</RootNamespace>
<AssemblyName>PocketSharp.Reader</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile>Profile96</TargetFrameworkProfile>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<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>
</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>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Compile Include="IPocketReader.cs" />
<Compile Include="PocketReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl4+win8+wp71\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http">
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PocketSharp\PocketSharp.csproj">
<Project>{817200c3-a327-4e35-9b5f-63a51c088577}</Project>
<Name>PocketSharp</Name>
</ProjectReference>
<ProjectReference Include="..\PortablePorts\NReadability\NReadability.csproj">
<Project>{14c3ee6a-54a4-4a37-8b56-d52a3802f1c2}</Project>
<Name>NReadability</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- 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,28 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<licenseUrl>https://raw.github.com/ceee/PocketSharp/master/LICENSE-MIT</licenseUrl>
<projectUrl>https://github.com/ceee/PocketSharp</projectUrl>
<iconUrl>https://raw.github.com/ceee/PocketSharp/master/Assets/pocketsharp.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
<![CDATA[
PocketSharp is a C#.NET portable class library that integrates the Pocket API v3.
PocketSharp.Reader contains the reader which extracts readable content from websites.
]]>
</description>
<language>en-US</language>
<releaseNotes>
<![CDATA[
For full release notes see https://github.com/ceee/PocketSharp/blob/master/CHANGELOG.md
]]>
</releaseNotes>
<copyright>Copyright by cee, 2013</copyright>
<tags>PocketAPI Pocket API PocketSharp Tobias Klika cee NReadability SgmlReader Reader Article SDK Pockem</tags>
</metadata>
</package>
@@ -0,0 +1,26 @@
using System.Reflection;
// 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.Reader")]
[assembly: AssemblyDescription("Custom Article View API for PocketSharp")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("cee")]
[assembly: AssemblyProduct("PocketSharp.Reader")]
[assembly: AssemblyCopyright("Copyright © cee 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("3.0.0")]
[assembly: AssemblyFileVersion("3.0.0")]
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.6" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Microsoft.Bcl.Async" version="1.0.165" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Microsoft.Bcl.Build" version="1.0.13" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Microsoft.Net.Http" version="2.2.18" targetFramework="portable-win+net403+sl40+wp71" />
</packages>
+5
View File
@@ -50,6 +50,11 @@ namespace PocketSharp.Tests
await client.RegisterAccount("myusername", "pocketsharp@outlook,com", "mypassword");
});
await ThrowsAsync<FormatException>(async () =>
{
await client.RegisterAccount("myusername", "pocketsharp@outlook.com", "my");
});
await ThrowsAsync<ArgumentNullException>(async () =>
{
await client.RegisterAccount("myusername", null, "mypassword");
+17 -4
View File
@@ -1,8 +1,8 @@
using System;
using System.Threading.Tasks;
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using PocketSharp.Models;
namespace PocketSharp.Tests
{
@@ -24,6 +24,19 @@ namespace PocketSharp.Tests
}
[Fact]
public async Task ItemWithInstableImagesIsAdded()
{
var uri = new Uri("http://www.valoronline.com.br");
PocketItem item = await client.Add(uri);
Assert.Equal<Uri>(uri, item.Uri);
itemsToDelete.Add(item.ID);
}
[Fact]
public async Task AddComplexItem()
{
@@ -39,7 +52,7 @@ namespace PocketSharp.Tests
items.ForEach(itm =>
{
if(itm.ID == item.ID)
if (itm.ID == item.ID)
{
itemDesired = itm;
}
File diff suppressed because one or more lines are too long
+92 -6
View File
@@ -1,8 +1,8 @@
using System;
using System.Threading.Tasks;
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using PocketSharp.Models;
namespace PocketSharp.Tests
{
@@ -15,7 +15,6 @@ namespace PocketSharp.Tests
public async Task AreItemsRetrieved()
{
List<PocketItem> items = await client.Get();
Assert.True(items.Count > 0);
}
@@ -76,7 +75,7 @@ namespace PocketSharp.Tests
Assert.False(items.Count > 0);
PocketItem item = await client.Get(99999999);
PocketItem item = await client.Get("99999999");
Assert.Null(item);
@@ -147,7 +146,7 @@ namespace PocketSharp.Tests
[Fact]
public async Task AreStatisticsRetrieved()
{
PocketStatistics statistics = await client.Statistics();
PocketStatistics statistics = await client.GetUserStatistics();
Assert.True(statistics.CountAll > 0);
}
@@ -160,5 +159,92 @@ namespace PocketSharp.Tests
Assert.True(limits.RateLimitForConsumerKey > 9999);
}
[Fact]
public async Task IsNewPocketItemListGeneratorWorking()
{
List<PocketItem> items = await client.Get(count: 1, tag: "pocket");
PocketItem item = items[0];
Assert.True(item.Tags.Find(i => i.Name == "pocket") != null);
}
[Fact]
public async Task IsSinceParameterWorkingOnAddTags()
{
DateTime since = DateTime.UtcNow;
List<PocketItem> items = await client.Get(state: State.all);
PocketItem itemToModify = items[0];
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.UtcNow;
List<PocketItem> items = await client.Get(state: State.all);
PocketItem itemToModify = items[0];
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.UtcNow;
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 IsSinceParameterWorkingOnAddAndDelete()
{
DateTime since = DateTime.UtcNow;
PocketItem item = await client.Add(new Uri("http://frontendplay.com"));
List<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[0].IsDeleted);
}
}
}
+31
View File
@@ -0,0 +1,31 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
public class MiscTests : TestsBase
{
private int Incrementor = 0;
public MiscTests()
: base()
{
client.PreRequest = method => Incrementor++;
}
[Fact]
public async Task CheckPreRequestAction()
{
List<PocketItem> items = await client.Get(count: 1);
PocketItem item = items[0];
await client.Favorite(item);
await client.Unfavorite(item);
Assert.True(Incrementor >= 3);
}
}
}
+5 -5
View File
@@ -1,9 +1,9 @@
using System;
using System.Threading.Tasks;
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using Xunit;
using PocketSharp.Models;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace PocketSharp.Tests
{
@@ -83,7 +83,7 @@ namespace PocketSharp.Tests
}
private async Task<PocketItem> GetItemById(int id, bool archive = false)
private async Task<PocketItem> GetItemById(string id, bool archive = false)
{
List<PocketItem> items = await client.Get(state: archive ? State.archive : State.unread);
PocketItem itemDesired = null;
+30 -4
View File
@@ -1,8 +1,9 @@
using System;
using System.Threading.Tasks;
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using PocketSharp.Models;
namespace PocketSharp.Tests
{
@@ -62,6 +63,31 @@ namespace PocketSharp.Tests
}
[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 },
new PocketAction() { Action = "tag_rename", ID = item.ID, OldTag = "social", NewTag = "not_social" }
});
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"));
Assert.NotNull(item.Tags.Single<PocketTag>(tag => tag.Name == "not_social"));
}
private async Task<PocketItem> Setup()
{
PocketItem item = await client.Add(
@@ -75,7 +101,7 @@ namespace PocketSharp.Tests
}
private async Task<PocketItem> GetItemById(int id, bool archive = false)
private async Task<PocketItem> GetItemById(string id, bool archive = false)
{
List<PocketItem> items = await client.Get(state: archive ? State.archive : State.unread);
PocketItem itemDesired = null;
+21 -11
View File
@@ -37,22 +37,24 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\net45\Microsoft.Threading.Tasks.dll</HintPath>
<Reference Include="Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\net45\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
<Reference Include="Microsoft.Threading.Tasks.Extensions, Version=1.0.12.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Net" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Net.Http.Extensions, Version=2.2.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Reference Include="System.Net.Http.Extensions, Version=2.2.18.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\net45\System.Net.Http.Extensions.dll</HintPath>
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\net45\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives, Version=4.2.15.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<Reference Include="System.Net.Http.Primitives, Version=4.2.18.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\net45\System.Net.Http.Primitives.dll</HintPath>
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\net45\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="xunit">
@@ -68,6 +70,7 @@
<Otherwise />
</Choose>
<ItemGroup>
<Compile Include="MiscTests.cs" />
<Compile Include="AddTests.cs" />
<Compile Include="AccountTests.cs" />
<Compile Include="ModifyTagsTests.cs" />
@@ -75,9 +78,14 @@
<Compile Include="GetTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReadTests.cs" />
<Compile Include="StressTests.cs" />
<Compile Include="TestsBase.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PocketSharp.Reader\PocketSharp.Reader.csproj">
<Project>{9d1bbd72-c263-43d3-9f2a-98f9f99235a4}</Project>
<Name>PocketSharp.Reader</Name>
</ProjectReference>
<ProjectReference Include="..\PocketSharp\PocketSharp.csproj">
<Project>{817200c3-a327-4e35-9b5f-63a51c088577}</Project>
<Name>PocketSharp</Name>
@@ -86,6 +94,8 @@
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
<None Include="url-10000.csv" />
<None Include="url-100000.csv" />
</ItemGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '10.0' And '$(IsCodedUITest)' == 'True'">
@@ -114,10 +124,10 @@
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- 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.
+24 -7
View File
@@ -1,8 +1,7 @@
using System;
using PocketSharp.Models;
using System;
using System.Threading.Tasks;
using Xunit;
using PocketSharp.Models;
using System.Diagnostics;
namespace PocketSharp.Tests
{
@@ -11,7 +10,8 @@ namespace PocketSharp.Tests
private PocketReader reader;
public ReadTests() : base()
public ReadTests()
: base()
{
reader = new PocketReader();
}
@@ -22,10 +22,27 @@ namespace PocketSharp.Tests
{
PocketArticle result = await reader.Read(new PocketItem()
{
ID = 99,
ID = "99",
Uri = new Uri("http://frontendplay.com/story/4/http-caching-demystified-part-2-implementation")
});
Assert.DoesNotContain("<!DOCTYPE html>", result.Content);
Assert.Contains("<h1>", result.Content);
Assert.True(result.Content.Length > 15000);
}
[Fact]
public async Task ReadArticleWithContainerNoHeadlineTest()
{
PocketArticle result = await reader.Read(new PocketItem()
{
ID = "99",
Uri = new Uri("http://frontendplay.com/story/4/http-caching-demystified-part-2-implementation")
}, false, true);
Assert.Contains("<!DOCTYPE html>", result.Content);
Assert.DoesNotContain("<h1>", result.Content);
Assert.True(result.Content.Length > 15000);
}
@@ -37,7 +54,7 @@ namespace PocketSharp.Tests
{
await reader.Read(new PocketItem()
{
ID = 99,
ID = "99",
Uri = new Uri("http://frontendplayyyyy.com")
});
});
@@ -49,7 +66,7 @@ namespace PocketSharp.Tests
{
PocketArticle result = await reader.Read(new PocketItem()
{
ID = 99,
ID = "99",
Uri = new Uri("http://calebjacob.com/tooltipster/")
});
+1
View File
@@ -0,0 +1 @@
<Playlist Version="1.0"><Add Test="PocketSharp.Tests.StressTests.Are0ItemsRetrievedProperly" /><Add Test="PocketSharp.Tests.StressTests.Are100ItemsRetrievedProperly" /><Add Test="PocketSharp.Tests.StressTests.Are10000ItemsRetrievedProperly" /><Add Test="PocketSharp.Tests.StressTests.IsSearchedSuccessfullyOn10000Items" /><Add Test="PocketSharp.Tests.StressTests.Are1000ItemsRetrievedProperly" /><Add Test="PocketSharp.Tests.StressTests.IsSearchedSuccessfullyOn10000Items (PocketSharp.Tests.StressTests.IsSearchedSuccessfullyOn10000Items (F:\Playground\CSharp\PocketSharp\PocketSharp.Tests\bin\Release\PocketSharp.Tests.dll))" /><Add Test="PocketSharp.Tests.StressTests.Are1000ItemsRetrievedProperly (PocketSharp.Tests.StressTests.Are1000ItemsRetrievedProperly (F:\Playground\CSharp\PocketSharp\PocketSharp.Tests\bin\Release\PocketSharp.Tests.dll))" /><Add Test="PocketSharp.Tests.StressTests.Are0ItemsRetrievedProperly (PocketSharp.Tests.StressTests.Are0ItemsRetrievedProperly (F:\Playground\CSharp\PocketSharp\PocketSharp.Tests\bin\Release\PocketSharp.Tests.dll))" /><Add Test="PocketSharp.Tests.StressTests.Are100ItemsRetrievedProperly (PocketSharp.Tests.StressTests.Are100ItemsRetrievedProperly (F:\Playground\CSharp\PocketSharp\PocketSharp.Tests\bin\Release\PocketSharp.Tests.dll))" /><Add Test="PocketSharp.Tests.StressTests.Are10000ItemsRetrievedProperly (PocketSharp.Tests.StressTests.Are10000ItemsRetrievedProperly (F:\Playground\CSharp\PocketSharp\PocketSharp.Tests\bin\Release\PocketSharp.Tests.dll))" /></Playlist>
+124
View File
@@ -0,0 +1,124 @@
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()
{
List<PocketItem> items = await client.Get(count: 100, state: State.all);
Assert.True(items.Count == 100);
}
[Fact]
public async Task Are1000ItemsRetrievedProperly()
{
List<PocketItem> items = await client.Get(count: 1000, state: State.all);
Assert.True(items.Count == 1000);
}
[Fact]
public async Task Are2500ItemsRetrievedProperly()
{
List<PocketItem> items = await client.Get(count: 2500, state: State.all);
Assert.True(items.Count == 2500);
}
[Fact]
public async Task Are5000ItemsRetrievedProperly()
{
List<PocketItem> items = await client.Get(count: 5000, state: State.all);
Assert.True(items.Count == 5000);
}
[Fact]
public async Task AreItemsRetrievedProperlyWithoutLimit()
{
List<PocketItem> items = await client.Get(state: State.all);
Assert.True(items.Count > 0);
}
[Fact]
public async Task IsSearchSuccessfullyOnBigList()
{
List<PocketItem> items = await client.Get(search: "google");
Assert.True(items.Count > 0);
Assert.True(items[0].Title.ToLower().Contains("google") || items[0].Uri.ToString().ToLower().Contains("google"));
}
[Fact]
public async Task IsTagSearchSuccessfullyOnBigList()
{
List<PocketItem> items = await client.SearchByTag(tags[0]);
Assert.True(items.Count > 1);
bool found = false;
items[0].Tags.ForEach(tag =>
{
if (tag.Name.Contains(tags[0]))
{
found = true;
}
});
Assert.True(found);
}
[Fact]
public async Task RetrieveTagsReturnsResultOnBigList()
{
List<PocketTag> items = await client.GetTags();
items.ForEach(tag =>
{
Assert.True(tags.Contains(tag.Name));
});
Assert.Equal(items.Count, tags.Length);
}
private async Task FillAccount(int offset, int count)
{
int r;
int r2;
string[] tag;
Random rnd = new Random();
foreach (string url in urls.Skip(offset).Take(count))
{
r = rnd.Next(tags.Length);
r2 = rnd.Next(tags.Length);
tag = new string[] { tags[r], tags[r2] };
await client.Add(new Uri("http://" + url), tag);
}
}
}
}
+3 -4
View File
@@ -1,8 +1,7 @@
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
using PocketSharp.Models;
namespace PocketSharp.Tests
{
@@ -10,7 +9,7 @@ namespace PocketSharp.Tests
{
protected PocketClient client;
protected List<int> itemsToDelete = new List<int>();
protected List<string> itemsToDelete = new List<string>();
// setup
@@ -26,7 +25,7 @@ namespace PocketSharp.Tests
// teardown
public void Dispose()
public void Dispose()
{
itemsToDelete.ForEach(async id =>
{
+1 -1
View File
@@ -4,7 +4,7 @@
<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.15.0" newVersion="4.2.15.0" />
<bindingRedirect oldVersion="0.0.0.0-4.2.18.0" newVersion="4.2.18.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
+4 -4
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Bcl" version="1.1.3" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.16" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.10" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.15" targetFramework="net45" />
<package id="Microsoft.Bcl" version="1.1.6" targetFramework="net45" />
<package id="Microsoft.Bcl.Async" version="1.0.165" targetFramework="net45" />
<package id="Microsoft.Bcl.Build" version="1.0.13" targetFramework="net45" />
<package id="Microsoft.Net.Http" version="2.2.18" targetFramework="net45" />
<package id="xunit" version="1.9.2" targetFramework="net45" />
</packages>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10
View File
@@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SgmlReader", "PortablePorts
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PortablePorts", "PortablePorts", "{82F79DE3-76D7-4FCB-AA7E-16BA7E363E0D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PocketSharp.Reader", "PocketSharp.Reader\PocketSharp.Reader.csproj", "{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -105,6 +107,14 @@ Global
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|Any CPU.Build.0 = Release|Any CPU
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|ARM.ActiveCfg = Release|Any CPU
{9112414C-E2D1-43BA-A298-A89F77D94332}.Release|x86.ActiveCfg = Release|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Debug|ARM.ActiveCfg = Debug|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Debug|x86.ActiveCfg = Debug|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Release|Any CPU.Build.0 = Release|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Release|ARM.ActiveCfg = Release|Any CPU
{9D1BBD72-C263-43D3-9F2A-98F9F99235A4}.Release|x86.ActiveCfg = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
+19 -31
View File
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
@@ -14,10 +15,11 @@ namespace PocketSharp
/// <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()
public async Task<string> GetRequestCode(CancellationToken cancellationToken = default(CancellationToken))
{
// check if request code is available
if (CallbackUri == null)
@@ -26,7 +28,7 @@ namespace PocketSharp
}
// do request
RequestCode response = await Request<RequestCode>("oauth/request", new Dictionary<string, string>()
RequestCode response = await Request<RequestCode>("oauth/request", cancellationToken, new Dictionary<string, string>()
{
{ "redirect_uri", CallbackUri }
}, false);
@@ -48,13 +50,13 @@ namespace PocketSharp
public Uri GenerateAuthenticationUri(string requestCode = null)
{
// check if request code is available
if(RequestCode == null && requestCode == null)
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)
if (requestCode != null)
{
RequestCode = requestCode;
}
@@ -63,30 +65,17 @@ namespace PocketSharp
}
/// <summary>
/// Requests the access code 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 requestCode. If no requestCode is supplied, the property from the PocketClient intialization is used.</param>
/// <returns>The permanent access code, which is used to authenticate the user with the application</returns>
/// <exception cref="System.NullReferenceException">Call GetRequestCode() first to receive a request_code</exception>
/// <exception cref="PocketException"></exception>
[Obsolete("Please use GetUser instead")]
public async Task<string> GetAccessCode(string requestCode = null)
{
await GetUser(requestCode);
return AccessCode;
}
/// <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.
/// 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>
/// <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)
public async Task<PocketUser> GetUser(string requestCode = null, CancellationToken cancellationToken = default(CancellationToken))
{
// check if request code is available
if (RequestCode == null && requestCode == null)
@@ -101,7 +90,7 @@ namespace PocketSharp
}
// do request
PocketUser response = await Request<PocketUser>("oauth/authorize", new Dictionary<string, string>()
PocketUser response = await Request<PocketUser>("oauth/authorize", cancellationToken, new Dictionary<string, string>()
{
{"code", RequestCode}
}, false);
@@ -120,21 +109,20 @@ namespace PocketSharp
/// <param name="username">The username.</param>
/// <param name="email">The email.</param>
/// <param name="password">The password.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">All parameters are required</exception>
/// <exception cref="System.FormatException">
/// Invalid email address.
/// <exception cref="System.FormatException">Invalid email address.
/// or
/// Invalid username. Please only use letters, numbers, and/or dashes and between 1-20 characters.
/// or
/// Invalid password.
/// </exception>
/// Invalid password.</exception>
/// <exception cref="PocketException"></exception>
public async Task<bool> RegisterAccount(string username, string email, string password)
public async Task<bool> RegisterAccount(string username, string email, string password, CancellationToken cancellationToken = default(CancellationToken))
{
if (username == null || email == null || password == null)
{
throw new ArgumentNullException("All parameters are required");
throw new ArgumentNullException("All parameters are required");
}
Match matchEmail = Regex.Match(email, @"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,10}))$");
@@ -162,7 +150,7 @@ namespace PocketSharp
Password = password
};
ResponseBase response = await Request<ResponseBase>("signup", parameters.Convert(), false);
ResponseBase response = await Request<ResponseBase>("signup", cancellationToken, parameters.Convert(), false);
return response.Status;
}
+19 -3
View File
@@ -1,5 +1,6 @@
using PocketSharp.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
@@ -16,10 +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>A simple representation of the saved item which doesn't contain all data (is only returned by calling the Retrieve method)</returns>
/// <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)
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,
@@ -28,7 +44,7 @@ namespace PocketSharp
TweetID = tweetID
};
Add response = await Request<Add>("add", parameters.Convert());
Add response = await Request<Add>("add", cancellationToken, parameters.Convert());
return response.Item;
}
+44 -31
View File
@@ -1,8 +1,9 @@
using PocketSharp.Models;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
@@ -11,22 +12,23 @@ namespace PocketSharp
/// </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>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
/// <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<List<PocketItem>> Get(
State? state = null,
bool? favorite = null,
@@ -37,7 +39,8 @@ namespace PocketSharp
string domain = null,
DateTime? since = null,
int? count = null,
int? offset = null
int? offset = null,
CancellationToken cancellationToken = default(CancellationToken)
)
{
RetrieveParameters parameters = new RetrieveParameters()
@@ -55,7 +58,7 @@ namespace PocketSharp
Offset = offset
};
Retrieve response = await Request<Retrieve>("get", parameters.Convert());
Retrieve response = await Request<Retrieve>("get", cancellationToken, parameters.Convert());
return response.Items;
}
@@ -66,14 +69,16 @@ namespace PocketSharp
/// 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(int itemID)
public async Task<PocketItem> Get(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
List<PocketItem> items = await Get(
state: State.all
cancellationToken: cancellationToken,
state: State.all
);
return items.SingleOrDefault<PocketItem>(item => item.ID == itemID);
}
@@ -82,13 +87,14 @@ namespace PocketSharp
/// 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<List<PocketItem>> Get(RetrieveFilter filter)
public async Task<List<PocketItem>> Get(RetrieveFilter filter, CancellationToken cancellationToken = default(CancellationToken))
{
RetrieveParameters parameters = new RetrieveParameters();
switch(filter)
switch (filter)
{
case RetrieveFilter.Article:
parameters.ContentType = ContentType.article;
@@ -115,7 +121,7 @@ namespace PocketSharp
parameters.DetailType = DetailType.complete;
Retrieve response = await Request<Retrieve>("get", parameters.Convert());
Retrieve response = await Request<Retrieve>("get", cancellationToken, parameters.Convert());
return response.Items;
}
@@ -125,11 +131,13 @@ namespace PocketSharp
/// 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<List<PocketTag>> GetTags()
public async Task<List<PocketTag>> GetTags(CancellationToken cancellationToken = default(CancellationToken))
{
List<PocketItem> items = await Get(
cancellationToken: cancellationToken,
state: State.all
);
@@ -145,11 +153,15 @@ namespace PocketSharp
/// 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<List<PocketItem>> SearchByTag(string tag)
public async Task<List<PocketItem>> SearchByTag(string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await Get(tag: tag);
return await Get(
cancellationToken: cancellationToken,
tag: tag
);
}
@@ -157,13 +169,14 @@ namespace PocketSharp
/// Retrieves items which match the specified search string in title and URI
/// </summary>
/// <param name="searchString">The search string.</param>
/// <param name="searchInUri">if set to <c>true</c> [search in URI].</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<List<PocketItem>> Search(string searchString, bool searchInUri = true)
public async Task<List<PocketItem>> Search(string searchString, bool searchInUri = true, CancellationToken cancellationToken = default(CancellationToken))
{
List<PocketItem> items = await Get(RetrieveFilter.All);
List<PocketItem> items = await Get(RetrieveFilter.All, cancellationToken);
return Search(items, searchString);
}
+50 -23
View File
@@ -1,4 +1,6 @@
using PocketSharp.Models;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
@@ -8,15 +10,30 @@ 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(List<PocketAction> actions, CancellationToken cancellationToken = default(CancellationToken))
{
return await Send(actions, 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>
public async Task<bool> Archive(int itemID)
public async Task<bool> Archive(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(itemID, "archive");
return await SendDefault(cancellationToken, itemID, "archive");
}
@@ -24,11 +41,12 @@ namespace PocketSharp
/// Archives the specified 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> Archive(PocketItem item)
public async Task<bool> Archive(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await Archive(item.ID);
return await Archive(item.ID, cancellationToken);
}
@@ -36,11 +54,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>
/// <exception cref="PocketException"></exception>
public async Task<bool> Unarchive(int itemID)
public async Task<bool> Unarchive(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(itemID, "readd");
return await SendDefault(cancellationToken, itemID, "readd");
}
@@ -48,11 +67,12 @@ namespace PocketSharp
/// Unarchives the specified 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> Unarchive(PocketItem item)
public async Task<bool> Unarchive(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await Unarchive(item.ID);
return await Unarchive(item.ID, cancellationToken);
}
@@ -60,11 +80,12 @@ namespace PocketSharp
/// 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>
public async Task<bool> Favorite(int itemID)
public async Task<bool> Favorite(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(itemID, "favorite");
return await SendDefault(cancellationToken, itemID, "favorite");
}
@@ -72,11 +93,12 @@ namespace PocketSharp
/// Favorites the specified 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> Favorite(PocketItem item)
public async Task<bool> Favorite(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await Favorite(item.ID);
return await Favorite(item.ID, cancellationToken);
}
@@ -84,11 +106,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>
/// <exception cref="PocketException"></exception>
public async Task<bool> Unfavorite(int itemID)
public async Task<bool> Unfavorite(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(itemID, "unfavorite");
return await SendDefault(cancellationToken, itemID, "unfavorite");
}
@@ -96,50 +119,54 @@ namespace PocketSharp
/// 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>
public async Task<bool> Unfavorite(PocketItem item)
public async Task<bool> Unfavorite(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await 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>
/// <exception cref="PocketException"></exception>
public async Task<bool> Delete(int itemID)
public async Task<bool> Delete(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(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 async Task<bool> Delete(PocketItem item)
public async Task<bool> Delete(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await 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 async Task<bool> SendDefault(int itemID, string action)
protected async Task<bool> SendDefault(CancellationToken cancellationToken, string itemID, string action)
{
return await Send(new ActionParameter()
return await Send(new PocketAction()
{
Action = action,
ID = itemID
});
}, cancellationToken);
}
}
}
+44 -30
View File
@@ -1,4 +1,5 @@
using PocketSharp.Models;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
@@ -13,11 +14,12 @@ namespace PocketSharp
/// </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> AddTags(int itemID, string[] tags)
public async Task<bool> AddTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendTags(itemID, "tags_add", tags);
return await SendTags(cancellationToken, itemID, "tags_add", tags);
}
@@ -26,11 +28,12 @@ namespace PocketSharp
/// </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>
public async Task<bool> AddTags(PocketItem item, string[] tags)
public async Task<bool> AddTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await AddTags(item.ID, tags);
return await AddTags(item.ID, tags, cancellationToken);
}
@@ -39,11 +42,12 @@ namespace PocketSharp
/// </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> RemoveTags(int itemID, string[] tags)
public async Task<bool> RemoveTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendTags(itemID, "tags_remove", tags);
return await SendTags(cancellationToken, itemID, "tags_remove", tags);
}
@@ -52,11 +56,12 @@ namespace PocketSharp
/// </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)
public async Task<bool> RemoveTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await RemoveTags(item.ID, tags);
return await RemoveTags(item.ID, tags, cancellationToken);
}
@@ -64,12 +69,13 @@ namespace PocketSharp
/// Removes a tag from an item.
/// </summary>
/// <param name="itemID">The item ID.</param>
/// <param name="tags">The tag.</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(int itemID, string tag)
public async Task<bool> RemoveTag(string itemID, string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendTags(itemID, "tags_remove", new string[] { tag });
return await SendTags(cancellationToken, itemID, "tags_remove", new string[] { tag });
}
@@ -77,12 +83,13 @@ namespace PocketSharp
/// Removes a tag from an item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="tags">The tags.</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)
public async Task<bool> RemoveTag(PocketItem item, string tag, CancellationToken cancellationToken = default(CancellationToken))
{
return await RemoveTag(item.ID, tag);
return await RemoveTag(item.ID, tag, cancellationToken);
}
@@ -90,11 +97,12 @@ namespace PocketSharp
/// 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(int itemID)
public async Task<bool> RemoveTags(string itemID, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendDefault(itemID, "tags_clear");
return await SendDefault(cancellationToken, itemID, "tags_clear");
}
@@ -102,11 +110,12 @@ namespace PocketSharp
/// 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)
public async Task<bool> RemoveTags(PocketItem item, CancellationToken cancellationToken = default(CancellationToken))
{
return await RemoveTags(item.ID);
return await RemoveTags(item.ID, cancellationToken);
}
@@ -115,11 +124,12 @@ namespace PocketSharp
/// </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(int itemID, string[] tags)
public async Task<bool> ReplaceTags(string itemID, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await SendTags(itemID, "tags_replace", tags);
return await SendTags(cancellationToken, itemID, "tags_replace", tags);
}
@@ -128,11 +138,12 @@ namespace PocketSharp
/// </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>
public async Task<bool> ReplaceTags(PocketItem item, string[] tags)
public async Task<bool> ReplaceTags(PocketItem item, string[] tags, CancellationToken cancellationToken = default(CancellationToken))
{
return await ReplaceTags(item.ID, tags);
return await ReplaceTags(item.ID, tags, cancellationToken);
}
@@ -142,17 +153,18 @@ namespace PocketSharp
/// <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>
/// <exception cref="PocketException"></exception>
public async Task<bool> RenameTag(int itemID, string oldTag, string newTag)
public async Task<bool> RenameTag(string itemID, string oldTag, string newTag, CancellationToken cancellationToken = default(CancellationToken))
{
return await Send(new ActionParameter()
return await Send(new PocketAction()
{
Action = "tag_rename",
ID = itemID,
OldTag = oldTag,
NewTag = newTag
});
}, cancellationToken);
}
@@ -162,29 +174,31 @@ namespace PocketSharp
/// <param name="item">The item.</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>
/// <exception cref="PocketException"></exception>
public async Task<bool> RenameTag(PocketItem item, string oldTag, string newTag)
public async Task<bool> RenameTag(PocketItem item, string oldTag, string newTag, CancellationToken cancellationToken = default(CancellationToken))
{
return await RenameTag(item.ID, oldTag, newTag);
return await 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 async Task<bool> SendTags(int itemID, string action, string[] tags)
protected async Task<bool> SendTags(CancellationToken cancellationToken, string itemID, string action, string[] tags)
{
return await Send(new ActionParameter()
return await Send(new PocketAction()
{
Action = action,
ID = itemID,
Tags = tags
});
}, cancellationToken);
}
}
}
+10 -16
View File
@@ -1,5 +1,6 @@
using PocketSharp.Models;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
@@ -12,23 +13,12 @@ namespace PocketSharp
/// <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()
public async Task<PocketStatistics> GetUserStatistics(CancellationToken cancellationToken = default(CancellationToken))
{
return await Request<PocketStatistics>("stats");
}
/// <summary>
/// Statistics from the user account.
/// </summary>
/// <returns></returns>
/// <exception cref="PocketException"></exception>
[Obsolete("Please use GetUserStatistics instead")]
public async Task<PocketStatistics> Statistics()
{
return await GetUserStatistics();
return await Request<PocketStatistics>("stats", cancellationToken);
}
@@ -37,16 +27,20 @@ namespace PocketSharp
/// 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()
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(count: 1);
await Get(
cancellationToken: cancellationToken,
count: 1
);
}
return new PocketLimits()
+448
View File
@@ -0,0 +1,448 @@
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; }
#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>
/// Registers a new account.
/// Account has to be activated via a activation email sent by Pocket.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="email">The email.</param>
/// <param name="password">The password.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">All parameters are required</exception>
/// <exception cref="System.FormatException">Invalid email address.
/// or
/// Invalid username. Please only use letters, numbers, and/or dashes and between 1-20 characters.
/// or
/// Invalid password.</exception>
/// <exception cref="PocketException"></exception>
Task<bool> RegisterAccount(string username, string email, string password, 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<List<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<List<PocketItem>> Get(RetrieveFilter filter, CancellationToken cancellationToken = default(CancellationToken));
/// <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<List<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<List<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="searchInUri">if set to <c>true</c> [search in URI].</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<List<PocketItem>> Search(string searchString, bool searchInUri = true, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Finds the specified search string in title and URI for an available list of items
/// </summary>
/// <param name="availableItems">The available items.</param>
/// <param name="searchString">The search string.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentOutOfRangeException">Search string length has to be a minimum of 2 chars</exception>
/// <exception cref="PocketException"></exception>
List<PocketItem> Search(List<PocketItem> availableItems, string searchString);
#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(List<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>
/// 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 in an item.
/// </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>
/// <exception cref="PocketException"></exception>
Task<bool> RenameTag(string itemID, string oldTag, string newTag, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Renames a tag in an item.
/// </summary>
/// <param name="item">The item.</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>
/// <exception cref="PocketException"></exception>
Task<bool> RenameTag(PocketItem item, 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
}
}
@@ -5,10 +5,10 @@ using System.Runtime.Serialization;
namespace PocketSharp.Models
{
/// <summary>
/// All parameters which can be passed for a modify action
/// All parameters which can be passed for a send action
/// </summary>
[DataContract]
internal class ActionParameter
public class PocketAction
{
/// <summary>
/// Gets or sets the action.
@@ -20,13 +20,40 @@ namespace PocketSharp.Models
public string Action { get; set; }
/// <summary>
/// Gets or sets the ID.
/// Gets or sets the PocketItem ID.
/// </summary>
/// <value>
/// The ID.
/// </value>
[DataMember(Name = "item_id")]
public int ID { get; set; }
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.
@@ -71,14 +98,15 @@ namespace PocketSharp.Models
/// Converts this instance to a parameter list.
/// </summary>
/// <returns></returns>
public Dictionary<string, object> Convert()
internal Dictionary<string, object> Convert()
{
Dictionary<string, object> parameters = new Dictionary<string, object>
{
{ "item_id", ID.ToString() },
{ "action", Action }
};
if (ID != "0" && !String.IsNullOrEmpty(ID.ToString()))
parameters.Add("item_id", ID.ToString());
if (Time != null)
parameters.Add("time", Time != null ? Utilities.GetUnixTimestamp(Time).ToString() : null);
if (Tags != null)
@@ -87,6 +115,12 @@ namespace PocketSharp.Models
parameters.Add("old_tag", OldTag);
if (NewTag != null)
parameters.Add("new_tag", NewTag);
if (!String.IsNullOrEmpty(Title))
parameters.Add("title", Title);
if (!String.IsNullOrEmpty(TweetID))
parameters.Add("ref_id", TweetID);
if (Uri != null)
parameters.Add("uri", Uri.ToString());
return parameters;
}
+3 -3
View File
@@ -1,5 +1,5 @@
using System;
using PropertyChanged;
using PropertyChanged;
using System;
namespace PocketSharp.Models
{
@@ -15,7 +15,7 @@ namespace PocketSharp.Models
/// <value>
/// The pocket item ID.
/// </value>
public int PocketItemID { get; set; }
public string PocketItemID { get; set; }
/// <summary>
/// Gets or sets the content.
+9
View File
@@ -0,0 +1,9 @@
namespace PocketSharp.Models
{
internal enum PocketBoolean
{
No = 0,
Yes = 1,
IsType = 2
}
}
+127 -79
View File
@@ -1,7 +1,8 @@
using Newtonsoft.Json;
using PropertyChanged;
using System;
using System.Collections.Generic;
using PropertyChanged;
using System.Diagnostics;
namespace PocketSharp.Models
{
@@ -11,6 +12,7 @@ namespace PocketSharp.Models
/// </summary>
[JsonObject]
[ImplementPropertyChanged]
[DebuggerDisplay("Uri = {Uri}, Title = {Title}")]
public class PocketItem
{
/// <summary>
@@ -20,7 +22,34 @@ namespace PocketSharp.Models
/// The ID.
/// </value>
[JsonProperty("item_id")]
public int ID { get; set; }
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 resolved URI.
/// </summary>
/// <value>
/// The resolved URI.
/// </value>
[JsonProperty("resolved_url")]
private Uri _ResolvedUri { get; set; }
/// <summary>
/// Gets or sets the URI.
@@ -28,8 +57,12 @@ namespace PocketSharp.Models
/// <value>
/// The URI.
/// </value>
[JsonProperty("resolved_url")]
public Uri Uri { get; set; }
[JsonIgnore]
public Uri Uri
{
get { return _ResolvedUri ?? _NormalUri; }
set { _NormalUri = value; _ResolvedUri = value; }
}
/// <summary>
/// Gets or sets the title.
@@ -132,7 +165,7 @@ namespace PocketSharp.Models
/// <c>true</c> if this instance has image; otherwise, <c>false</c>.
/// </value>
[JsonProperty("has_image")]
public bool HasImage { get; set; }
private PocketBoolean? _HasImage { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance has video.
@@ -141,7 +174,67 @@ namespace PocketSharp.Models
/// <c>true</c> if this instance has video; otherwise, <c>false</c>.
/// </value>
[JsonProperty("has_video")]
public bool HasVideo { get; set; }
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.
@@ -200,65 +293,44 @@ namespace PocketSharp.Models
/// <summary>
/// Gets or sets the _ tag dictionary.
/// </summary>
/// <value>
/// The _ tag dictionary.
/// </value>
[JsonProperty("tags")]
private Dictionary<string, PocketTag> _TagDictionary { get; set; }
/// <summary>
/// Gets or sets the _ image dictionary.
/// </summary>
/// <value>
/// The _ image dictionary.
/// </value>
[JsonProperty("images")]
private Dictionary<string, PocketImage> _ImageDictionary { get; set; }
/// <summary>
/// Gets or sets the _ video dictionary.
/// </summary>
/// <value>
/// The _ video dictionary.
/// </value>
[JsonProperty("videos")]
private Dictionary<string, PocketVideo> _VideoDictionary { get; set; }
/// <summary>
/// Gets or sets the _ author dictionary.
/// </summary>
/// <value>
/// The _ author dictionary.
/// </value>
[JsonProperty("authors")]
private Dictionary<string, PocketAuthor> _AuthorDictionary { get; set; }
/// <summary>
/// Gets the tags.
/// Gets or sets the tags.
/// </summary>
/// <value>
/// The tags.
/// </value>
[JsonIgnore]
public List<PocketTag> Tags
{
get { return Utilities.DictionaryToList<PocketTag>(_TagDictionary); }
}
[JsonProperty("tags")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketTag>))]
public List<PocketTag> Tags { get; set; }
/// <summary>
/// Gets the images.
/// Gets or sets the images.
/// </summary>
/// <value>
/// The images.
/// </value>
[JsonIgnore]
public List<PocketImage> Images
{
get { return Utilities.DictionaryToList<PocketImage>(_ImageDictionary); }
}
[JsonProperty("images")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketImage>))]
public List<PocketImage> Images { get; set; }
/// <summary>
/// Gets or sets the videos.
/// </summary>
/// <value>
/// The videos.
/// </value>
[JsonProperty("videos")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketVideo>))]
public List<PocketVideo> Videos { get; set; }
/// <summary>
/// Gets or sets the authors.
/// </summary>
/// <value>
/// The authors.
/// </value>
[JsonProperty("authors")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketAuthor>))]
public List<PocketAuthor> Authors { get; set; }
/// <summary>
/// Gets the lead image.
@@ -271,29 +343,5 @@ namespace PocketSharp.Models
{
get { return Images != null && Images.Count > 0 ? Images[0] : null; }
}
/// <summary>
/// Gets the videos.
/// </summary>
/// <value>
/// The videos.
/// </value>
[JsonIgnore]
public List<PocketVideo> Videos
{
get { return Utilities.DictionaryToList<PocketVideo>(_VideoDictionary); }
}
/// <summary>
/// Gets the authors.
/// </summary>
/// <value>
/// The authors.
/// </value>
[JsonIgnore]
public List<PocketAuthor> Authors
{
get { return Utilities.DictionaryToList<PocketAuthor>(_AuthorDictionary); }
}
}
}
+14 -14
View File
@@ -3,20 +3,20 @@ using PropertyChanged;
namespace PocketSharp.Models
{
/// <summary>
/// Tag
/// </summary>
[JsonObject]
[ImplementPropertyChanged]
public class PocketTag
{
/// <summary>
/// Tag
/// Gets or sets the name.
/// </summary>
[JsonObject]
[ImplementPropertyChanged]
public class PocketTag
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
[JsonProperty("tag")]
public string Name { get; set; }
}
/// <value>
/// The name.
/// </value>
[JsonProperty("tag")]
public string Name { get; set; }
}
}
+30 -30
View File
@@ -4,38 +4,38 @@ using PropertyChanged;
namespace PocketSharp.Models
{
/// <summary>
/// Video
/// </summary>
[JsonObject]
[ImplementPropertyChanged]
public class PocketVideo
{
/// <summary>
/// Video
/// Gets or sets the ID.
/// </summary>
[JsonObject]
[ImplementPropertyChanged]
public class PocketVideo
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
/// <value>
/// The ID.
/// </value>
[JsonProperty("video_id")]
public string ID { get; set; }
/// <value>
/// The ID.
/// </value>
[JsonProperty("video_id")]
public string ID { get; set; }
/// <summary>
/// Gets or sets the external ID.
/// </summary>
/// <value>
/// The external ID.
/// </value>
[JsonProperty("vid")]
public string ExternalID { get; set; }
/// <summary>
/// Gets or sets the external ID.
/// </summary>
/// <value>
/// The external ID.
/// </value>
[JsonProperty("vid")]
public string ExternalID { get; set; }
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// The URI.
/// </value>
[JsonProperty("src")]
public Uri Uri { get; set; }
}
/// <summary>
/// Gets or sets the URI.
/// </summary>
/// <value>
/// The URI.
/// </value>
[JsonProperty("src")]
public Uri Uri { get; set; }
}
}
+6 -16
View File
@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
namespace PocketSharp.Models
@@ -24,17 +25,8 @@ namespace PocketSharp.Models
/// <value>
/// The since.
/// </value>
[JsonProperty]
public int Since { get; set; }
/// <summary>
/// Gets or sets the _ item dictionary.
/// </summary>
/// <value>
/// The _ item dictionary.
/// </value>
[JsonProperty("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>
[JsonIgnore]
public List<PocketItem> Items
{
get { return Utilities.DictionaryToList<PocketItem>(ItemDictionary); }
}
[JsonProperty("list")]
[JsonConverter(typeof(ObjectToArrayConverter<PocketItem>))]
public List<PocketItem> Items { get; set; }
}
}
+66 -19
View File
@@ -1,19 +1,20 @@
using PocketSharp.Models;
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.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Net.Http.Headers;
using System.Threading;
using System.Threading.Tasks;
namespace PocketSharp
{
/// <summary>
/// PocketClient
/// </summary>
public partial class PocketClient
public partial class PocketClient : IPocketClient
{
/// <summary>
/// REST client used for the API communication
@@ -23,7 +24,12 @@ namespace PocketSharp
/// <summary>
/// Caches HTTP headers from last response
/// </summary>
private HttpResponseHeaders lastHeaders;
public HttpResponseHeaders lastHeaders;
/// <summary>
/// Caches JSON data from last response
/// </summary>
public string lastResponseData;
/// <summary>
/// The base URL for the Pocket API
@@ -36,35 +42,56 @@ namespace PocketSharp
protected string authentificationUri = "https://getpocket.com/auth/authorize?request_token={0}&redirect_uri={1}";
/// <summary>
/// callback URL for API calls
/// 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>
/// 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>
/// 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, string callbackUri = null)
/// <param name="handler">The HttpMessage handler.</param>
/// <param name="timeout">Request timeout (in seconds).</param>
public PocketClient(string consumerKey, string accessCode = null, string callbackUri = null, HttpMessageHandler handler = null, int? timeout = null)
{
// assign public properties
ConsumerKey = consumerKey;
@@ -82,11 +109,16 @@ namespace PocketSharp
}
// initialize REST client
_restClient = new HttpClient(new HttpClientHandler()
_restClient = new HttpClient(handler ?? new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip
});
if (timeout.HasValue)
{
_restClient.Timeout = TimeSpan.FromSeconds(timeout.Value);
}
// set base uri
_restClient.BaseAddress = baseUri;
@@ -103,15 +135,20 @@ 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="PocketException">No access token available. Use authentification first.</exception>
protected async Task<T> Request<T>(string method, Dictionary<string, string> parameters = null, bool requireAuth = true) where T : class, new()
protected async Task<T> Request<T>(
string method,
CancellationToken cancellationToken,
Dictionary<string, string> parameters = null,
bool requireAuth = true) where T : class, new()
{
if (requireAuth && AccessCode == null)
{
throw new PocketException("SDK error: No access token available. Use authentification first.");
throw new PocketException("SDK error: No access token available. Use authentication first.");
}
// every single Pocket API endpoint requires HTTP POST data
@@ -135,10 +172,16 @@ namespace PocketSharp
// content of the request
request.Content = new FormUrlEncodedContent(parameters);
// call pre request action
if (PreRequest != null)
{
PreRequest(method);
}
// make async request
try
{
response = await _restClient.SendAsync(request);
response = await _restClient.SendAsync(request, cancellationToken);
}
catch (HttpRequestException exc)
{
@@ -154,6 +197,9 @@ namespace PocketSharp
// read response
var responseString = await response.Content.ReadAsStringAsync();
// cache response
lastResponseData = responseString;
responseString = responseString.Replace("[]", "{}");
// deserialize object
@@ -168,7 +214,9 @@ namespace PocketSharp
Converters =
{
new BoolConverter(),
new UnixDateTimeConverter()
new UnixDateTimeConverter(),
new NullableIntConverter(),
new UriConverter()
}
}
);
@@ -182,7 +230,7 @@ namespace PocketSharp
/// </summary>
/// <param name="actionParameters">The action parameters.</param>
/// <returns></returns>
internal async Task<bool> Send(List<ActionParameter> actionParameters)
internal async Task<bool> Send(List<PocketAction> actionParameters, CancellationToken cancellationToken)
{
List<Dictionary<string, object>> actionParamList = new List<Dictionary<string, object>>();
@@ -195,7 +243,7 @@ namespace PocketSharp
"actions", JsonConvert.SerializeObject(actionParamList)
}};
Modify response = await Request<Modify>("send", parameters);
Modify response = await Request<Modify>("send", cancellationToken, parameters);
return response.Status;
}
@@ -206,10 +254,9 @@ namespace PocketSharp
/// </summary>
/// <param name="actionParameter">The action parameter.</param>
/// <returns></returns>
internal async Task<bool> Send(ActionParameter actionParameter)
internal async Task<bool> Send(PocketAction actionParameter, CancellationToken cancellationToken)
{
bool response = await Send(new List<ActionParameter>() { actionParameter });
return response;
return await Send(new List<PocketAction>() { actionParameter }, cancellationToken);
}
+16 -21
View File
@@ -42,8 +42,10 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Components\Statistics.cs" />
<Compile Include="IPocketClient.cs" />
<Compile Include="Models\Parameters\RegisterParameters.cs" />
<Compile Include="Models\PocketArticle.cs" />
<Compile Include="Models\PocketBoolean.cs" />
<Compile Include="Models\PocketLimits.cs" />
<Compile Include="Models\PocketStatistics.cs" />
<Compile Include="Utilities\PocketException.cs" />
@@ -53,7 +55,7 @@
<Compile Include="Components\ModifyTags.cs" />
<Compile Include="Components\Get.cs" />
<Compile Include="Utilities\JsonExtensions.cs" />
<Compile Include="Models\Parameters\ActionParameter.cs" />
<Compile Include="Models\PocketAction.cs" />
<Compile Include="Models\Parameters\AddParameters.cs" />
<Compile Include="Models\Parameters\ModifyParameters.cs" />
<Compile Include="Models\Parameters\Parameters.cs" />
@@ -70,16 +72,15 @@
<Compile Include="Models\Response\ResponseBase.cs" />
<Compile Include="Models\Response\Retrieve.cs" />
<Compile Include="PocketClient.cs" />
<Compile Include="PocketReader.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities\Utilities.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Threading.Tasks.Extensions">
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.16\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.Async.1.0.165\lib\portable-net40+sl4+win8+wp71\Microsoft.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\packages\Newtonsoft.Json.5.0.8\lib\portable-net40+sl4+wp7+win8\Newtonsoft.Json.dll</HintPath>
@@ -89,33 +90,27 @@
<Private>False</Private>
</Reference>
<Reference Include="System.IO">
<HintPath>..\packages\Microsoft.Bcl.1.1.3\lib\portable-net40+sl4+win8+wp71\System.IO.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl4+win8+wp71\System.IO.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http">
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\portable-net40+sl4+win8+wp71\System.Net.Http.dll</HintPath>
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Extensions">
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Extensions.dll</HintPath>
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Primitives">
<HintPath>..\packages\Microsoft.Net.Http.2.2.15\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Primitives.dll</HintPath>
<HintPath>..\packages\Microsoft.Net.Http.2.2.18\lib\portable-net40+sl4+win8+wp71\System.Net.Http.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Runtime">
<HintPath>..\packages\Microsoft.Bcl.1.1.3\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl4+win8+wp71\System.Runtime.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks">
<HintPath>..\packages\Microsoft.Bcl.1.1.3\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll</HintPath>
<HintPath>..\packages\Microsoft.Bcl.1.1.6\lib\portable-net40+sl4+win8+wp71\System.Threading.Tasks.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="FodyWeavers.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\PortablePorts\NReadability\NReadability.csproj">
<Project>{14c3ee6a-54a4-4a37-8b56-d52a3802f1c2}</Project>
<Name>NReadability</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
@@ -124,12 +119,12 @@
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" />
</Target>
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.10\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<Import Project="Fody.targets" />
<Import Project="..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets" Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" />
<Target Name="EnsureBclBuildImported" BeforeTargets="BeforeBuild" Condition="'$(BclBuildImported)' == ''">
<Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=317567." HelpKeyword="BCLBUILD2001" />
<Error Condition="Exists('..\packages\Microsoft.Bcl.Build.1.0.13\tools\Microsoft.Bcl.Build.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://go.microsoft.com/fwlink/?LinkID=317568." HelpKeyword="BCLBUILD2002" />
</Target>
<!-- 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">
+1 -1
View File
@@ -18,6 +18,6 @@
]]>
</releaseNotes>
<copyright>Copyright by cee, 2013</copyright>
<tags>PocketAPI Pocket API PocketSharp Tobias Klika cee NReadability Reader Article SDK Pockem</tags>
<tags>PocketAPI Pocket API PocketSharp Tobias Klika cee NReadability SgmlReader Reader Article SDK Pockem</tags>
</metadata>
</package>
+3 -6
View File
@@ -1,7 +1,4 @@
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Reflection;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
@@ -25,5 +22,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.2")]
[assembly: AssemblyFileVersion("2.2.2")]
[assembly: AssemblyVersion("3.0.0")]
[assembly: AssemblyFileVersion("3.0.0")]
+112 -2
View File
@@ -1,6 +1,8 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace PocketSharp
{
@@ -14,7 +16,7 @@ namespace PocketSharp
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return reader.Value.ToString() == "1";
return reader.Value == null ? false : (reader.Value.ToString() == "1");
}
public override bool CanConvert(Type objectType)
@@ -37,7 +39,7 @@ namespace PocketSharp
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if(reader.Value.ToString() == "0")
if (reader.Value.ToString() == "0")
{
return null;
}
@@ -45,4 +47,112 @@ namespace PocketSharp
return new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(Convert.ToDouble(reader.Value)).ToLocalTime();
}
}
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 && Uri.IsWellFormedUriString(reader.Value.ToString(), UriKind.Absolute))
{
return new Uri(reader.Value.ToString());
}
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<List<T>> where T : new()
{
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jObject;
List<T> result = new List<T>();
T target;
// object is an array
if (reader.TokenType == JsonToken.StartArray)
{
return serializer.Deserialize<List<T>>(reader);
}
else if (reader.TokenType == JsonToken.Null)
{
return null;
}
try
{
jObject = JObject.Load(reader);
}
catch
{
return null;
}
// Populate the object properties
foreach (KeyValuePair<string, JToken> item in jObject)
{
target = new T();
serializer.Populate(item.Value.CreateReader(), target);
result.Add(target);
}
return result;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override List<T> Create(Type objectType)
{
return new List<T>();
}
}
}
+3 -26
View File
@@ -12,7 +12,9 @@ namespace PocketSharp
/// converts DateTime to an UNIX timestamp
/// </summary>
/// <param name="dateTime">The date.</param>
/// <returns>UNIX timestamp</returns>
/// <returns>
/// UNIX timestamp
/// </returns>
public static int? GetUnixTimestamp(DateTime? dateTime)
{
if (dateTime == null)
@@ -22,30 +24,5 @@ namespace PocketSharp
return (int)((DateTime)dateTime - new DateTime(1970, 1, 1)).TotalSeconds;
}
/// <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;
}
}
}
+4 -4
View File
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Fody" version="1.17.4.0" targetFramework="portable-net403+sl40+wp71+win" />
<package id="Microsoft.Bcl" version="1.1.3" targetFramework="portable-net45+sl40+wp71+win" />
<package id="Microsoft.Bcl.Async" version="1.0.16" targetFramework="portable-net45+sl40+wp71+win" />
<package id="Microsoft.Bcl.Build" version="1.0.10" targetFramework="portable-net45+sl40+wp71+win" />
<package id="Microsoft.Net.Http" version="2.2.15" targetFramework="portable-net403+sl40+wp71+win" />
<package id="Microsoft.Bcl" version="1.1.6" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Microsoft.Bcl.Async" version="1.0.165" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Microsoft.Bcl.Build" version="1.0.13" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Microsoft.Net.Http" version="2.2.18" targetFramework="portable-win+net403+sl40+wp71" />
<package id="Newtonsoft.Json" version="5.0.8" targetFramework="portable-net45+sl40+wp71+win" />
<package id="PropertyChanged.Fody" version="1.41.0.0" targetFramework="portable-net403+sl40+wp71+win" />
</packages>
@@ -1,5 +1,4 @@
using System;
namespace PocketSharp.Ports.NReadability
{
public class DomSerializationParams
@@ -48,6 +47,10 @@ namespace PocketSharp.Ports.NReadability
/// </summary>
public bool BodyOnly { get; set; }
/// <summary>
/// Remove headline of website
/// </summary>
public bool NoHeadline { get; set; }
#endregion
}
}
@@ -92,6 +92,16 @@ namespace PocketSharp.Ports.NReadability
}
}
if (domSerializationParams.NoHeadline)
{
var h1 = document.Root.GetElementsByTagName("h1").FirstOrDefault();
if (h1 != null)
{
result = result.Replace(h1.ToString(), "");
}
}
return result;
}
+17 -13
View File
@@ -2,12 +2,18 @@
**PocketSharp** is a C#.NET portable class library that integrates the [Pocket API v3](http://getpocket.com/developer).
## Install using [NuGet](https://www.nuget.org/packages/PocketSharp/)
## Install [PocketSharp](https://www.nuget.org/packages/PocketSharp/) using NuGet
```
Install-Package PocketSharp
```
for the [PocketSharp.Reader](https://www.nuget.org/packages/PocketSharp.Reader/)
```
Install-Package PocketSharp.Reader
```
## Documentation
See [wiki](https://github.com/ceee/PocketSharp/wiki)
@@ -24,7 +30,7 @@ PocketClient client = new PocketClient("[YOUR_CONSUMER_KEY]", "[YOUR_ACCESS_CODE
List<PocketItem> items = await client.Search("css");
items.ForEach(
item => Debug.WriteLine(item.ID + " | " + item.Title)
item => Debug.WriteLine(item.ID + " | " + item.Title)
);
```
@@ -34,14 +40,14 @@ Which will output:
345541438 | Editr - HTML, CSS, JavaScript playground
251743431 | CSS Architecture
343693149 | CSS3 Transitions - Thank God We Have A Specification!
...
...
---
## Supported platforms
PocketSharp is a **Portable Class Library** (since 1.0.0), therefore it's compatible with multiple platforms:
PocketSharp is a **Portable Class Library**, therefore it's compatible with multiple platforms:
- **.NET** >= 4.5 (including WPF)
- **Silverlight** >= 4
@@ -52,21 +58,19 @@ You can find examples for Silverlight 5, WP8 and WPF in the `PocketSharp.Example
## What's next?
- `cancellationToken` support for all methods
- support HTML injection into content from PocketArticle (maybe remove title from Article)
- benchmarking download of large lists
- benchmarking of search algorithm
- Update website and merge into plugin repository site
- [ ] Preferences API, if Pocket will ever release it to the public -.-
## Dependencies
- [Microsoft.Bcl.Async](https://www.nuget.org/packages/Microsoft.Bcl.Async/)
- [Microsoft.Net.Http](https://www.nuget.org/packages/Microsoft.Net.Http/)
- [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json/)
- [PropertyChanged.Fody](https://github.com/Fody/PropertyChanged)
- [Microsoft.Bcl.Async](https://www.nuget.org/packages/Microsoft.Bcl.Async/) _(used in PocketSharp & PocketSharp.Reader)_
- [Microsoft.Net.Http](https://www.nuget.org/packages/Microsoft.Net.Http/) _(used in PocketSharp & PocketSharp.Reader)_
- [Newtonsoft.Json](https://www.nuget.org/packages/Newtonsoft.Json/) _(only for PocketSharp project)_
- [PropertyChanged.Fody](https://github.com/Fody/PropertyChanged) _(only for PocketSharp project)_
## Forked Dependencies
_used in PocketSharp.Reader_
- [NReadability](https://github.com/marek-stoj/NReadability) - converted to a PCL with minor adaptations
- [SgmlReader](https://github.com/MindTouch/SGMLReader) - converted to a PCL