blogger/gphotos: share OLW album, get download url for images, remove image editing; reupload a new image every time
This commit is contained in:
parent
5fe336f957
commit
fa95f4a9af
|
@ -37,6 +37,7 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
{
|
{
|
||||||
// These URLs map to OAuth2 permission scopes for Google Blogger.
|
// These URLs map to OAuth2 permission scopes for Google Blogger.
|
||||||
public static string PhotosLibraryServiceScope = PhotosLibraryService.Scope.Photoslibrary;
|
public static string PhotosLibraryServiceScope = PhotosLibraryService.Scope.Photoslibrary;
|
||||||
|
public static string PhotosLibraryServiceSharingScope = PhotosLibraryService.Scope.PhotoslibrarySharing;
|
||||||
public static string BloggerServiceScope = BloggerService.Scope.Blogger;
|
public static string BloggerServiceScope = BloggerService.Scope.Blogger;
|
||||||
public static char LabelDelimiter = ',';
|
public static char LabelDelimiter = ',';
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
// browser window and prompt the user for permissions and then write those permissions to the IDataStore.
|
// browser window and prompt the user for permissions and then write those permissions to the IDataStore.
|
||||||
return GoogleWebAuthorizationBroker.AuthorizeAsync(
|
return GoogleWebAuthorizationBroker.AuthorizeAsync(
|
||||||
GoogleClientSecrets.Load(ClientSecretsStream).Secrets,
|
GoogleClientSecrets.Load(ClientSecretsStream).Secrets,
|
||||||
new List<string>() { BloggerServiceScope, PhotosLibraryServiceScope },
|
new List<string>() { BloggerServiceScope, PhotosLibraryServiceScope, PhotosLibraryServiceSharingScope },
|
||||||
blogId,
|
blogId,
|
||||||
taskCancellationToken,
|
taskCancellationToken,
|
||||||
GetCredentialsDataStoreForBlog(blogId));
|
GetCredentialsDataStoreForBlog(blogId));
|
||||||
|
@ -257,7 +258,7 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
{
|
{
|
||||||
ClientSecretsStream = ClientSecretsStream,
|
ClientSecretsStream = ClientSecretsStream,
|
||||||
DataStore = GetCredentialsDataStoreForBlog(tc.Username),
|
DataStore = GetCredentialsDataStoreForBlog(tc.Username),
|
||||||
Scopes = new List<string>() { BloggerServiceScope, PhotosLibraryServiceScope },
|
Scopes = new List<string>() { BloggerServiceScope, PhotosLibraryServiceScope, PhotosLibraryServiceSharingScope },
|
||||||
});
|
});
|
||||||
|
|
||||||
var loadTokenTask = flow.LoadTokenAsync(tc.Username, CancellationToken.None);
|
var loadTokenTask = flow.LoadTokenAsync(tc.Username, CancellationToken.None);
|
||||||
|
@ -626,43 +627,7 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
albumName = StringHelper.Reverse(chunks[1]);
|
albumName = StringHelper.Reverse(chunks[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
string EDIT_MEDIA_LINK = "EditMediaLink";
|
return PostNewImage(albumName, path, uploadContext.BlogId);
|
||||||
string srcUrl;
|
|
||||||
string editUri = uploadContext.Settings.GetString(EDIT_MEDIA_LINK, null);
|
|
||||||
if (editUri == null || editUri.Length == 0)
|
|
||||||
{
|
|
||||||
PostNewImage(albumName, path, uploadContext.BlogId, out srcUrl, out editUri);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
UpdateImage(editUri, path, out srcUrl, out editUri);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Trace.Fail(e.ToString());
|
|
||||||
if (e is WebException)
|
|
||||||
HttpRequestHelper.LogException((WebException)e);
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
srcUrl = null; // compiler complains without this line
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// couldn't update existing image? try posting a new one
|
|
||||||
PostNewImage(albumName, path, uploadContext.BlogId, out srcUrl, out editUri);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
if (!success)
|
|
||||||
throw; // rethrow the exception from the update, not the post
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uploadContext.Settings.SetString(EDIT_MEDIA_LINK, editUri);
|
|
||||||
|
|
||||||
return srcUrl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoAfterPublishUploadWork(IFileUploadContext uploadContext)
|
public void DoAfterPublishUploadWork(IFileUploadContext uploadContext)
|
||||||
|
@ -716,7 +681,19 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
// Get the URL of the Google Photos 'Open Live Writer' album, creating it if it doesn't exist
|
// Get the URL of the Google Photos 'Open Live Writer' album, creating it if it doesn't exist
|
||||||
var library = GetPhotosLibraryService();
|
var library = GetPhotosLibraryService();
|
||||||
var matchingAlbums = GetAllAlbums(library).Where(album => album.Title == albumName);
|
var matchingAlbums = GetAllAlbums(library).Where(album => album.Title == albumName);
|
||||||
if (matchingAlbums.Count() > 0) return matchingAlbums.First().Id; // Return the ID of the album if it exists
|
if (matchingAlbums.Count() > 0)
|
||||||
|
{
|
||||||
|
// Check if album has sharing permissions and add them if not
|
||||||
|
if (matchingAlbums.First().ShareInfo == null)
|
||||||
|
library.Albums.Share(new ShareAlbumRequest() {
|
||||||
|
SharedAlbumOptions = new SharedAlbumOptions()
|
||||||
|
{
|
||||||
|
IsCollaborative = false, IsCommentable = false
|
||||||
|
}
|
||||||
|
}, matchingAlbums.First().Id).Execute();
|
||||||
|
|
||||||
|
return matchingAlbums.First().Id; // Return the ID of the album if it exists
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to create the album as it does not exist
|
// Attempt to create the album as it does not exist
|
||||||
var newAlbum = library.Albums.Create(new CreateAlbumRequest()
|
var newAlbum = library.Albums.Create(new CreateAlbumRequest()
|
||||||
|
@ -727,21 +704,24 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
}
|
}
|
||||||
}).Execute();
|
}).Execute();
|
||||||
|
|
||||||
|
// Share the new album
|
||||||
|
library.Albums.Share(new ShareAlbumRequest()
|
||||||
|
{
|
||||||
|
SharedAlbumOptions = new SharedAlbumOptions()
|
||||||
|
{
|
||||||
|
IsCollaborative = false,
|
||||||
|
IsCommentable = false
|
||||||
|
}
|
||||||
|
}, newAlbum.Id).Execute();
|
||||||
// Return the ID of the new album
|
// Return the ID of the new album
|
||||||
return newAlbum.Id;
|
return newAlbum.Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PostNewImage(string albumName, string filename, string blogId, out string srcUrl, out string editUri)
|
private string PostNewImage(string albumName, string filename, string blogId)
|
||||||
{
|
{
|
||||||
var albumId = GetBlogImagesAlbum(albumName, blogId);
|
var albumId = GetBlogImagesAlbum(albumName, blogId);
|
||||||
var library = GetPhotosLibraryService();
|
var library = GetPhotosLibraryService();
|
||||||
|
|
||||||
/* Uploading an image to Google Photos from a filename is a multiple step process
|
|
||||||
* 1. Create a reading System.IO.FileStream on the given filename
|
|
||||||
* 2. begin the file upload
|
|
||||||
* 3. Execute a MediaItems BatchCreate request to create the metadata on Google Photos */
|
|
||||||
|
|
||||||
|
|
||||||
// Create a FileStream
|
// Create a FileStream
|
||||||
var imageFileStream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
|
var imageFileStream = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);
|
||||||
|
|
||||||
|
@ -775,59 +755,10 @@ namespace OpenLiveWriter.BlogClient.Clients
|
||||||
}
|
}
|
||||||
}).Execute();
|
}).Execute();
|
||||||
|
|
||||||
// TODO correctly format baseUrl to include width parameter
|
// Retrieve the appropiate Base URL for inlining the image.
|
||||||
srcUrl = batchCreateResponse.NewMediaItemResults.First().MediaItem.BaseUrl;
|
var mediaItem = library.MediaItems.Get(batchCreateResponse.NewMediaItemResults.First().MediaItem.Id).Execute();
|
||||||
// TODO change from edit URI into and edit token or ID
|
|
||||||
editUri = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateImage(string editUri, string filename, out string srcUrl, out string newEditUri)
|
return mediaItem.BaseUrl + "=d"; // 'd' Base URL parameter for Download
|
||||||
{
|
|
||||||
for (int retry = 0; retry < MaxRetries; retry++)
|
|
||||||
{
|
|
||||||
var transientCredentials = Login();
|
|
||||||
HttpWebResponse response;
|
|
||||||
bool conflict = false;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
response = RedirectHelper.GetResponse(editUri, new RedirectHelper.RequestFactory(new UploadFileRequestFactory(this, filename, "PUT").Create));
|
|
||||||
}
|
|
||||||
catch (WebException we)
|
|
||||||
{
|
|
||||||
if (retry < MaxRetries - 1 &&
|
|
||||||
we.Response as HttpWebResponse != null)
|
|
||||||
{
|
|
||||||
if (((HttpWebResponse)we.Response).StatusCode == HttpStatusCode.Conflict)
|
|
||||||
{
|
|
||||||
response = (HttpWebResponse)we.Response;
|
|
||||||
conflict = true;
|
|
||||||
}
|
|
||||||
else if (((HttpWebResponse)we.Response).StatusCode == HttpStatusCode.Forbidden)
|
|
||||||
{
|
|
||||||
// HTTP 403 Forbidden means our OAuth access token is not valid.
|
|
||||||
RefreshAccessToken(transientCredentials);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
using (Stream s = response.GetResponseStream())
|
|
||||||
{
|
|
||||||
ParseMediaEntry(s, out srcUrl, out newEditUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conflict)
|
|
||||||
{
|
|
||||||
return; // success!
|
|
||||||
}
|
|
||||||
|
|
||||||
editUri = newEditUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
Trace.Fail("Should never get here");
|
|
||||||
throw new ApplicationException("Should never get here");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ParseMediaEntry(Stream s, out string srcUrl, out string editUri)
|
private void ParseMediaEntry(Stream s, out string srcUrl, out string editUri)
|
||||||
|
|
Loading…
Reference in New Issue