Google photos update for Picasa deprecation (#3890)

* Add new object classes
Update scope
Update album list url
Remove extra headers

* Implement new albums

* Update GooglePhotos to new API

* Add create album button

* Fix redundancy
This commit is contained in:
Matthew Burnett 2019-01-22 02:57:43 -05:00 committed by Jaex
parent 017c19cd21
commit 5e9c3c43b6
6 changed files with 9895 additions and 2113 deletions

View file

@ -712,6 +712,7 @@ private void InitializeComponent()
this.txtPhotobucketVerificationCode = new System.Windows.Forms.TextBox();
this.lblPhotobucketAccountStatus = new System.Windows.Forms.Label();
this.tpGooglePhotos = new System.Windows.Forms.TabPage();
this.cbGooglePhotosIsPublic = new System.Windows.Forms.CheckBox();
this.txtPicasaAlbumID = new System.Windows.Forms.TextBox();
this.lblPicasaAlbumID = new System.Windows.Forms.Label();
this.lvPicasaAlbumList = new System.Windows.Forms.ListView();
@ -742,6 +743,9 @@ private void InitializeComponent()
this.tsmiCustomUploaderExamples = new System.Windows.Forms.ToolStripMenuItem();
this.tsmiCustomUploaderExportAll = new System.Windows.Forms.ToolStripMenuItem();
this.actRapidShareAccountType = new ShareX.UploadersLib.AccountTypeControl();
this.btnGooglePhotosCreateAlbum = new System.Windows.Forms.Button();
this.txtGooglePhotosCreateAlbumName = new System.Windows.Forms.TextBox();
this.lblGooglePhotosCreateAlbumName = new System.Windows.Forms.Label();
this.tscCustomUploaderResponseText.ContentPanel.SuspendLayout();
this.tscCustomUploaderResponseText.TopToolStripPanel.SuspendLayout();
this.tscCustomUploaderResponseText.SuspendLayout();
@ -5727,6 +5731,10 @@ private void InitializeComponent()
// tpGooglePhotos
//
this.tpGooglePhotos.BackColor = System.Drawing.SystemColors.Window;
this.tpGooglePhotos.Controls.Add(this.lblGooglePhotosCreateAlbumName);
this.tpGooglePhotos.Controls.Add(this.txtGooglePhotosCreateAlbumName);
this.tpGooglePhotos.Controls.Add(this.btnGooglePhotosCreateAlbum);
this.tpGooglePhotos.Controls.Add(this.cbGooglePhotosIsPublic);
this.tpGooglePhotos.Controls.Add(this.txtPicasaAlbumID);
this.tpGooglePhotos.Controls.Add(this.lblPicasaAlbumID);
this.tpGooglePhotos.Controls.Add(this.lvPicasaAlbumList);
@ -5735,6 +5743,13 @@ private void InitializeComponent()
resources.ApplyResources(this.tpGooglePhotos, "tpGooglePhotos");
this.tpGooglePhotos.Name = "tpGooglePhotos";
//
// cbGooglePhotosIsPublic
//
resources.ApplyResources(this.cbGooglePhotosIsPublic, "cbGooglePhotosIsPublic");
this.cbGooglePhotosIsPublic.Name = "cbGooglePhotosIsPublic";
this.cbGooglePhotosIsPublic.UseVisualStyleBackColor = true;
this.cbGooglePhotosIsPublic.CheckedChanged += new System.EventHandler(this.cbGooglePhotosIsPublic_CheckedChanged);
//
// txtPicasaAlbumID
//
resources.ApplyResources(this.txtPicasaAlbumID, "txtPicasaAlbumID");
@ -5945,6 +5960,23 @@ private void InitializeComponent()
this.actRapidShareAccountType.Name = "actRapidShareAccountType";
this.actRapidShareAccountType.SelectedAccountType = ShareX.UploadersLib.AccountType.Anonymous;
//
// btnGooglePhotosCreateAlbum
//
resources.ApplyResources(this.btnGooglePhotosCreateAlbum, "btnGooglePhotosCreateAlbum");
this.btnGooglePhotosCreateAlbum.Name = "btnGooglePhotosCreateAlbum";
this.btnGooglePhotosCreateAlbum.UseVisualStyleBackColor = true;
this.btnGooglePhotosCreateAlbum.Click += new System.EventHandler(this.btnGooglePhotosCreateAlbum_Click);
//
// txtGooglePhotosCreateAlbumName
//
resources.ApplyResources(this.txtGooglePhotosCreateAlbumName, "txtGooglePhotosCreateAlbumName");
this.txtGooglePhotosCreateAlbumName.Name = "txtGooglePhotosCreateAlbumName";
//
// lblGooglePhotosCreateAlbumName
//
resources.ApplyResources(this.lblGooglePhotosCreateAlbumName, "lblGooglePhotosCreateAlbumName");
this.lblGooglePhotosCreateAlbumName.Name = "lblGooglePhotosCreateAlbumName";
//
// UploadersConfigForm
//
resources.ApplyResources(this, "$this");
@ -6841,5 +6873,9 @@ private void InitializeComponent()
private System.Windows.Forms.ToolStripButton tsbCustomUploaderJSONFormat;
private System.Windows.Forms.ToolStripButton tsbCustomUploaderXMLFormat;
private System.Windows.Forms.ToolStripButton tsbCustomUploaderCopyResponseText;
private System.Windows.Forms.CheckBox cbGooglePhotosIsPublic;
private System.Windows.Forms.Label lblGooglePhotosCreateAlbumName;
private System.Windows.Forms.TextBox txtGooglePhotosCreateAlbumName;
private System.Windows.Forms.Button btnGooglePhotosCreateAlbum;
}
}

