Skip to content

*unofficial* Google Photos REST API library for .NET projects.

License

Notifications You must be signed in to change notification settings

f2calv/CasCap.Api.GooglePhotos

Repository files navigation

CasCap.Api.GooglePhotos

Unofficial Google Photos Library API wrapper library for .NET applications

CI Coverage Status Code Smells Nuget

Want to save yourself some coding? See the preview release of GooglePhotosCli using this library...

This is an unofficial Google Photos REST API library targeting .NET 8.0.

Note: Older projects that require .NET Standard 2.0 please use version 1.x of this library.

If you find this library of use then please give it a thumbs-up by giving this repository a ⭐ ... 😉

If you wish to interact with your Google Photos media items/albums then there are official PHP and Java Client Libraries. However if you're looking for a comprehensive .NET library then you were out of luck... until now :)

The CasCap.Api.GooglePhotos library wraps up all the available functionality of the Google Photos REST API in easy to use methods.

Note: Before you jump in and use this library you should be aware that the Google Photos Library API has some key limitations. The biggest of these is that the API only allows the upload/addition of images/videos to the library, no edits or deletion are possible and have to be done manually via https://photos.google.com.

Google Photos API Set-up

When you create your photos application, you must first create an OAuth login details using the Google API Console and retrieve a Client ID and a Client Secret.

Using your Google Account the steps are*;

  1. Visit Google API Console
  2. Select 'Library' on the main menu;
    • Search for 'Photos Library API', select it from the results and hit the Enable button.
  3. Select 'Credentials' on the main menu;
    • Select 'Create Credentials' on the sub menu and pick 'OAuth client ID'
    • Select 'Desktop' as the application type.
    • Enter a suitable application name and hit the Create button.
    • Copy/save the Client ID and Client Secret which are then displayed you will use these to authenticate with the GooglePhotosService.

*Note: the above instructions are correct as of 2022-04-06.

Library Configuration/Usage

Install the package into your project using NuGet (see details here).

For .NET Core applications using dependency injection the primary API usage is to call IServiceCollection.AddGooglePhotos in the Startup.cs ConfigureServices method.

//Startup.cs
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGooglePhotos();
    }
}

There are 4 mandatory configuration options that must be passed;

  • User (your email address)
  • Google Client ID
  • Google Client Secret
  • Authorisation Scopes

There are 5 possible authorisation scopes which designate the level of access you wish to give, these scopes can be combined if required;

  • ReadOnly
  • AppendOnly
  • AppCreatedData
  • Access
  • Sharing

Best practise is to assign the lowest access level possible to meet your requirements. If you wish to go against best practise and give your application unfettered access to your media collection then use Access and Sharing scopes combined.

The recommended method of setting these mandatory options is via the appsettings.json file;

// appsettings.json
{
    ...
    "CasCap": {
        "GooglePhotosOptions": {
            // This is the email address of the Google Account.
            "User": "[email protected]",

            // There are 5 security scopes, which can be combined.
            "Scopes": [
                "ReadOnly"
                //"AppendOnly",
                //"AppCreatedData",
                //"Access",
                //"Sharing"
                ],

            // The ClientId and ClientSecret are provided by the Google Console after you register your own application.
            "ClientId": "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com",

            "ClientSecret": "abcabcabcabcabcabcabcabc",
        }
    }
    ...
}

Alternatively you can pass the options into the AddGooglePhotos method;

//Startup.cs
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGooglePhotos(options =>
        {
            options.User = "[email protected]";//replace with **your** info
            options.ClientId = "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com";//replace with **your** info
            options.ClientSecret = "abcabcabcabcabcabcabcabc";//replace with **your** info
            options.Scopes = new[] { GooglePhotosScope.ReadOnly };
        });
    }
}

Using appsettings.json is generally the best option however remember the Client ID & Client Secret should be stored securely outside of source control via Azure KeyVault (or .NET Secret Manager as shown below).

dotnet user-secrets init
dotnet user-secrets set "CasCap:GooglePhotosOptions:User" "[email protected]" #replace with **your** info
dotnet user-secrets set "CasCap:GooglePhotosOptions:ClientId" "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com" #replace with **your** info
dotnet user-secrets set "CasCap:GooglePhotosOptions:ClientSecret" "abcabcabcabcabcabcabcabc" #replace with **your** info

