Esempio n. 1
0
        public Place TransformTextPlaceToPlace(GoogleTextSearchPlace gtp)
        {
            IPhotosService photoService = new GooglePhotosService();

            Place place = new Place()
            {
                Id         = gtp.PlaceId,
                Name       = gtp.Name,
                Categories = gtp.Categories,
                Rating     = gtp.Rating,
                Location   = gtp.Geometry.Location.Latitude.ToString() + " " + gtp.Geometry.Location.Longitude.ToString(),
                Address    = gtp.Address ?? "",
                Icon       = gtp.Icon ?? "",
                OpenNow    = gtp.OpenHours?.OpenNow ?? false
            };

            if (gtp.GooglePhotos == null)
            {
                place.PhotoReference = place.Icon;
                place.Photo          = place.Icon;
            }
            else
            {
                place.PhotoReference = gtp.GooglePhotos[0].PhotoReference;
                place.Photo          = photoService.GetImageByReference(place.PhotoReference, "100", "80");
            }
            return(place);
        }
Esempio n. 2
0
    public TestBase(ITestOutputHelper output)
    {
        var configuration = new ConfigurationBuilder()
                            .AddJsonFile($"appsettings.Test.json", optional: false, reloadOnChange: true)
                            .AddUserSecrets <TestBase>() //for local testing
                            .AddEnvironmentVariables()   //for CI testing
                            .Build();

        //initiate ServiceCollection w/logging
        var services = new ServiceCollection()
                       .AddSingleton <IConfiguration>(configuration)
                       .AddXUnitLogging(output);

        _logger = ApplicationLogging.LoggerFactory.CreateLogger <TestBase>();

        //add services
        services.AddGooglePhotos();
        services.AddSingleton <DiskCacheService>();

        //retrieve services
        var serviceProvider = services.BuildServiceProvider();

        _googlePhotosSvc = serviceProvider.GetRequiredService <GooglePhotosService>();
        _diskCacheSvc    = serviceProvider.GetRequiredService <DiskCacheService>();
    }
Esempio n. 3
0
        public DetailedPlace TransformDetailedPlaceToPlace(DetailedGooglePlace dgp, Place place)
        {
            IPhotosService photo    = new GooglePhotosService();
            DetailedPlace  detPlace = new DetailedPlace()
            {
                Id          = dgp.PlaceId,
                Name        = dgp.Name,
                Categories  = dgp.Categories,
                Rating      = dgp.Rating,
                Location    = dgp.Geometry.Location.Latitude.ToString() + " " + dgp.Geometry.Location.Longitude.ToString(),
                Address     = place.Address,
                Icon        = place.Icon,
                OpenNow     = dgp.OpenHours?.OpenNow ?? false,
                PriceLevel  = place.PriceLevel,
                PriceString = place.PriceString,
                Reviews     = dgp.Reviews,
                PhoneNumber = dgp.PhoneNumber,
                WebSite     = dgp.WebSite,
                Photo       = photo.GetImageByReference(place.PhotoReference, "184", "400")
            };

            if (detPlace.Reviews != null)
            {
                detPlace.Author  = detPlace.Reviews.FirstOrDefault().ReviewAuthor;
                detPlace.Comment = detPlace.Reviews.FirstOrDefault().ReviewText;
            }
            return(detPlace);
        }
    const string _testFolder = "c:/temp/GooglePhotos/";//local folder of test media files

    public MyBackgroundService(ILogger <MyBackgroundService> logger, IHostApplicationLifetime appLifetime,
                               GooglePhotosService googlePhotosSvc)
    {
        _logger          = logger;
        _appLifetime     = appLifetime;
        _googlePhotosSvc = googlePhotosSvc;
    }
