Giter Club home page Giter Club logo

cascap.apis.googlephotos's People

Contributors

dependabot-preview[bot] avatar f2calv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

cascap.apis.googlephotos's Issues

File size by day and month

Hi

would it be possible to built an app with this library, that would calculate storage usage per Month and possibly per day for all the photos stored in the account?

something like 'du -sh *' in bash

Doesn't work in UWP

ConsoleApp sample code works fine as a .NET Core 3.1 console app.
Same code in an UWP app crashes deep in LoginAsync, seems async-related trying to access a disposed Socket object.
I could post a project to reproduce but you already have the code, it's a pretty hard crash and burn.
Let me know if you have questions.
Lars

How to find the lifetime of a login token.

I want to add a huge amount of photos (let's say 1000) which will takes a long time. After a while I get Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential error when calling any method on the library.

How do I find out when the OAuth access token is expiring?

P.S. My current workaround is to basically new up GooglePhotosService. Is there a better way?

Uploading of files with names containing non-English characters is not supported

Sometimes when uploading files with names that contain non-English characters fails.
For example, uploading of file a "D:\2003.02.06 - (Открытый) Урок английского.jpg" fails and the server returns an HTML page

<title>Error 400 (Bad Request)!!1</title>

which eventually results in Newtonsoft.Json.JsonReaderException

Unexpected character encountered while parsing value: <. Path '', line 0, position 0.

The reason for this is the HTTP standard that doesn't support non-ISO-8859-1 characters directly in an HTTP header. Thus characters should be encoded to be passed in the header.

Suggested fix: use HttpUtility.UrlPathEncode in GooglePhotosServiceBase.UploadMediaAsync:

headers.Add((X_Goog_Upload_File_Name, HttpUtility.UrlPathEncode(Path.GetFileName(path))));

GetMediaItemsAsync JSON Error: 'Could not convert string to double: 0.050s' for 'mediaItems[0].mediaMetadata.photo.exposureTime'

Could not convert string to double: 0.050s. Path 'mediaItems[0].mediaMetadata.photo.exposureTime', line 18, position 34. | Newtonsoft.Json.JsonReaderException: Could not convert string to double: 0.050s. Path 'mediaItems[0].mediaMetadata.photo.exposureTime', line 18, position 34.
at Newtonsoft.Json.JsonReader.ReadDoubleString(String s)
at Newtonsoft.Json.JsonTextReader.FinishReadQuotedNumber(ReadType readType)
at Newtonsoft.Json.JsonTextReader.ReadAsDouble()
at Newtonsoft.Json.JsonReader.ReadForType(JsonContract contract, Boolean hasConverter)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value)
at CasCap.Common.Extensions.Helpers.FromJSON[T](String json)
at CasCap.Services.HttpClientBase.HandleResult[TResult,TError](HttpResponseMessage response)
at CasCap.Services.HttpClientBase.Get[TResult,TError](String requestUri, Nullable1 timeout, List1 headers)
at CasCap.Services.GooglePhotosServiceBase._GetMediaItemsAsync(Int32 pageSize, Int32 maxPageCount, Boolean excludeNonAppCreatedData, String requestUri, CancellationToken cancellationToken)

Unable to upload files bigger than 2 GB in ResumableMultipart mode

Uploading files with sizes more than 2 GB fails in ResumableMultipart mode with JsonReaderException:

Error parsing Infinity value. Path '', line 1, position 2.

The reason is that variable offset in the method GooglePhotosServiceBase.UploadMediaAsync is Int32. As a result when loading files with sizes greater than Int32.MaxValue, offset overflows to a negative value passed to the HTTP header.

The solution would be to change the type of offset variable to Int64:

var offset = 0L;

Non Compatibilty with .Net Framework 4.5

Thanks a lot for your effort in creating a proper library for C#. Google API Documentation does not have any examples on consuming the their REST API in C#.

I'm trying to use your library in one of my Winforms project that targets .net Framework 4.5. Installing from nuget does not seem to work since there is some compatibility issues with .Net 5. I have tried manually adding the DLLs but still there are some reference issues. Is there an official way to make this work with .Net Framework 4.5 ?

How to find the owner of each media item? Otherwise is it possible to load only media items owned by user in shared album?

Is it possible to know the owner of each media item, e.g. loaded by GetMediaItemsByAlbumAsync method, in Google Photos?

I mean, is there a property in some class?

I've found the property contributorInfo in class MediaItem, but, as written in summary, that field is only populated if the media item is in a shared album created by the app that use the library.

Do you confirm that is present only that property? Doesn't Google provide this useful information?

Otherwise, is it possible in method GetMediaItemsByAlbumAsync for a shared album to load only media items owned by the user used in the login?

I hope you can help me and thanks in advance.

Filter by "Camera" or "Partner"

I would like to be able to use the API to filter my media, but haven't figured out the appropriate filters. The two filters I'm looking for are:

  • media from my phone/camera (essentially what's in my phone's "Gallery" app)
  • media from my partner's phone/camera (a special shared folder that, for some reason, doesn't show up on the list of shared folders)

Those are easy enough to do in the Google Photos app or web site, but I can't figure out how to do that via the API. Any/all help appreciated.

(Note: I've asked this question on Stack Overflow as well. I'm not 100% certain which is the better place for it.)

If Photos Library API is not enabled, some requests succeed with zero results.

If you have not enabled the Photos Library API permission on your google app, the request fails with a 403, but the library ignores the error and just returns zero results.

Sample result from Fiddler.

HTTP/1.1 403 Forbidden
Content-Type: application/json; charset=UTF-8
Date: Mon, 27 Jul 2020 00:41:39 GMT