View file

@ -299,6 +299,7 @@ private void LoadImageUploaderSettings()
}
txtPicasaAlbumID.Text = Config.PicasaAlbumID;
cbGooglePhotosIsPublic.Checked = Config.GooglePhotosIsPublic;
#endregion Google Photos
@ -1190,6 +1191,17 @@ private void lvPicasaAlbumList_SelectedIndexChanged(object sender, EventArgs e)
}
}
private void cbGooglePhotosIsPublic_CheckedChanged(object sender, EventArgs e)
{
Config.GooglePhotosIsPublic = cbGooglePhotosIsPublic.Checked;
}
private void btnGooglePhotosCreateAlbum_Click(object sender, EventArgs e)
{
GooglePhotosCreateAlbum(txtGooglePhotosCreateAlbumName.Text);
GooglePhotosRefreshAlbumList();
}
#endregion Google Photos
#region Chevereto

File diff suppressed because it is too large Load diff

View file

@ -244,6 +244,14 @@ public void GooglePhotosRefreshAlbumList()
}
}
public void GooglePhotosCreateAlbum(string albumName)
{
if (OAuth2Info.CheckOAuth(Config.PicasaOAuth2Info))
{
new GooglePhotos(Config.PicasaOAuth2Info).CreateAlbum(albumName);
}
}
#endregion Google Photos
#region Amazon S3

View file

