private async Task<IEnumerable<object[]>> ExecuteYouTubeDataApiV3(IConfiguration youTubeConf, string clientSecretsJson,
			string sharedSecretFolder, ILogger<YouTubePlaylistDumpOperation> logger, BloggingContext context,
			IHostingEnvironment environment, CancellationToken token)
		{
			UserCredential credential;

			using (var stream = new FileStream(clientSecretsJson, FileMode.Open, FileAccess.Read))
			{
				var store = new EFContextDataStore<BloggingContext>(context, environment, token);

				credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
					GoogleClientSecrets.Load(stream).Secrets,
					// This OAuth 2.0 access scope allows for read-only access to the authenticated 
					// user's account, but not other types of account access.
					new[] { YouTubeService.Scope.YoutubeReadonly },
					"user", token, store
					);
			}

			using (var youtubeService = new YouTubeService(new BaseClientService.Initializer
			{
				HttpClientInitializer = credential,
				ApplicationName = youTubeConf["ApplicationName"]
			}))
			{
				var lst = new List<object[]>(365);
				var nextPageToken = "";
				while (nextPageToken != null)
				{
					var playlistItemsListRequest = youtubeService.PlaylistItems.List("snippet");
					playlistItemsListRequest.PlaylistId = youTubeConf["playlistId"];
					// playlistItemsListRequest.Fields = "items(snippet(title,position,resourceId(videoId)))";
					playlistItemsListRequest.MaxResults = 50;
					playlistItemsListRequest.PageToken = nextPageToken;
					// Retrieve the list of videos uploaded to the authenticated user's channel.
					var playlistItemsListResponse = await playlistItemsListRequest.ExecuteAsync(token);

					foreach (var item in playlistItemsListResponse.Items)
					{
						lst.Add(new object[] {
							item.Snippet.Position,
							item.Snippet.Title,
							item.Snippet.ResourceId.VideoId,
							item.Snippet.PublishedAt.GetValueOrDefault(DateTime.MinValue)//.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)
						});
					}

					nextPageToken = playlistItemsListResponse.NextPageToken;
				}

				return lst;
			}//end using youtubeService
		}
        private async Task <bool> ExecuteYouTubeDataApiV3(IConfiguration youTubeConf, string clientSecretsJson,
                                                          string sharedSecretFolder, ILogger <YouTubeUploadOperation> logger, BloggingContext context,
                                                          IHostingEnvironment environment, CancellationToken token)
        {
            UserCredential credential;

            using (var stream = new FileStream(clientSecretsJson, FileMode.Open, FileAccess.Read))
            {
                var store = new EFContextDataStore <BloggingContext>(context, environment, token);

                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    // This OAuth 2.0 access scope allows for read-only access to the authenticated
                    // user's account, but not other types of account access.
                    new[] { YouTubeService.Scope.Youtube, YouTubeService.Scope.YoutubeUpload },
                    "user", token, store
                    );
            }

            using (var youtubeService = new YouTubeService(new BaseClientService.Initializer
            {
                HttpClientInitializer = credential,
                ApplicationName = youTubeConf["ApplicationName"]
            }))
            {
                string new_video_title  = $"timelapse {DateTime.Now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)}";
                bool   already_uploaded = false;
                var    nextPageToken    = "";
                while (nextPageToken != null && !already_uploaded)
                {
                    var playlistItemsListRequest = youtubeService.PlaylistItems.List("snippet");
                    playlistItemsListRequest.PlaylistId = youTubeConf["playlistId"];
                    playlistItemsListRequest.Fields     = "items(snippet(description,publishedAt,title))";
                    playlistItemsListRequest.MaxResults = 10;
                    playlistItemsListRequest.PageToken  = nextPageToken;
                    // Retrieve the list of videos uploaded to the authenticated user's channel.
                    var playlistItemsListResponse = await playlistItemsListRequest.ExecuteAsync(token);

                    foreach (var item in playlistItemsListResponse.Items)
                    {
                        // Print information about each video.
                        logger.LogInformation("'{title}' [{description}] {publishedAt}", item.Snippet.Title, item.Snippet.Description,
                                              item.Snippet.PublishedAt);

                        if (item.Snippet.Title == new_video_title)
                        {
                            already_uploaded = true;
                            logger.LogWarning("'{title}' already uploaded aborting", item.Snippet.Title);
                            break;
                        }
                    }

                    nextPageToken = playlistItemsListResponse.NextPageToken;
                }

#if DEBUG
                already_uploaded = true;
#endif
                if (already_uploaded || string.IsNullOrEmpty(_videoFileNameToUpload))
                {
                    return(false);
                }

                //upload
                var video = new Video
                {
                    Snippet = new VideoSnippet
                    {
                        Title       = new_video_title,
                        Description = $"Daily timelapse video taken on {DateTime.Now}",
                        Tags        = new string[] { "timelapse", "video", "webcam" },
                        //"1" -> "Film & Animation", see https://developers.google.com/youtube/v3/docs/videoCategories/list
                        CategoryId = "1",
                    },
                    Status = new VideoStatus
                    {
                        PrivacyStatus = "unlisted"                         // or "private" or "public"
                    }
                };

                string successVideoID = null;
                using (var fileStream = new FileStream(_videoFileNameToUpload, FileMode.Open, FileAccess.Read))
                {
                    var videosInsertRequest = youtubeService.Videos.Insert(video, "snippet,status", fileStream, "video/*");
                    videosInsertRequest.ProgressChanged += (IUploadProgress progress) =>
                    {
                        switch (progress.Status)
                        {
                        case UploadStatus.Uploading:
                            logger.LogInformation("{bytesSent} bytes sent.", progress.BytesSent);
                            break;

                        case UploadStatus.Failed:
                            logger.LogWarning("An error prevented the upload from completing.\n{exception}", progress.Exception);
                            break;
                        }
                    };
                    videosInsertRequest.ResponseReceived += (Video uploadedVideo) =>
                    {
                        successVideoID = uploadedVideo.Id;
                        logger.LogInformation("Video id '{id}' was successfully uploaded.", uploadedVideo.Id);
                    };

                    var uploaded = await videosInsertRequest.UploadAsync(token);

                    if (uploaded.Status == UploadStatus.Completed && !string.IsNullOrEmpty(successVideoID))
                    {
                        var newPlaylistItem = new PlaylistItem();
                        newPlaylistItem.Snippet                    = new PlaylistItemSnippet();
                        newPlaylistItem.Snippet.PlaylistId         = youTubeConf["playlistId"];
                        newPlaylistItem.Snippet.ResourceId         = new ResourceId();
                        newPlaylistItem.Snippet.ResourceId.Kind    = "youtube#video";
                        newPlaylistItem.Snippet.ResourceId.VideoId = successVideoID;
                        newPlaylistItem = await youtubeService.PlaylistItems.Insert(newPlaylistItem, "snippet")
                                          .ExecuteAsync(token);

                        logger.LogInformation("Video id '{id}' was added to playlist id '{playlistID}'.",
                                              successVideoID, newPlaylistItem.Snippet.PlaylistId);

                        return(true);
                    }

                    return(false);
                } //end using fileStream
            }     //end using youtubeService
        }