{
  "error": {
    "code": 403,
    "message": "Photos Library API has not been used in project XXX before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/photoslibrary.googleapis.com/overview?project=XXX then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.",
    "status": "PERMISSION_DENIED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.Help",
        "links": [
          {
            "description": "Google developers console API activation",
            "url": "https://console.developers.google.com/apis/api/photoslibrary.googleapis.com/overview?project=XXX"
          }
        ]
      }
    ]
  }
}

Note: I only verified this behavior with GetAlbumsAsync(...).

How to upload a "live" photo?

"Live Photo" is an iPhone construct where the camera records 2 seconds of video and using some algorithm picks the best frame and that is what displays on phone's Photos app. When you long tap the photo, the entire 2 second video plays.

When Google Photos app backs up this "Live Photo", it shows up as a photo on the website, however, it has a "Turn on motion" button, that allows you to play the entire video, just like on the phone.

image

I have this "Live Photo" file on my desktop and Google Photos exports it as an mp4. However, when I upload the photo using _googlePhotosSvc.UploadMediaAsync and _googlePhotosSvc.AddMediaItemAsync combo, it just shows up as another video.

Is there a way to tell Google Photos that it's a "Live Photo"?

Feature Request: Limit Pages to Get

Hi, would be great to add optional parameter MaxPages to GetMediaItemsAsync. So get stops requesting after defined number of pages. The same could be reached by using the cancel token. But Cancel token would be for "surprising" user cancellation while max pages would be for deterministic stop.

Use case would be if you pull the whole MediaList you might get thousands of pages a) this can take very long and b) if you want to show them until pictures are downloaded download link has expired.

You are already tracking page numbers. So just add it to condition a la
var pageNumber = 1;
while (pageToken is object && !cancellationToken.IsCancellationRequested && maxPageNumber <= pageNumber)

No permission to add media items to this album - When trying to upload to existing Album

Hello,

Thanks a lot for the .Net Wrapper :) .

I recently came across an issue when trying to upload photos to existing google albums(created from Google Photos web UI/elsewhere) . I keep getting the following error

No permission to add media items to this album

Even when the following permissions are granted in the Google security section

  • Add to your Google Photos library
  • View your Google Photos library

I'm using version 1.1.2 of CasCap.Apis.GooglePhotos

Please advice

library testing

@k0qed I'm looking for testers for this new Google Photos .NET Library, are you interested?

Getting "Request contains an invalid media item id" error when adding photo to an album.

I am trying to do the following:

  1. Create an album.
  2. Add existing photos to that album.

So I do the following:

// boilerplate to connect to google api

List<MediaItem> mediaItems = await googlePhotosSvc.GetMediaItemsAsync();
Album album= await googlePhotosSvc.CreateAlbumAsync(albumName);

foreach (var item in mediaItems) {
    bool success = await googlePhotosSvc.AddMediaItemsToAlbumAsync(album.id, new string[] { item.id });
}

It blows up on googlePhotosSvc.AddMediaItemsToAlbumAsync with Request contains an invalid media item id.

I've played around with adding scopes and at this point I have GooglePhotosScope.AppendOnly, GooglePhotosScope.ReadOnly, GooglePhotosScope.AppCreatedData, GooglePhotosScope.Sharing. But I am not sure what exactly is the problem. I've also tried adding photos in batches, but I get the same error.

The API call looks like this in Fiddler:

POST /v1/albums/ALvc__nJoKD2Rfh9rav5sQ7U9lm5ClQ3F_tVQ-mBANpi0pjGMfs5wn8eJ1gD2ibjQNbLsD3SHeI3:batchAddMediaItems HTTP/1.1

with the body of:

{"mediaItemIds":["ALvc__kuVUBPmBfk8AkGiXLrvxLj1tOdkGaoMtp0AmPqEbcP-hI13wILoiFpCzUXc9xe6zk2eMnsTGry-3SaS4znQZa_qFQwxQ"]}

And it returns

{
  "error": {
    "code": 400,
    "message": "Request contains an invalid media item id.",
    "status": "INVALID_ARGUMENT"
  }
}

What am I missing?

DownloadBytes does not preserve exif data

It would be nice if the DownloadBytes would preserve the exif data, it currently does not, This can be accomplished by adding the "ip" parameter to the url you are creating to download the media item. (Found the info here https://gist.github.com/Sauerstoffdioxid/2a0206da9f44dde1fdfce290f38d2703)

async Task<byte[]?> DownloadBytes(string baseUrl, int? maxWidth = null, int? maxHeight = null, bool crop = false, bool downloadPhoto = false, bool downloadVideo = false)

MimeType support

Hello,

Thanks for the excellent .net library.

Try to upload the RW2 file which is supported by google photo but get System.NotSupportedException.

System.NotSupportedException: 'Cannot match file extension '.RW2' from 'd:/temp/GooglePhotos/P1000195.RW2' to a known image or video mime type.'

The AcceptedMimeTypesImage needs to include a more supported format.

    static readonly HashSet<string> AcceptedMimeTypesImage = new(StringComparer.OrdinalIgnoreCase)
    {
        { "image/bmp" },
        { "image/gif" },
        { "image/heic" },
        { "image/vnd.microsoft.icon" },
        { "image/jpeg" },
        { "image/jpeg" },
        { "image/png" },
        { "image/tiff" },
        { "image/webp" },
    };

Paging

I have a big library with 10k+ items. When I run _googlePhotosSvc.GetMediaItemsByAlbumAsync(album.id, 25); It take long time...hangs. What am I doing wrong since paging is not working for me. Could you please help? Also, is there a easy way to get filenames? Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.