Esempio n. 5
0
 public GoogleFile File(GooglePhotosService service, DiscretePicasaAlbum picasaAlbum, Picasa.Photo picasaPhoto)
 {
     return(new GoogleFile(new Path(mainPrefix, new string[] {
         PicasaExtensions.VirtualDirectoryName(service),
         PicasaExtensions.VirtualDirectoryName(picasaAlbum),
         PicasaExtensions.VirtualFileName(picasaPhoto)
     }, this)));
 }
Esempio n. 6
0
        public AlbumsQuery(GooglePhotosService service)
        {
            this.service = service;

            AlbumQuery albumsQuery = new AlbumQuery(PicasaQuery.CreatePicasaUri("default"));

            albumsQuery.ExtraParameters = "imgmax=d";
            PicasaFeed albumsFeed = service.PicasaService.Query(albumsQuery);

            picasaAlbums = albumsFeed.Entries.OfType <PicasaEntry> ().ToArray();
        }
Esempio n. 7
0
        public ContentQuery(GooglePhotosService service, DiscretePicasaAlbum album)
        {
            this.service = service;
            this.album   = album;

            Picasa.Album picasaAlbum = new Picasa.Album();
            picasaAlbum.AtomEntry = album.Entry;

            PhotoQuery picturesQuery = new PhotoQuery(PicasaQuery.CreatePicasaUri("default", picasaAlbum.Id));

            picturesQuery.ExtraParameters = "imgmax=d";
            PicasaFeed picturesFeed = service.PicasaService.Query(picturesQuery);

            picasaPictures = picturesFeed.Entries.OfType <PicasaEntry> ().ToArray();
        }
Esempio n. 8
0
 public Duplicates(IConsole console, DiskCacheService diskCacheSvc, GooglePhotosService googlePhotosSvc) : base(console, diskCacheSvc, googlePhotosSvc)
 {
 }
Esempio n. 9
0
 public Download(IConsole console, DiskCacheService diskCacheSvc, GooglePhotosService googlePhotosSvc) : base(console, diskCacheSvc, googlePhotosSvc)
 {
 }