@ -23,14 +23,13 @@ You should have received a copy of the GNU General Public License
#endregion License Information (GPL v3)
using ShareX.HelpersLib;
using ShareX.UploadersLib.Properties;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Xml.Linq;
using Newtonsoft.Json;
namespace ShareX.UploadersLib.ImageUploaders
{
@ -49,27 +48,25 @@ public override GenericUploader CreateUploader(UploadersConfig config, TaskRefer
{
return new GooglePhotos(config.PicasaOAuth2Info)
{
AlbumID = config.PicasaAlbumID
AlbumID = config.PicasaAlbumID,
IsPublic = config.GooglePhotosIsPublic
};
}
public override TabPage GetUploadersConfigTabPage(UploadersConfigForm form) => form.tpGooglePhotos;
}
public class GooglePhotos : ImageUploader, IOAuth2
public sealed class GooglePhotos : ImageUploader, IOAuth2
{
private GoogleOAuth2 GoogleAuth { get; set; }
public string AlbumID { get; set; }
private static readonly XNamespace AtomNS = "http://www.w3.org/2005/Atom";
private static readonly XNamespace MediaNS = "http://search.yahoo.com/mrss/";
private static readonly XNamespace GPhotoNS = "http://schemas.google.com/photos/2007";
public bool IsPublic { get; set; }
public GooglePhotos(OAuth2Info oauth)
{
GoogleAuth = new GoogleOAuth2(oauth, this)
{
Scope = "https://picasaweb.google.com/data"
Scope = "https://www.googleapis.com/auth/photoslibrary https://www.googleapis.com/auth/photoslibrary.sharing"
};
}
@ -95,11 +92,22 @@ public bool GetAccessToken(string code)
return GoogleAuth.GetAccessToken(code);
}
private NameValueCollection GetAuthHeaders()
public GooglePhotosAlbum CreateAlbum(string albumName)
{
NameValueCollection headers = GoogleAuth.GetAuthHeaders();
headers.Add("GData-Version", "3");
return headers;
GooglePhotosNewAlbum newItemAlbum = new GooglePhotosNewAlbum
{
album = new GooglePhotosAlbum
{
title = albumName
}
};
string serializedNewItemAlbum = JsonConvert.SerializeObject(newItemAlbum);
string serializedNewItemAlbumResponse = SendRequest(HttpMethod.POST, "https://photoslibrary.googleapis.com/v1/albums", serializedNewItemAlbum, headers: GoogleAuth.GetAuthHeaders(), contentType: UploadHelpers.ContentTypeJSON);
GooglePhotosAlbum newItemAlbumResponse = JsonConvert.DeserializeObject<GooglePhotosAlbum>(serializedNewItemAlbumResponse);
return newItemAlbumResponse;
}
public List<GooglePhotosAlbumInfo> GetAlbumList()
@ -108,24 +116,40 @@ public List<GooglePhotosAlbumInfo> GetAlbumList()
List<GooglePhotosAlbumInfo> albumList = new List<GooglePhotosAlbumInfo>();
string response = SendRequest(HttpMethod.GET, "https://picasaweb.google.com/data/feed/api/user/default", headers: GetAuthHeaders());
if (!string.IsNullOrEmpty(response))
Dictionary<string, string> args = new Dictionary<string, string>
{
XDocument xd = XDocument.Parse(response);
{ "excludeNonAppCreatedData", "true" }
};
if (xd != null)
string pageToken = "";
do
{
args["pageToken"] = pageToken;
string response = SendRequest(HttpMethod.GET, "https://photoslibrary.googleapis.com/v1/albums", args, headers: GoogleAuth.GetAuthHeaders());
pageToken = "";
if (!string.IsNullOrEmpty(response))
{
foreach (XElement entry in xd.Descendants(AtomNS + "entry"))
GooglePhotosAlbums albums = JsonConvert.DeserializeObject<GooglePhotosAlbums>(response);
if (albums.albums != null)
{
GooglePhotosAlbumInfo album = new GooglePhotosAlbumInfo();
album.ID = entry.GetElementValue(GPhotoNS + "id");
album.Name = entry.GetElementValue(AtomNS + "title");
album.Summary = entry.GetElementValue(AtomNS + "summary");
albumList.Add(album);
foreach (GooglePhotosAlbum album in albums.albums)
{
GooglePhotosAlbumInfo AlbumInfo = new GooglePhotosAlbumInfo
{
ID = album.id,
Name = album.title
};
albumList.Add(AlbumInfo);
}
pageToken = albums.nextPageToken;
}
}
}
while (!string.IsNullOrEmpty(pageToken));
return albumList;
}
@ -134,48 +158,57 @@ public override UploadResult Upload(Stream stream, string fileName)
{
if (!CheckAuthorization()) return null;
if (string.IsNullOrEmpty(AlbumID))
UploadResult result = new UploadResult();
if (IsPublic)
{
AlbumID = "default";
AlbumID = CreateAlbum(fileName).id;
GooglePhotosAlbumOptions albumOptions = new GooglePhotosAlbumOptions();
string serializedAlbumOptions = JsonConvert.SerializeObject(albumOptions);
string serializedAlbumOptionsResponse = SendRequest(HttpMethod.POST, $"https://photoslibrary.googleapis.com/v1/albums/{AlbumID}:share", content: serializedAlbumOptions, headers: GoogleAuth.GetAuthHeaders(), contentType: UploadHelpers.ContentTypeJSON);
GooglePhotosAlbumOptionsResponse albumOptionsResponse = JsonConvert.DeserializeObject<GooglePhotosAlbumOptionsResponse>(serializedAlbumOptionsResponse);
result.URL = albumOptionsResponse.shareInfo.shareableUrl;
}
UploadResult ur = new UploadResult();
string url = string.Format("https://picasaweb.google.com/data/feed/api/user/default/albumid/" + AlbumID);
string contentType = UploadHelpers.GetMimeType(fileName);
NameValueCollection headers = GetAuthHeaders();
headers.Add("Slug", URLHelpers.URLEncode(fileName));
ur.Response = SendRequest(HttpMethod.POST, url, stream, contentType, null, headers);
if (ur.Response != null)
NameValueCollection uploadTokenHeaders = new NameValueCollection
{
XDocument xd = XDocument.Parse(ur.Response);
{ "X-Goog-Upload-File-Name", fileName },
{ "X-Goog-Upload-Protocol", "raw" },
{ "Authorization", GoogleAuth.GetAuthHeaders()["Authorization"] }
};
XElement entry_element = xd.Element(AtomNS + "entry");
string uploadToken = SendRequest(HttpMethod.POST, "https://photoslibrary.googleapis.com/v1/uploads", stream, contentType: UploadHelpers.ContentTypeOctetStream, headers: uploadTokenHeaders);
if (entry_element != null)
GooglePhotosNewMediaItemRequest newMediaItemRequest = new GooglePhotosNewMediaItemRequest
{
albumId = AlbumID,
newMediaItems = new GooglePhotosNewMediaItem[]
{
XElement group_element = entry_element.Element(MediaNS + "group");
if (group_element != null)
new GooglePhotosNewMediaItem
{
XElement content_element = group_element.Element(MediaNS + "content");
if (content_element != null)
simpleMediaItem = new GooglePhotosSimpleMediaItem
{
ur.ThumbnailURL = content_element.GetAttributeValue("url");
int last_slash_index = ur.ThumbnailURL.LastIndexOf(@"/");
ur.URL = ur.ThumbnailURL.Insert(last_slash_index, @"/s0");
uploadToken = uploadToken
}
}
}
};
string serializedNewMediaItemRequest = JsonConvert.SerializeObject(newMediaItemRequest);
result.Response = SendRequest(HttpMethod.POST, "https://photoslibrary.googleapis.com/v1/mediaItems:batchCreate", serializedNewMediaItemRequest, headers: GoogleAuth.GetAuthHeaders(), contentType: UploadHelpers.ContentTypeJSON);
GooglePhotosNewMediaItemResults newMediaItemResult = JsonConvert.DeserializeObject<GooglePhotosNewMediaItemResults>(result.Response);
if (!IsPublic)
{
result.URL = newMediaItemResult.newMediaItemResults[0].mediaItem.productUrl;
}
return ur;
return result;
}
}
@ -185,4 +218,106 @@ public class GooglePhotosAlbumInfo
public string Name { get; set; }
public string Summary { get; set; }
}
public class GooglePhotosAlbums
{
public GooglePhotosAlbum[] albums { get; set; }
public string nextPageToken { get; set; }
}
public class GooglePhotosAlbum
{
public string id { get; set; }
public string title { get; set; }
public string productUrl { get; set; }
public string coverPhotoBaseUrl { get; set; }
public string coverPhotoMediaItemId { get; set; }
public string isWriteable { get; set; }
public string mediaItemsCount { get; set; }
}
public class GooglePhotosNewMediaItemRequest
{
public string albumId { get; set; }
public GooglePhotosNewMediaItem[] newMediaItems { get; set; }
}
public class GooglePhotosNewMediaItem
{
public string description { get; set; }
public GooglePhotosSimpleMediaItem simpleMediaItem { get; set; }
}
public class GooglePhotosSimpleMediaItem
{
public string uploadToken { get; set; }
}
public class GooglePhotosNewMediaItemResults
{
public GooglePhotosNewMediaItemResult[] newMediaItemResults { get; set; }
}
public class GooglePhotosNewMediaItemResult
{
public string uploadToken { get; set; }
public GooglePhotosStatus status { get; set; }
public GooglePhotosMediaItem mediaItem { get; set; }
}
public class GooglePhotosStatus
{
public string message { get; set; }
public int code { get; set; }
}
public class GooglePhotosMediaItem
{
public string id { get; set; }
public string productUrl { get; set; }
public string description { get; set; }
public string baseUrl { get; set; }
public GooglePhotosMediaMetaData mediaMetadata { get; set; }
}
public class GooglePhotosMediaMetaData
{
public string width { get; set; }
public string height { get; set; }
public string creationTime { get; set; }
public GooglePhotosPhoto photo { get; set; }
}
public class GooglePhotosPhoto
{
}
public class GooglePhotosNewAlbum
{
public GooglePhotosAlbum album { get; set; }
}
public class GooglePhotosAlbumOptions
{
public GooglePhotosSharedAlbumOptions sharedAlbumOptions { get; set; }
}
public class GooglePhotosSharedAlbumOptions
{
public string isCollaborative { get; set; }
public string isCommentable { get; set; }
}
public class GooglePhotosAlbumOptionsResponse
{
public GooglePhotosShareInfo shareInfo { get; set; }
}
public class GooglePhotosShareInfo
{
public GooglePhotosSharedAlbumOptions sharedAlbumOptions { get; set; }
public string shareableUrl { get; set; }
public string shareToken { get; set; }
public string isJoined { get; set; }
}
}

View file

@ -83,6 +83,7 @@ public class UploadersConfig : SettingsBase<UploadersConfig>
public OAuth2Info PicasaOAuth2Info = null;
public string PicasaAlbumID = "";
public bool GooglePhotosIsPublic = false;
#endregion Google Photos