diff --git a/LeanderShiftPlannerV2/FileIO/GoogleApiLoader.cs b/LeanderShiftPlannerV2/FileIO/GoogleApiLoader.cs index 1757cdb..65935d8 100644 --- a/LeanderShiftPlannerV2/FileIO/GoogleApiLoader.cs +++ b/LeanderShiftPlannerV2/FileIO/GoogleApiLoader.cs @@ -7,7 +7,7 @@ namespace LeanderShiftPlannerV2.FileIO; public static class GoogleApiLoader { - public static bool CheckFileSystem() + public static bool CheckFileSystem_ReadFile() { if (!Directory.Exists(Constants.DataPath)) Directory.CreateDirectory(Constants.DataPath); @@ -20,10 +20,22 @@ public static class GoogleApiLoader } return true; } + + public static bool CheckFileSystem_ReadToken() + { + if (!Directory.Exists(Constants.DataPath)) + Directory.CreateDirectory(Constants.DataPath); + if (!File.Exists(Constants.DataPath + Constants.GoogleApiTokenPath)) + { + File.Create(Constants.DataPath + Constants.GoogleApiTokenPath); + return false; + } + return true; + } public static Dictionary ReadFile() { - if (!CheckFileSystem()) return new Dictionary(); + if (!CheckFileSystem_ReadFile()) return new Dictionary(); Dictionary apiSecrets = new Dictionary(); try @@ -51,4 +63,30 @@ public static class GoogleApiLoader return apiSecrets; } + + public static void WriteToken(string token) + { + if (File.Exists(Constants.DataPath + Constants.GoogleApiTokenPath)) + File.Delete(Constants.DataPath + Constants.GoogleApiTokenPath); + File.Create(Constants.DataPath + Constants.GoogleApiTokenPath).Close(); + File.WriteAllText(Constants.DataPath + Constants.GoogleApiTokenPath, token); + } + + public static string? ReadToken() + { + if (!CheckFileSystem_ReadToken()) return null; + string tokenString = null; + + try + { + tokenString = File.ReadAllText(Constants.DataPath + Constants.GoogleApiTokenPath); + } + catch (Exception ex) + { + //TODO + Console.WriteLine($"Fehler beim Lesen der Datei: {ex.Message}"); + } + + return (tokenString.Equals(String.Empty) ? null : tokenString); + } } \ No newline at end of file diff --git a/LeanderShiftPlannerV2/LeanderShiftPlannerV2.csproj b/LeanderShiftPlannerV2/LeanderShiftPlannerV2.csproj index a5adc0f..64fdf71 100644 --- a/LeanderShiftPlannerV2/LeanderShiftPlannerV2.csproj +++ b/LeanderShiftPlannerV2/LeanderShiftPlannerV2.csproj @@ -8,10 +8,10 @@ Resources/icon/ShiftPlannerIcon.ico true Resources\icon\ShiftPlannerIcon.png - 1.0.5 - 1.0.5 + 2.0.2 + 2.0.2 en - 1.0.5 + 2.0.2 diff --git a/LeanderShiftPlannerV2/Service/TimesheetService.cs b/LeanderShiftPlannerV2/Service/TimesheetService.cs index 479eaf1..42623e6 100644 --- a/LeanderShiftPlannerV2/Service/TimesheetService.cs +++ b/LeanderShiftPlannerV2/Service/TimesheetService.cs @@ -10,6 +10,8 @@ using System.Threading.Tasks; using LeanderShiftPlannerV2.Model; using LeanderShiftPlannerV2.Util; using Google.Apis.Auth.OAuth2; +using Google.Apis.Auth.OAuth2.Flows; +using Google.Apis.Auth.OAuth2.Responses; using Google.Apis.Calendar.v3; using Google.Apis.Services; using LeanderShiftPlannerV2.FileIO; @@ -30,51 +32,81 @@ public class TimesheetService public async Task GenerateGoogleTimeSheets(List persons, bool randomize) { - string[] scopes = { CalendarService.Scope.CalendarReadonly }; const string applicationName = "LeanderShiftPlanner"; Dictionary secrets = GoogleApiLoader.ReadFile(); if (!secrets.ContainsKey(Constants.GoogleClientId) || !secrets.ContainsKey(Constants.GoogleClientSecret)) return; - if (secrets[Constants.GoogleClientId].Equals(string.Empty) || secrets[Constants.GoogleClientSecret].Equals(string.Empty)) + if (secrets[Constants.GoogleClientId].Equals(string.Empty) || + secrets[Constants.GoogleClientSecret].Equals(string.Empty)) return; - + + UserCredential credential; + string[] scopes = { CalendarService.Scope.CalendarReadonly }; ClientSecrets clientSecrets = new ClientSecrets(); clientSecrets.ClientId = secrets[Constants.GoogleClientId]; clientSecrets.ClientSecret = secrets[Constants.GoogleClientSecret]; - //clientSecrets.ClientId = "823920428427-ub5n9a9dkfpuvjlut4eneg2058so49o3.apps.googleusercontent.com"; - //clientSecrets.ClientSecret = "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"; - UserCredential credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets, scopes, "user", CancellationToken.None); - + string? tokenString = GoogleApiLoader.ReadToken(); + + + try + { + TokenResponse token = new TokenResponse { RefreshToken = tokenString }; + + credential = new UserCredential( + new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer + { + ClientSecrets = clientSecrets + }), + "user", + token + ); + + if (!await credential.RefreshTokenAsync(CancellationToken.None)) + { + credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets, scopes, "user", + CancellationToken.None); + GoogleApiLoader.WriteToken(credential.Token.RefreshToken); + } + } + catch (Exception e) + { + credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(clientSecrets, scopes, "user", + CancellationToken.None); + GoogleApiLoader.WriteToken(credential.Token.RefreshToken); + } + + // Erstelle den CalendarService - var service = new CalendarService(new BaseClientService.Initializer() + CalendarService service = new CalendarService(new BaseClientService.Initializer() { HttpClientInitializer = credential, ApplicationName = applicationName, }); - + foreach (Person person in persons) { foreach (string month in Constants.Months) { if (month == Constants.Months[0]) continue; List<(DateTime, DateTime, bool)> timesheetValue = new List<(DateTime, DateTime, bool)>(); - + // Aktuelles Datum DateTime now = DateTime.Now; // Erster Tag des aktuellen Monats (00:00:00 Uhr) DateTime firstDayOfMonth = new DateTime(now.Year, Constants.Months.IndexOf(month), 1, 0, 0, 0); // Letzter Tag des aktuellen Monats (23:59:59 Uhr) - DateTime lastDayOfMonth = new DateTime(now.Year, Constants.Months.IndexOf(month), DateTime.DaysInMonth(now.Year, Constants.Months.IndexOf(month)), + DateTime lastDayOfMonth = new DateTime(now.Year, Constants.Months.IndexOf(month), + DateTime.DaysInMonth(now.Year, Constants.Months.IndexOf(month)), 23, 59, 59); - + // Beispiel: Liste die nächsten 10 Ereignisse im ITM Kalender auf var requestItm = service.Events.List("on089es7kq4ugi3rqvslkn7720@group.calendar.google.com"); requestItm.TimeMinDateTimeOffset = firstDayOfMonth; requestItm.TimeMaxDateTimeOffset = lastDayOfMonth; requestItm.SingleEvents = true; - + var requestWebService = service.Events.List("s4rdo3uk2on8ualv1goaktbiec@group.calendar.google.com"); requestWebService.TimeMinDateTimeOffset = firstDayOfMonth; requestWebService.TimeMaxDateTimeOffset = lastDayOfMonth; @@ -82,14 +114,14 @@ public class TimesheetService var eventsItm = await requestItm.ExecuteAsync(); var eventsWebService = await requestWebService.ExecuteAsync(); - + foreach (var eventItem in eventsItm.Items) { if (eventItem.Start.DateTime == null || eventItem.End.DateTime == null) continue; if (eventItem.Summary.Contains(person.FirstName)) { - DateTime dayStart = (DateTime) eventItem.Start.DateTime; - DateTime dayEnd = (DateTime) eventItem.End.DateTime; + DateTime dayStart = (DateTime)eventItem.Start.DateTime; + DateTime dayEnd = (DateTime)eventItem.End.DateTime; timesheetValue.Add((dayStart, dayEnd, (dayEnd.Hour > 13))); } } @@ -99,12 +131,12 @@ public class TimesheetService if (eventItem.Start.DateTime == null || eventItem.End.DateTime == null) continue; if (eventItem.Summary.Contains(person.FirstName)) { - DateTime dayStart = (DateTime) eventItem.Start.DateTime; - DateTime dayEnd = (DateTime) eventItem.End.DateTime; + DateTime dayStart = (DateTime)eventItem.Start.DateTime; + DateTime dayEnd = (DateTime)eventItem.End.DateTime; timesheetValue.Add((dayStart, dayEnd, false)); } } - + person.Timesheets.Add(new Timesheet(month, timesheetValue)); } @@ -124,17 +156,18 @@ public class TimesheetService if (pattern.Count == 0) continue; List holidays = await GetHolidays(); List weekends = GetWeekends(); - + int monthHours = person.Hours * 4; foreach (string month in Constants.Months) { if (month == Constants.Months[0]) continue; List<(DateTime, DateTime, bool)> timesheetValue = new List<(DateTime, DateTime, bool)>(); - + int currentPersonHours = 0; int currentPatternIndex = 0; int dayOfMonth = 1; - int lastDayOfMonth = new DateTime(DateTime.Now.Year, Constants.Months.IndexOf(month), dayOfMonth).AddMonths(1).AddDays(-1).Day; + int lastDayOfMonth = new DateTime(DateTime.Now.Year, Constants.Months.IndexOf(month), dayOfMonth) + .AddMonths(1).AddDays(-1).Day; while (currentPersonHours != monthHours) { DateTime currentDay = new DateTime(DateTime.Now.Year, Constants.Months.IndexOf(month), dayOfMonth); @@ -148,7 +181,8 @@ public class TimesheetService { case 6: { - DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 9, 0, 0); + DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 9, 0, + 0); DateTime dayEnd = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 16, 0, 0); timesheetValue.Add((dayStart, dayEnd, true)); currentPersonHours += 6; @@ -156,7 +190,8 @@ public class TimesheetService } case 4: { - DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 9, 0, 0); + DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 9, 0, + 0); DateTime dayEnd = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 13, 0, 0); timesheetValue.Add((dayStart, dayEnd, false)); currentPersonHours += 4; @@ -164,7 +199,8 @@ public class TimesheetService } case 2: { - DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 14, 0, 0); + DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 14, 0, + 0); DateTime dayEnd = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 16, 0, 0); timesheetValue.Add((dayStart, dayEnd, false)); currentPersonHours += 2; @@ -172,14 +208,15 @@ public class TimesheetService } case 1: { - DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 9, 0, 0); + DateTime dayStart = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 9, 0, + 0); DateTime dayEnd = new DateTime(currentDay.Year, currentDay.Month, currentDay.Day, 10, 0, 0); timesheetValue.Add((dayStart, dayEnd, false)); currentPersonHours += 1; break; } } - + dayOfMonth++; if (dayOfMonth > lastDayOfMonth) throw new Exception("Too many hours!"); currentPatternIndex = (currentPatternIndex + 1) % pattern.Count; @@ -202,7 +239,8 @@ public class TimesheetService for (int i = 0; i <= daysInYear; i++) { DateTime currentDay = firstDayOfYear.AddDays(i); - if (currentDay.DayOfWeek == DayOfWeek.Saturday || currentDay.DayOfWeek == DayOfWeek.Sunday) weekends.Add(currentDay); + if (currentDay.DayOfWeek == DayOfWeek.Saturday || currentDay.DayOfWeek == DayOfWeek.Sunday) + weekends.Add(currentDay); } return weekends; @@ -295,7 +333,7 @@ public class TimesheetService private int CalcHours(Timesheet timesheet) { double hours = 0; - + foreach ((DateTime, DateTime, bool) tuple in timesheet.Value) { if (tuple.Item3) @@ -307,32 +345,34 @@ public class TimesheetService hours += (tuple.Item2 - tuple.Item1).TotalHours; } } - - return (int) hours; + + return (int)hours; } private async Task CheckForNotEnoughHours(Person person) { List holidays = await GetHolidays(); List weekends = GetWeekends(); - + int monthHours = person.Hours * 4; foreach (string month in Constants.Months) { if (month == Constants.Months[0]) continue; Timesheet timesheet = person.GetTimeSheetByMonth(month); List<(DateTime, DateTime, bool)> timesheetValue = timesheet.Value; - + int currentPersonHours = CalcHours(timesheet); List pattern = GetPattern((person.Hours * 4) - currentPersonHours); - + int currentPatternIndex = 0; int dayOfMonth = 1; - int lastDayOfMonth = new DateTime(DateTime.Now.Year, Constants.Months.IndexOf(month), dayOfMonth).AddMonths(1).AddDays(-1).Day; + int lastDayOfMonth = new DateTime(DateTime.Now.Year, Constants.Months.IndexOf(month), dayOfMonth) + .AddMonths(1).AddDays(-1).Day; while (currentPersonHours != monthHours) { DateTime currentDay = new DateTime(DateTime.Now.Year, Constants.Months.IndexOf(month), dayOfMonth); - if (holidays.Contains(currentDay) || weekends.Contains(currentDay) || CheckForDayIsNotEmpty(currentDay, timesheetValue)) + if (holidays.Contains(currentDay) || weekends.Contains(currentDay) || + CheckForDayIsNotEmpty(currentDay, timesheetValue)) { dayOfMonth++; continue; @@ -373,7 +413,7 @@ public class TimesheetService break; } } - + dayOfMonth++; if (dayOfMonth > lastDayOfMonth) throw new Exception($"Too many hours for Person {person.FirstName}!"); currentPatternIndex = (currentPatternIndex + 1) % pattern.Count; @@ -387,7 +427,7 @@ public class TimesheetService { if (tuple.Item1.Date.Day == currentDay.Day) return true; } - + return false; } } \ No newline at end of file diff --git a/LeanderShiftPlannerV2/Util/Constants.cs b/LeanderShiftPlannerV2/Util/Constants.cs index f2730fa..113af93 100644 --- a/LeanderShiftPlannerV2/Util/Constants.cs +++ b/LeanderShiftPlannerV2/Util/Constants.cs @@ -21,6 +21,7 @@ namespace LeanderShiftPlannerV2.Util public const string GoogleClientId = "GoogleClientId"; public const string GoogleClientSecret = "GoogleClientSecret"; public const string GoogleApiFileResource = @"Resources/templates/googleapi.txt"; + public const string GoogleApiTokenPath = @"/googleapitoken.txt"; // TimeSheets public static readonly string TimeSheetSourceRandom = "Random"; diff --git a/LeanderShiftPlannerV2/View/LeanderShiftPlannerView/LeanderShiftPlannerMainWindow.axaml.cs b/LeanderShiftPlannerV2/View/LeanderShiftPlannerView/LeanderShiftPlannerMainWindow.axaml.cs index 31044b8..70c5e1e 100644 --- a/LeanderShiftPlannerV2/View/LeanderShiftPlannerView/LeanderShiftPlannerMainWindow.axaml.cs +++ b/LeanderShiftPlannerV2/View/LeanderShiftPlannerView/LeanderShiftPlannerMainWindow.axaml.cs @@ -47,7 +47,8 @@ public partial class LeanderShiftPlannerMainWindow : Window private void CreateApiFile() { - GoogleApiLoader.CheckFileSystem(); + GoogleApiLoader.CheckFileSystem_ReadFile(); + GoogleApiLoader.CheckFileSystem_ReadToken(); } // ------------------------------------------------------UI-Interactions------------------------------------------------------