Esempio n. 10
0
    public async override Task <int> OnExecuteAsync(CommandLineApplication app)
    {
        await base.OnExecuteAsync(app);

        var rootPath = Path.GetFullPath(path);

        _console.Write($"Checking for file(s)... ");
        var allFileInfos = GetFiles(path, searchPattern);
        var items        = new List <MyMediaFileItem>(allFileInfos.Count);

        if (allFileInfos.IsNullOrEmpty())
        {
            _console.WriteLine($" 0 files found at {rootPath}");
        }
        else
        {
            var checkForUploadableFileTypes = allFileInfos.GroupBy(p => Path.GetExtension(p.Name), StringComparer.InvariantCultureIgnoreCase)
                                              .Select(g => new
            {
                Extension  = g.Key,
                MimeType   = MimeTypeMap.GetMimeType(g.Key),
                Count      = g.Count(),
                TotalBytes = g.Sum(p => p.Length)
            })
                                              .ToList();
            _console.WriteLine($"located {allFileInfos.Count} file(s), breakdown of file types;");
            _console.WriteLine();
            //todo: do we also analyse the files with ImageSharp/Exif?

            var headers = new[] { new ColumnHeader("File Extension"), new ColumnHeader("Mime Type"), new ColumnHeader("Count", Alignment.Right), new ColumnHeader("Size (MB)", Alignment.Right), new ColumnHeader("Status") };
            var table   = new Table(headers)
            {
                Config = TableConfiguration.Markdown()
            };
            foreach (var f in checkForUploadableFileTypes.OrderBy(p => p.Extension))
            {
                var status = string.Empty;
                if (!GooglePhotosService.IsFileUploadableByExtension(f.Extension))
                {
                    status = "Unsupported file extension, will not be uploaded.";
                }
                table.AddRow(f.Extension, f.MimeType, f.Count, f.TotalBytes.GetSizeInMB().ToString("0.0"), status);
            }
            //below summary row breaks the progress bar somehow
            //table.AddRow(string.Empty, string.Empty, allFileInfos.Count, allFileInfos.Sum(p => p.Length.GetSizeInMB()).ToString("0.0"), string.Empty);
            Console.Write(table.ToString());
            _console.WriteLine();

            //add all uploadable files into a new collection
            foreach (var fileInfo in allFileInfos)
            {
                if (GooglePhotosService.IsFileUploadable(fileInfo.FullName))
                {
                    items.Add(new MyMediaFileItem {
                        fileInfo = fileInfo
                    });
                }
            }
        }
        if (items.IsNullOrEmpty())
        {
            _console.WriteLine($"{items.Count} uploadable file(s)");
            return(0);
        }

        {
            //extract album information from the folder structure (if requested)
            _console.WriteLine($"{items.Count} file(s) to be uploaded;");
            _console.WriteLine();

            var headers = new[] { new ColumnHeader("Relative Path"), new ColumnHeader("Size (KB)", Alignment.Right), new ColumnHeader("Album(s)") };
            var table   = new Table(headers)
            {
                Config = TableConfiguration.Markdown()
            };
            foreach (var item in items)
            {
                item.relPath = GetRelPath(rootPath, item.fileInfo);
                item.albums  = GetAlbums(item);
                table.AddRow(item.relPath, item.fileInfo.Length.GetSizeInKB().ToString("#,###,###"), string.Join(", ", item.albums));
            }
            Console.Write(table.ToString());
            _console.WriteLine();
        }


        string[] GetAlbums(MyMediaFileItem item)
        {
            var albums = item.relPath.Substring(0, item.relPath.LastIndexOf(item.fileInfo.Name));

            if (albums.StartsWith(Path.DirectorySeparatorChar))
            {
                albums = albums.Substring(1);
            }
            if (albums.EndsWith(Path.DirectorySeparatorChar))
            {
                albums = albums.Substring(0, albums.Length - 1);
            }
            var myAlbums = albums.Split(Path.DirectorySeparatorChar);

            return(myAlbums);
        }

        //note: if we are uploading a crazy amount of data ProgressBar only supports int for ticks, so may break :/
        var totalBytes = items.Sum(p => p.fileInfo.Length);

        if (totalBytes > int.MaxValue)
        {
            throw new Exception($"Unable to upload more than {((long)int.MaxValue).GetSizeInMB()} in one session!");
        }

        var totalKBytes = totalBytes.GetSizeInKB();

        if (!AutoConfirm && !Prompt.GetYesNo($"Hit (Y)es to upload {items.Count} files, {totalBytes.GetSizeInMB():###,###} MB...", false, ConsoleColor.Cyan))
        {
            return(0);
        }
        else
        {
            _console.WriteLine($"Now uploading {items.Count} files, {totalBytes.GetSizeInMB():###,###} MB...");
        }

        var dtStart           = DateTime.UtcNow;
        var estimatedDuration = TimeSpan.FromMilliseconds(items.Count * 2_000);//set gu-estimatedDuration

        pbar = new ProgressBar((int)totalBytes, $"Uploading {items.Count} media item(s)...", pbarOptions)
        {
            EstimatedDuration = estimatedDuration
        };

        //do we upload an assign to library(and albums) as we progress?
        //or
        //do we upload all and get the uploadTokens, then assign to the library(and albums) in a second step?
        //...which gives the user to bomb out if a file isn't successfully uploaded?
        var uploadedFileCount  = 0;
        var uploadedTotalBytes = 0;

        foreach (var item in items)
        {
            var str = $"{item.fileInfo.Name} : 0 of {(int)item.fileInfo.Length.GetSizeInKB()} Kb";
            childPBar = pbar.Spawn((int)item.fileInfo.Length, str, childPbarOptions);

            //todo: pass Action or Func for a callback instead of raising an event?
            var uploadToken = await _googlePhotosSvc.UploadMediaAsync(item.fileInfo.FullName /*, callback: child.Tick()*/);

            if (!string.IsNullOrWhiteSpace(uploadToken))
            {
                item.uploadToken = uploadToken;
            }
            else
            {
                Debugger.Break();
                //todo: how to handle upload failure here?
            }

            childPBar.Dispose();

            uploadedFileCount++;
            uploadedTotalBytes += (int)item.fileInfo.Length;
            pbar.Tick(uploadedTotalBytes, $"Uploaded {uploadedFileCount} of {items.Count}");
            //if (Interlocked.Read(ref iteration) % 25 == 0)
            {
                var tsTaken            = DateTime.UtcNow.Subtract(dtStart).TotalMilliseconds;
                var timePerCombination = tsTaken / uploadedFileCount;
                pbar.EstimatedDuration = TimeSpan.FromMilliseconds((items.Count - uploadedFileCount) * timePerCombination);
            }
        }

        pbar.Dispose();

        //album duplicate checking needs to happen first
        var requiredAlbumTitles = items.SelectMany(p => p.albums).Distinct(StringComparer.OrdinalIgnoreCase).Where(p => !string.IsNullOrWhiteSpace(p)).ToList();

        //allAlbums = await _diskCacheSvc.GetAsync($"albums.json", () => _googlePhotosSvc.GetAlbumsAsync());
        allAlbums = await _googlePhotosSvc.GetAlbumsAsync();

        if (!requiredAlbumTitles.IsNullOrEmpty())
        {
            DoDuplicateAlbumsExist();
        }
        var dAlbums = await GetOrCreateAlbums();

        if (dAlbums is null)
        {
            return(1);
        }


        _console.Write($"Adding {items.Count} media item(s) to your library...");
        var uploadItems = items.Select(p => (p.uploadToken, p.fileInfo.Name)).ToList();
        var res         = await _googlePhotosSvc.AddMediaItemsAsync(uploadItems);

        if (res is object)
        {
            _console.WriteLine($" done! :)");
            //iterate over results and assign the MediaItem object to our collection
            foreach (var newMediaItem in res.newMediaItemResults)
            {
                var item = items.FirstOrDefault(p => p.uploadToken == newMediaItem.uploadToken);
                if (item is null)
                {
                    throw new Exception("could this happen?");
                }
                if (newMediaItem.status is object && newMediaItem.status.message == "Success")
                {
                    item.mediaItem = newMediaItem.mediaItem;
                }
                else
                {
                    Debugger.Break();
                    //todo: handle error?
                }
            }

            //todo: delete local files (if required)
            //todo: delete empty folders?
            if (deleteLocal)
            {
                foreach (var item in items.Where(p => p.mediaItem is object))
                {
                    _console.Write($"Deleting '{item.fileInfo.FullName}'...");
                    File.Delete(item.fileInfo.FullName);//todo: try...catch here?
                    _console.WriteLine($" deleted!");
                }
            }

            if (dAlbums.Count > 0)
            {
                _console.WriteLine($"Adding media item(s) to albums...");
                //todo: put progress bar here?
                var table = new Table("Album Name", "Status")
                {
                    Config = TableConfiguration.Markdown()
                };
                foreach (var kvp in dAlbums)
                {
                    var ids = items.Where(p => p.albums.Contains(kvp.Value.title, StringComparer.OrdinalIgnoreCase)).Select(p => p.mediaItem.id).ToList();
                    if (await _googlePhotosSvc.AddMediaItemsToAlbumAsync(kvp.Value.id, ids))
                    {
                        table.AddRow(kvp.Value.title, $"{ids.Count} media item(s) added");
                    }
                    else
                    {
                        Debugger.Break();
                    }
                }
                Console.Write(table.ToString());
                _console.WriteLine();
            }

            _console.WriteLine($"Upload completed, exiting.");
        }
        else
        {
            _console.WriteLine($" failed :(");
        }
        //todo: now handle albums
        //todo: do we add media items to local cache here?

        return(0);

        bool DoDuplicateAlbumsExist()
        {
            var duplicateAlbumsByTitle = GetAlbumDuplicates(allAlbums);

            //album titles in google photos don't need to be unique, but we can't assign photos to an existing album
            //if duplicate titles exist that match one of our required album titles...
            if (duplicateAlbumsByTitle.Count > 0 && duplicateAlbumsByTitle.Any(p => requiredAlbumTitles.Contains(p.title, StringComparer.OrdinalIgnoreCase)))
            {
                _console.WriteLine($"Duplicate album titles present, unable to assign media item(s) to albums.");
                foreach (var album in duplicateAlbumsByTitle)
                {
                    _console.WriteLine($"{album.title}");
                }
                _console.WriteLine($"Please rename or merge the above albums to continue.");
                return(false);
            }
            return(true);
        }

        async Task <Dictionary <string, Album> > GetOrCreateAlbums()
        {
            //great there are no duplicate titles, lets get/create the missing albums
            var d = new Dictionary <string, Album>();

            foreach (var title in requiredAlbumTitles)
            {
                var album = allAlbums.FirstOrDefault(p => p.title.Equals(title, StringComparison.OrdinalIgnoreCase));
                if (album is null)
                {
                    album = await _googlePhotosSvc.CreateAlbumAsync(title);
                }
                d.Add(title, album);
            }
            return(d);
        }
    }
