using Google.Apis.Auth.OAuth2; using Google.Apis.Services; using Google.Apis.Sheets.v4; using framework_library; using System; using System.IO; namespace framework_business.handlers { public class GoogleSheetsHelper { public SheetsService Service { get; set; } static readonly string[] Scopes = { SheetsService.Scope.Spreadsheets }; public GoogleSheetsHelper(string applicationName) { InitializeService(applicationName); } private void InitializeService(string applicationName) { var credential = GetCredentialsFromFile(); Service = new SheetsService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = applicationName }); } private GoogleCredential GetCredentialsFromFile() { string filePath = Environment.GetEnvironmentVariable("GOOGLE_SHEETS_CREDENTIALS_FILE"); if (string.IsNullOrEmpty(filePath)) throw new InvalidOperationException( "GOOGLE_SHEETS_CREDENTIALS_FILE must be set in .env or the process environment."); filePath = ResolveCredentialsPath(filePath); if (!File.Exists(filePath)) throw new FileNotFoundException( "Google Sheets credentials file not found at: " + filePath, filePath); using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { return GoogleCredential.FromStream(stream).CreateScoped(Scopes); } } private static string ResolveCredentialsPath(string filePath) { if (Path.IsPathRooted(filePath)) return filePath; if (EnvBootstrap.IsLoaded && !string.IsNullOrEmpty(EnvBootstrap.LoadedPath)) { string repoRoot = Path.GetDirectoryName(EnvBootstrap.LoadedPath); if (!string.IsNullOrEmpty(repoRoot)) { string fromRepo = Path.GetFullPath(Path.Combine(repoRoot, filePath.TrimStart('.', '/', '\\'))); if (File.Exists(fromRepo)) return fromRepo; } } return Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, filePath)); } } }