After calling AddGooglePhotos in the ConfigureServices method of Startup.cs you can then call upon the GooglePhotosService within your own services shown below.

using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
namespace CasCap.Services
{
    public class MyPhotoService
    {
        readonly ILogger _logger;
        readonly GooglePhotosService _googlePhotosSvc;

        public MyPhotoService(ILogger<MyPhotoService> logger, GooglePhotosService googlePhotosSvc)
        {
            _logger = logger;
            _googlePhotosSvc = googlePhotosSvc;
        }

        public async Task Login_And_List_Albums()
        {
            if (!await _googlePhotosSvc.LoginAsync())
                throw new Exception($"login failed");

            var albums = await _googlePhotosSvc.GetAlbums();
            foreach (var album in albums)
            {
                _logger.LogInfo($"{album.id}\t{album.title}");
            }
        }
    }
}

If you don't use dependency injection you can new-up the GooglePhotosService manually and pass the mandatory configuration options, logger and HttpClient via the service constructor;

//MyPhotosClass.cs
using CasCap.Models;
using CasCap.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

public class MyPhotosClass
{
    public async Task Login_And_List_Albums()
    {
        //new-up logging
        var logger = new LoggerFactory().CreateLogger<GooglePhotosService>();

        //new-up configuration options
        var options = new GooglePhotosOptions
        {
            User = "[email protected]",//replace with **your** info
            ClientId = "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com",//replace with **your** info
            ClientSecret = "abcabcabcabcabcabcabcabc",//replace with **your** info
            Scopes = new[] { GooglePhotosScope.ReadOnly },
        };

        //new-up a single HttpClient
        var handler = new HttpClientHandler { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate };
        var client = new HttpClient(handler) { BaseAddress = new Uri(options.BaseAddress) };

        //new-up the GooglePhotosService and pass in the logger, options and HttpClient
        var googlePhotosSvc = new GooglePhotosService(logger, Options.Create(options), client);

        //attempt to log-in
        if (!await googlePhotosSvc.LoginAsync())
            throw new Exception($"login failed!");

        //get and list all albums
        var albums = await googlePhotosSvc.GetAlbums();
        foreach (var album in albums)
        {
            Console.WriteLine(album.title);
        }
    }
}

Misc

Changing Users/Scopes

The Google.Apis.Auth library will cache the OAuth 2.0 login information in a local JSON file which it will then read tokens from (and renew if necessary) on subsequent logins. The JSON file(s) are stored on a per-User basis in the Environment.SpecialFolder.ApplicationData folder. On Windows 10 this folder is located at;

  • %UserProfile%\AppData\Roaming\Google.Apis.Auth

If you change the authentication scopes for a User you must delete the JSON file and allow the Google.Apis.Auth library to re-auth and re-create a new JSON file with the new scopes.

You can change the location where these JSON token files are stored at using the FileDataStoreFullPathOverride property in the configuration options;

//Startup.cs
using Microsoft.Extensions.DependencyInjection;

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddGooglePhotos(options =>
        {
            options.User = "[email protected]";
            options.Scopes = new[] { GooglePhotosScope.ReadOnly };
            options.ClientId = "012345678901-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com";
            options.ClientSecret = "abcabcabcabcabcabcabcabc";
            //change FileDataStoreFullPathOverride
            options.FileDataStoreFullPathOverride = "c:/temp/GooglePhotos/"
        });
    }
}

Sample Projects

All API functions are exposed by the GooglePhotosService class. There are several sample .NET Core applications which show the basics on how to set-up/config/use the library;

Core Dependencies

Misc Tips

  • The NuGet package includes SourceLink which enables you to jump inside the library and debug the API yourself. By default Visual Studio 2017/2019 does not allow this and will pop up an message "You are debugging a Release build of...", to disable this message go into the Visual Studio debugging options and un-check the 'Just My Code' option (menu path, Tools > Options > Debugging).

Resources

Feedback/Issues

Please post any issues or feedback here.

License

CasCap.Api.GooglePhotos is Copyright © 2020 Alex Vincent under the MIT license.