Esempio n. 11
0
 public Upload(IConsole console, DiskCacheService diskCacheSvc, GooglePhotosService googlePhotosSvc) : base(console, diskCacheSvc, googlePhotosSvc)
 {
     _googlePhotosSvc.UploadProgressEvent += _googlePhotosSvc_UploadProgressEvent;
 }
Esempio n. 12
0
 public static void AddService(GooglePhotosService service)
 {
     Instance.Services [PicasaExtensions.VirtualDirectoryName(service)] = service;
 }
Esempio n. 13
0
    static async Task Main(string[] args)
    {
        if (new[] { _user, _clientId, _clientSecret }.Any(p => string.IsNullOrWhiteSpace(p)))
        {
            Console.WriteLine("Please populate authentication details to continue...");
            Debugger.Break();
            return;
        }
        if (!Directory.Exists(_testFolder))
        {
            Console.WriteLine($"Cannot find folder '{_testFolder}'");
            Debugger.Break();
            return;
        }

        //1) new-up some basic logging (if using appsettings.json you could load logging configuration from there)
        //var configuration = new ConfigurationBuilder().Build();
        var loggerFactory = LoggerFactory.Create(builder =>
        {
            //builder.AddConfiguration(configuration.GetSection("Logging")).AddDebug().AddConsole();
        });
        var logger = loggerFactory.CreateLogger <GooglePhotosService>();

        //2) create a configuration object
        var options = new GooglePhotosOptions
        {
            User         = _user,
            ClientId     = _clientId,
            ClientSecret = _clientSecret,
            //FileDataStoreFullPathOverride = _testFolder,
            Scopes = new[] { GooglePhotosScope.Access, GooglePhotosScope.Sharing },//Access+Sharing == full access
        };

        //3) (Optional) display local OAuth 2.0 JSON file(s);
        var path = options.FileDataStoreFullPathOverride is null ? options.FileDataStoreFullPathDefault : options.FileDataStoreFullPathOverride;

        Console.WriteLine($"{nameof(options.FileDataStoreFullPathOverride)}:\t{path}");
        var files = Directory.GetFiles(path);

        if (files.Length == 0)
        {
            Console.WriteLine($"\t- n/a this is probably the first time we have authenticated...");
        }
        else
        {
            Console.WriteLine($"Files;");
            foreach (var file in files)
            {
                Console.WriteLine($"\t- {Path.GetFileName(file)}");
            }
        }
        //4) create a single HttpClient, this will be efficiently re-used by GooglePhotosService
        var handler = new HttpClientHandler {
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
        };
        var client = new HttpClient(handler)
        {
            BaseAddress = new Uri(options.BaseAddress)
        };

        //5) new-up the GooglePhotosService passing in the previous references (in lieu of dependency injection)
        _googlePhotosSvc = new GooglePhotosService(logger, Options.Create(options), client);

        //6) log-in
        if (!await _googlePhotosSvc.LoginAsync())
        {
            throw new Exception($"login failed!");
        }

        //get existing/create new album
        var albumTitle = $"{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss}-{Guid.NewGuid()}";//make-up a random title
        var album      = await _googlePhotosSvc.GetOrCreateAlbumAsync(albumTitle);

        if (album is null)
        {
            throw new Exception("album creation failed!");
        }
        Console.WriteLine($"{nameof(album)} '{album.title}' id is '{album.id}'");

        //upload single media item and assign to album
        var mediaItem = await _googlePhotosSvc.UploadSingle($"{_testFolder}test1.jpg", album.id);

        if (mediaItem is null)
        {
            throw new Exception("media item upload failed!");
        }
        Console.WriteLine($"{nameof(mediaItem)} '{mediaItem.mediaItem.filename}' id is '{mediaItem.mediaItem.id}'");

        //retrieve all media items in the album
        var albumMediaItems = await _googlePhotosSvc.GetMediaItemsByAlbumAsync(album.id);

        if (albumMediaItems is null)
        {
            throw new Exception("retrieve media items by album id failed!");
        }
        var i = 1;

        foreach (var item in albumMediaItems)
        {
            Console.WriteLine($"{i}\t{item.filename}\t{item.mediaMetadata.width}x{item.mediaMetadata.height}");
            i++;
        }
    }
