Merge pull request #371 from willduff/issue247

Issue #247 - Support loading more than 500 Google Blogger posts
This commit is contained in:
Will Duff 2016-02-10 08:24:46 -08:00
commit 5c8bcd9206
1 changed files with 82 additions and 15 deletions

View File

@ -37,6 +37,11 @@ namespace OpenLiveWriter.BlogClient.Clients
public static string BloggerServiceScope = BloggerService.Scope.Blogger;
public static char LabelDelimiter = ',';
/// <summary>
/// Maximum number of results the Google Blogger v3 API will return in one request.
/// </summary>
public static int MaxResultsPerRequest = 500;
public static Task<UserCredential> GetOAuth2AuthorizationAsync(string blogId, CancellationToken taskCancellationToken)
{
// This async task will either find cached credentials in the IDataStore provided, or it will pop open a
@ -337,8 +342,14 @@ namespace OpenLiveWriter.BlogClient.Clients
return new BlogPostKeyword[] { };
}
private PostList ListRecentPosts(string blogId, int maxPosts, DateTime? now, PostsResource.ListRequest.StatusEnum status)
private PostList ListRecentPosts(string blogId, int maxPosts, DateTime? now, PostsResource.ListRequest.StatusEnum status, PostList previousPage)
{
if (previousPage != null && string.IsNullOrWhiteSpace(previousPage.NextPageToken))
{
// The previous page was also the last page, so do nothing and return an empty list.
return new PostList();
}
var recentPostsRequest = GetService().Posts.List(blogId);
if (now.HasValue)
{
@ -348,21 +359,46 @@ namespace OpenLiveWriter.BlogClient.Clients
recentPostsRequest.MaxResults = maxPosts;
recentPostsRequest.OrderBy = PostsResource.ListRequest.OrderByEnum.Published;
recentPostsRequest.Status = status;
recentPostsRequest.PageToken = previousPage?.NextPageToken;
return recentPostsRequest.Execute();
}
public BlogPost[] GetRecentPosts(string blogId, int maxPosts, bool includeCategories, DateTime? now)
{
var draftRecentPostsList = ListRecentPosts(blogId, maxPosts, now, PostsResource.ListRequest.StatusEnum.Draft);
var liveRecentPostsList = ListRecentPosts(blogId, maxPosts, now, PostsResource.ListRequest.StatusEnum.Live);
var scheduledRecentPostsList = ListRecentPosts(blogId, maxPosts, now, PostsResource.ListRequest.StatusEnum.Scheduled);
// Blogger requires separate API calls to get drafts vs. live vs. scheduled posts. We aggregate each
// type of post separately.
IList<Post> draftRecentPosts = new List<Post>();
IList<Post> liveRecentPosts = new List<Post>();
IList<Post> scheduledRecentPosts = new List<Post>();
IEnumerable<Post> allPosts = new List<Post>();
var draftRecentPosts = draftRecentPostsList.Items ?? new List<Post>();
var liveRecentPosts = liveRecentPostsList.Items ?? new List<Post>();
var scheduledRecentPosts = scheduledRecentPostsList.Items ?? new List<Post>();
// We keep around the PostList returned by each request to support pagination.
PostList draftRecentPostsList = null;
PostList liveRecentPostsList = null;
PostList scheduledRecentPostsList = null;
var allPosts = draftRecentPosts.Concat(liveRecentPosts).Concat(scheduledRecentPosts);
// Google has a per-request results limit on their API.
var maxResultsPerRequest = Math.Min(maxPosts, MaxResultsPerRequest);
// We break out of the following loop depending on which one of these two cases we hit:
// (a) the number of all blog posts ever posted to this blog is greater than maxPosts, so eventually
// allPosts.count() will exceed maxPosts and we can stop making requests.
// (b) the number of all blog posts ever posted to this blog is less than maxPosts, so eventually our
// calls to ListRecentPosts() will return 0 results and we need to stop making requests.
do
{
draftRecentPostsList = ListRecentPosts(blogId, maxResultsPerRequest, now, PostsResource.ListRequest.StatusEnum.Draft, draftRecentPostsList);
liveRecentPostsList = ListRecentPosts(blogId, maxResultsPerRequest, now, PostsResource.ListRequest.StatusEnum.Live, liveRecentPostsList);
scheduledRecentPostsList = ListRecentPosts(blogId, maxResultsPerRequest, now, PostsResource.ListRequest.StatusEnum.Scheduled, scheduledRecentPostsList);
draftRecentPosts = draftRecentPostsList?.Items ?? new List<Post>();
liveRecentPosts = liveRecentPostsList?.Items ?? new List<Post>();
scheduledRecentPosts = scheduledRecentPostsList?.Items ?? new List<Post>();
allPosts = allPosts.Concat(draftRecentPosts).Concat(liveRecentPosts).Concat(scheduledRecentPosts);
} while (allPosts.Count() < maxPosts && (draftRecentPosts.Count > 0 || liveRecentPosts.Count > 0 || scheduledRecentPosts.Count > 0));
return allPosts
.OrderByDescending(p => p.Published)
.Take(maxPosts)
@ -430,22 +466,53 @@ namespace OpenLiveWriter.BlogClient.Clients
return ConvertToBlogPost(getPageRequest.Execute());
}
private PageList ListPages(string blogId, int? maxPages, PagesResource.ListRequest.StatusEnum status)
private PageList ListPages(string blogId, int? maxPages, PagesResource.ListRequest.StatusEnum status, PageList previousPage)
{
if (previousPage != null && string.IsNullOrWhiteSpace(previousPage.NextPageToken))
{
// The previous page was also the last page, so do nothing and return an empty list.
return new PageList();
}
var getPagesRequest = GetService().Pages.List(blogId);
getPagesRequest.MaxResults = maxPages;
if (maxPages.HasValue)
{
// Google has a per-request results limit on their API.
getPagesRequest.MaxResults = Math.Min(maxPages.Value, MaxResultsPerRequest);
}
getPagesRequest.Status = status;
return getPagesRequest.Execute();
}
private IEnumerable<Page> ListAllPages(string blogId, int? maxPages)
{
var draftPageList = ListPages(blogId, maxPages, PagesResource.ListRequest.StatusEnum.Draft);
var livePageList = ListPages(blogId, maxPages, PagesResource.ListRequest.StatusEnum.Live);
// Blogger requires separate API calls to get drafts vs. live vs. scheduled posts. We aggregate each
// type of post separately.
IList<Page> draftPages = new List<Page>();
IList<Page> livePages = new List<Page>();
IEnumerable<Page> allPages = new List<Page>();
var draftPages = draftPageList.Items ?? new List<Page>();
var livePages = livePageList.Items ?? new List<Page>();
return draftPages.Concat(livePages);
// We keep around the PageList returned by each request to support pagination.
PageList draftPagesList = null;
PageList livePagesList = null;
// We break out of the following loop depending on which one of these two cases we hit:
// (a) the number of all blog pages ever posted to this blog is greater than maxPages, so eventually
// allPages.count() will exceed maxPages and we can stop making requests.
// (b) the number of all blog pages ever posted to this blog is less than maxPages, so eventually our
// calls to ListPages() will return 0 results and we need to stop making requests.
do
{
draftPagesList = ListPages(blogId, maxPages, PagesResource.ListRequest.StatusEnum.Draft, draftPagesList);
livePagesList = ListPages(blogId, maxPages, PagesResource.ListRequest.StatusEnum.Live, livePagesList);
draftPages = draftPagesList?.Items ?? new List<Page>();
livePages = livePagesList?.Items ?? new List<Page>();
allPages = allPages.Concat(draftPages).Concat(livePages);
} while (allPages.Count() < maxPages && (draftPages.Count > 0 || livePages.Count > 0));
return allPages;
}
public PageInfo[] GetPageList(string blogId)