using System; using Google.Apis.Auth.OAuth2; using Google.Apis.Auth.OAuth2.Flows; using Google.Apis.Services; using Google.Apis.Drive.v3; using Google.Apis.Util.Store; using Google.Apis.Drive.v3.Data; using System.IO; using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using AsbCloudApp.Services; using Google.Apis.Auth.OAuth2.Responses; namespace AsbCloudInfrastructure.Services { public class GoogleDriveService : IFileShareService, IDisposable { private readonly DriveService service; const string applicationName = "FileSharing"; const string username = "asbautodrilling@gmail.com"; const string redirectUri = "http://autodrilling.naftagaz.com/AuthCallback/IndexAsync"; const string clientId = "1020584579240-f7amqg35qg7j94ta1ntgitajq27cgh49.apps.googleusercontent.com"; const string clientSecret = "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"; const string authorizationCode = "4/0AX4XfWgwsZ5QIGwAbuyOyA9oGfcHVIhduERn3wUBVL04TPF1unHf5zWr58nWdLlDDlYBIA"; const string refreshToken = "1//04n0Xn0AxQbN6CgYIARAAGAQSNwF-L9Ir-Lo-3BAskEKuy-SmllhhjYrmAzmZ2h9GaUNqEQjTIpb9wOanarU2JPI3zOj_cyYVRm4"; static readonly IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer { ClientSecrets = new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }, Scopes = new[] { DriveService.Scope.Drive }, DataStore = new FileDataStore(applicationName),//TODO: replace FileDataStore by thread safe static datastore service }); public GoogleDriveService() { service = MakeDriveServiceAsync(CancellationToken.None).Result; } ~GoogleDriveService() { Dispose(); } private async Task MakeDriveServiceAsync(CancellationToken cancellationToken) { var token = await flow.LoadTokenAsync(username, cancellationToken).ConfigureAwait(false); if (flow.ShouldForceTokenRetrieval() || token is null || token.IsExpired(flow.Clock)) { token = await flow.RefreshTokenAsync(clientId, refreshToken, cancellationToken).ConfigureAwait(false); //token = await flow.ExchangeCodeForTokenAsync(clientId, authorizationCode, redirectUri, cancellationToken).ConfigureAwait(false); await flow.DataStore.StoreAsync(username, token).ConfigureAwait(false); } var credential = new UserCredential(flow, username, token); var newService = new DriveService(new BaseClientService.Initializer { HttpClientInitializer = credential, ApplicationName = applicationName }); return newService; } public async Task> GetAllFileNames() { var fileList = service.Files.List(); fileList.Fields = "files(id, webViewLink, size)"; var result = new List(); string pageToken = null; do { fileList.PageToken = pageToken; var filesResult = await fileList.ExecuteAsync(); var files = filesResult.Files; pageToken = filesResult.NextPageToken; result.AddRange(files); } while (pageToken != null); return result.Select(r => r.Name); } public async Task GetFileWebLinkAsync(string idFile, CancellationToken token = default) { var fileList = service.Files.List(); fileList.Fields = "files(id, webViewLink, size)"; var filesResult = await fileList.ExecuteAsync(token) .ConfigureAwait(false); var file = filesResult.Files.FirstOrDefault(f => f.Id == idFile); return file?.WebViewLink ?? string.Empty; } public async Task CreateFolderAsync(string folderName, CancellationToken token = default) { var driveFolder = new Google.Apis.Drive.v3.Data.File(); driveFolder.Name = folderName; driveFolder.MimeType = "application/vnd.google-apps.folder"; //driveFolder.Parents = new string[] { parent }; var command = service.Files.Create(driveFolder); var file = await command.ExecuteAsync(token) .ConfigureAwait(false); return file.Id; } public async Task CreatePublicPermissionForFileAsync(string idFile, CancellationToken token = default) { var permission = new Permission() { Type = "anyone", Role = "reader"}; var addPermissionRequest = service.Permissions.Create(permission, idFile); await addPermissionRequest.ExecuteAsync(token) .ConfigureAwait(false); } public async Task UploadFileAsync(Stream file, string fileName, string fileMime, string fileDescription, CancellationToken token = default) { var driveFile = new Google.Apis.Drive.v3.Data.File(); driveFile.Name = fileName; driveFile.Description = fileDescription; driveFile.MimeType = fileMime; //driveFile.Parents = new [] {folder}; var request = service.Files.Create(driveFile, file, fileMime); request.Fields = "id"; var response = await request.UploadAsync(token) .ConfigureAwait(false); if (response.Status != Google.Apis.Upload.UploadStatus.Completed) throw response.Exception; return request.ResponseBody.Id; } public async Task DeleteFileAsync(string fileId, CancellationToken token = default) { var command = service.Files.Delete(fileId); var result = await command.ExecuteAsync(token) .ConfigureAwait(false); } #pragma warning disable CA1816 // Методы Dispose должны вызывать SuppressFinalize public void Dispose() { service?.Dispose(); } #pragma warning restore CA1816 // Методы Dispose должны вызывать SuppressFinalize public async Task PublishFileToCloudAsync(string filePath, string originalName, CancellationToken token) { await using var fileStream = System.IO.File.Open(filePath, FileMode.Open); var uploadedFileId = await UploadFileAsync(fileStream, originalName, "", "uploaded", token) .ConfigureAwait(false); await CreatePublicPermissionForFileAsync(uploadedFileId, token) .ConfigureAwait(false); var webLink = await GetFileWebLinkAsync(uploadedFileId, token) .ConfigureAwait(false); return webLink; } } }