Esempio n. 14
0
 public Logout(IConsole console, DiskCacheService diskCacheSvc, GooglePhotosService googlePhotosSvc) : base(console, diskCacheSvc, googlePhotosSvc)
 {
 }
Esempio n. 15
0
        public Place TransformAPINerabyPlaceToPlace(GooglePlace gp)
        {
            IPhotosService photoService = new GooglePhotosService();

            var   gplace = gp;
            Place place  = new Place()
            {
                Id         = gp.PlaceId,
                Name       = gp.Name,
                Categories = gp.Categories ?? new List <string>(),
                Rating     = gp.Rating,
                Location   = gp.Geometry.Location.Latitude.ToString() + " " + gp.Geometry.Location.Longitude.ToString(),
                Address    = gp.Address ?? "",
                Icon       = gp.Icon,
                OpenNow    = gp.OpenHours?.OpenNow ?? false
            };

            if (gp.GooglePhotos == null)
            {
                place.PhotoReference = place.Icon;
                place.Photo          = place.Icon;
            }
            else
            {
                place.PhotoReference = gp.GooglePhotos[0].PhotoReference;
                place.Photo          = photoService.GetImageByReference(place.PhotoReference, "100", "80");
            }

            if (gp.PriceLevel.ToString() != "")
            {
                place.PriceLevel = gp.PriceLevel.ToString();
            }
            else
            {
                place.PriceLevel = "5";
            }

            switch (place.PriceLevel)
            {
            case "0":
                place.PriceString = "free";
                break;

            case "1":
                place.PriceString = "cheap";
                break;

            case "2":
                place.PriceString = "moderate";
                break;

            case "3":
                place.PriceString = "expensive";
                break;

            case "4":
                place.PriceString = "very expensive";
                break;

            case "5":
                place.PriceString = "unknown";
                break;
            }
            return(place);
        }
Esempio n. 16
0
 public Program(IConsole console, GooglePhotosService googlePhotosSvc)
 {
     _console         = console;
     _googlePhotosSvc = googlePhotosSvc;
 }
Esempio n. 17
0
 public MediaItems(IConsole console, DiskCacheService diskCacheSvc, GooglePhotosService googlePhotosSvc) : base(console, diskCacheSvc, googlePhotosSvc)
 {
 }