From 49275681fddb2124149002d1148223b5f6e0568e Mon Sep 17 00:00:00 2001 From: Giovani Date: Thu, 9 Apr 2020 21:11:01 -0400 Subject: [PATCH] wip --- .../HttpSyncFunction.cs | 2 +- .../ScheduledSyncFunction.cs | 5 +-- .../Habitica/ChecklistItem.cs | 15 ++++++++ .../Habitica/Task.cs | 2 ++ .../Todoist/Item.cs | 8 +++++ .../Extensions.cs | 17 ++++++++++ .../HabiticaIntegrationService.cs | 30 ++++++++++++++-- .../HabiticaServiceClient.cs | 12 +++++++ .../TodoistIntegrationService.cs | 34 +++++++++++-------- .../TodoistServiceClient.cs | 12 ++++--- 10 files changed, 112 insertions(+), 25 deletions(-) create mode 100644 Habitica.Todoist.Integration.Model/Habitica/ChecklistItem.cs diff --git a/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs b/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs index 1031db2..94a1aa8 100644 --- a/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs +++ b/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs @@ -39,7 +39,7 @@ namespace Habitica.Todoist.Integration.Function.Sync var items = await todoistService.ReadItemChanges(); // perform actions - await habiticaService.AddTasks(items.WhereAdded()); + await habiticaService.Add(items.WhereAdded()); await habiticaService.UpdateTasks(items.WhereUpdated()); await habiticaService.CompleteTasks(items.WhereCompleted()); await habiticaService.DeleteTasks(items.WhereDeleted()); diff --git a/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs b/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs index 157df22..bf5d0bd 100644 --- a/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs +++ b/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs @@ -21,7 +21,7 @@ namespace Habitica.Todoist.Integration.Function.Sync [Singleton("SyncLock", SingletonScope.Host)] [FunctionName("ScheduledSyncFunction")] - public static async Task Run([TimerTrigger("0 0 * * * *")]TimerInfo myTimer, ILogger log) + public static async Task Run([TimerTrigger("* * * * * *")]TimerInfo myTimer, ILogger log) { // initialize integration services var todoistService = new TodoistIntegrationService(ScheduledConfiguration.TodoistApiKey, @@ -33,10 +33,11 @@ namespace Habitica.Todoist.Integration.Function.Sync ScheduledConfiguration.GiosUserId); // get all changed items from todoist + var items = await todoistService.ReadItemChanges(); // perform actions - await habiticaService.AddTasks(items.WhereAdded()); + await habiticaService.Add(items.WhereAdded()); await habiticaService.UpdateTasks(items.WhereUpdated()); await habiticaService.CompleteTasks(items.WhereCompleted()); await habiticaService.DeleteTasks(items.WhereDeleted()); diff --git a/Habitica.Todoist.Integration.Model/Habitica/ChecklistItem.cs b/Habitica.Todoist.Integration.Model/Habitica/ChecklistItem.cs new file mode 100644 index 0000000..0f15fb4 --- /dev/null +++ b/Habitica.Todoist.Integration.Model/Habitica/ChecklistItem.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Habitica.Todoist.Integration.Model.Habitica +{ + public class ChecklistItem + { + [JsonProperty("id")] + public string Id { get; set; } + [JsonProperty("text")] + public string Text { get; set; } + } +} diff --git a/Habitica.Todoist.Integration.Model/Habitica/Task.cs b/Habitica.Todoist.Integration.Model/Habitica/Task.cs index 192b1b9..6185b88 100644 --- a/Habitica.Todoist.Integration.Model/Habitica/Task.cs +++ b/Habitica.Todoist.Integration.Model/Habitica/Task.cs @@ -15,6 +15,8 @@ namespace Habitica.Todoist.Integration.Model.Habitica public string Date { get; set; } [JsonProperty("priority")] public string Priority { get; set; } + [JsonProperty("checklist", NullValueHandling = NullValueHandling.Ignore)] + public List Checklist { get; set; } [JsonProperty("id")] public string Id { get; set; } } diff --git a/Habitica.Todoist.Integration.Model/Todoist/Item.cs b/Habitica.Todoist.Integration.Model/Todoist/Item.cs index bad23a4..3b5f1e1 100644 --- a/Habitica.Todoist.Integration.Model/Todoist/Item.cs +++ b/Habitica.Todoist.Integration.Model/Todoist/Item.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.Linq; namespace Habitica.Todoist.Integration.Model.Todoist @@ -14,9 +15,16 @@ namespace Habitica.Todoist.Integration.Model.Todoist public Due Due { get; set; } [JsonProperty("priority")] public int Priority { get; set; } + [JsonProperty("parent_id")] + public string Parent_Id { get; set; } [JsonProperty("is_deleted")] public int Is_deleted { get; set; } + [JsonProperty("project_id")] + public string Project_id { get; set; } [JsonProperty("date_completed")] public string Date_completed { get; set; } + + [JsonIgnore] + public bool IsChild => !string.IsNullOrEmpty(Parent_Id); } } diff --git a/Habitica.Todoist.Integration.Services/Extensions.cs b/Habitica.Todoist.Integration.Services/Extensions.cs index 8dd9850..2fae40a 100644 --- a/Habitica.Todoist.Integration.Services/Extensions.cs +++ b/Habitica.Todoist.Integration.Services/Extensions.cs @@ -9,8 +9,25 @@ namespace Habitica.Todoist.Integration.Services.Extensions { public static class Extensions { + public static ChecklistItem ToHabiticaChecklistItem(this Item item, string habiticaId = null) + { + if (string.IsNullOrEmpty(item.Parent_Id)) + return null; + + var checklistItem = new ChecklistItem + { + Id = habiticaId, + Text = item.Content + }; + + return checklistItem; + } + public static Task ToHabiticaTask(this Item item, string habiticaId = null) { + if (!string.IsNullOrEmpty(item.Parent_Id)) + return null; + var taskTypeStr = Enum.GetName(typeof(TaskType), TaskType.Todo).ToLower(); var task = new Task { diff --git a/Habitica.Todoist.Integration.Services/HabiticaIntegrationService.cs b/Habitica.Todoist.Integration.Services/HabiticaIntegrationService.cs index f3a449c..73659d6 100644 --- a/Habitica.Todoist.Integration.Services/HabiticaIntegrationService.cs +++ b/Habitica.Todoist.Integration.Services/HabiticaIntegrationService.cs @@ -1,10 +1,12 @@ using Habitica.Todoist.Integration.Data; +using ChecklistItem = Habitica.Todoist.Integration.Model.Habitica.ChecklistItem; using Habitica.Todoist.Integration.Model.Habitica.Enums; using Habitica.Todoist.Integration.Model.Storage; using Habitica.Todoist.Integration.Model.Todoist; using Habitica.Todoist.Integration.Services.Extensions; using System; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; @@ -27,14 +29,22 @@ namespace Habitica.Todoist.Integration.Services this.userId = userId; } - public async Task AddTasks(IEnumerable items) + public async Task Add(IEnumerable items) { - foreach (var item in items) - await AddTask(item); + foreach (var item in items.OrderBy(x => x.Parent_Id)) + { + if (!item.IsChild) + await AddTask(item); + else + await AddChecklistItem(item); + } } public async Task AddTask(Item item) { + if (item.IsChild) + throw new ArgumentException("Item passed as arguement has a valid Parent_Id"); + var task = (await habiticaClient.CreateTask(item.ToHabiticaTask())).Data; var link = new TodoHabitLink(userId, item.Id, task.Id); @@ -42,6 +52,20 @@ namespace Habitica.Todoist.Integration.Services await storageClient.InsertOrUpdate(link.Reverse()); } + public async Task AddChecklistItem(Item item) + { + if (!item.IsChild) + throw new ArgumentException("Item passed as arguement does not have a valid Parent_Id"); + + var habiticaTaskId = (await storageClient.RetrieveRecord(userId, item.Parent_Id)).HabiticaId; + var checklistItem = (await habiticaClient.CreateChecklistItem(item.ToHabiticaChecklistItem(), habiticaTaskId)).Data.Checklist + .First(x => x.Text == item.Content); + + var link = new TodoHabitLink(userId, item.Id, checklistItem.Id); + await storageClient.InsertOrUpdate(link); + await storageClient.InsertOrUpdate(link.Reverse()); + } + public async Task UpdateTasks(IEnumerable items) { foreach (var item in items) diff --git a/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs b/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs index 067becc..59eee18 100644 --- a/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs +++ b/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs @@ -1,4 +1,5 @@ using HabiticaTask = Habitica.Todoist.Integration.Model.Habitica.Task; +using ChecklistItem = Habitica.Todoist.Integration.Model.Habitica.ChecklistItem; using System.Net; using System.Threading.Tasks; using Newtonsoft.Json; @@ -22,6 +23,17 @@ namespace Habitica.Todoist.Integration.Services this.apiKey = apiKey; } + public async Task> CreateChecklistItem(ChecklistItem checklistItem, string taskId) + { + using (var client = CreateWebClient()) + { + var request = JsonConvert.SerializeObject(checklistItem); + var json = await client.UploadStringTaskAsync($"{baseUrl}/tasks/{taskId}/checklist", "POST", request); + + return JsonConvert.DeserializeObject>(json); + } + } + public async Task> CreateTask(HabiticaTask task) { using (var client = CreateWebClient()) diff --git a/Habitica.Todoist.Integration.Services/TodoistIntegrationService.cs b/Habitica.Todoist.Integration.Services/TodoistIntegrationService.cs index 21d7205..0ab9e3e 100644 --- a/Habitica.Todoist.Integration.Services/TodoistIntegrationService.cs +++ b/Habitica.Todoist.Integration.Services/TodoistIntegrationService.cs @@ -29,10 +29,10 @@ namespace Habitica.Todoist.Integration.Services public async Task ReadItemChanges() { - var response = await todoistClient.GetItemChanges(ReadLatestSyncToken()); - latestSyncToken = response.Sync_token; + var itemChangesResponse = await todoistClient.GetItemChanges(ReadLatestSyncToken()); + latestSyncToken = itemChangesResponse.Sync_token; - return new Items(response.Items, storageClient, userId); + return new Items(itemChangesResponse.Items, storageClient, userId); } public async Task CommitRead() @@ -57,48 +57,52 @@ namespace Habitica.Todoist.Integration.Services public class Items : IEnumerable { - private List items { get; set; } + private List changedItems; private readonly TableStorageClient storageClient; private readonly string userId; - internal Items(List items, TableStorageClient storageClient, string userId) + internal Items(List changedItems, TableStorageClient storageClient, string userId) { - this.items = items; + this.changedItems = changedItems; this.storageClient = storageClient; this.userId = userId; } public IEnumerable WhereAdded() { - return items + return changedItems .Where(x => !storageClient - .Exists(userId, x.Id) && x.Is_deleted == 0); + .Exists(userId, x.Id) && x.Is_deleted == 0) + .OrderBy(x => x.Parent_Id); } public IEnumerable WhereUpdated() { - return items + return changedItems .Where(x => storageClient - .Exists(userId, x.Id) && x.Is_deleted == 0); + .Exists(userId, x.Id) && x.Is_deleted == 0) + .OrderBy(x => x.Parent_Id); } public IEnumerable WhereCompleted() { - return items + return changedItems .Where(x => storageClient - .Exists(userId, x.Id) && x.Is_deleted == 0 && x.Date_completed != null); + .Exists(userId, x.Id) && x.Is_deleted == 0 && x.Date_completed != null) + .OrderBy(x => x.Parent_Id); } public IEnumerable WhereDeleted() { - return items + return changedItems .Where(x => storageClient - .Exists(userId, x.Id) && x.Is_deleted == 1); + .Exists(userId, x.Id) && x.Is_deleted == 1) + .OrderBy(x => x.Parent_Id); } public IEnumerator GetEnumerator() { - return items.GetEnumerator(); + return changedItems.OrderBy(x => x.Parent_Id).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() diff --git a/Habitica.Todoist.Integration.Services/TodoistServiceClient.cs b/Habitica.Todoist.Integration.Services/TodoistServiceClient.cs index f82847f..bac5bf9 100644 --- a/Habitica.Todoist.Integration.Services/TodoistServiceClient.cs +++ b/Habitica.Todoist.Integration.Services/TodoistServiceClient.cs @@ -19,11 +19,14 @@ namespace Habitica.Todoist.Integration.Services this.apiKey = apiKey; } - public async Task GetItemChanges(string syncToken = null) + public async Task GetItems() { - if (string.IsNullOrEmpty(syncToken)) - syncToken = "*"; + var response = await GetItemChanges("*"); + return response; + } + public async Task GetItemChanges(string syncToken) + { using (var client = CreateWebClient()) { var body = InitializeRequestBody(); @@ -31,7 +34,8 @@ namespace Habitica.Todoist.Integration.Services body["resource_types"] = "[\"items\"]"; var json = await client.UploadStringTaskAsync($"{baseUrl}sync", RequestBodyToString(body)); - return JsonConvert.DeserializeObject(json); + var response = JsonConvert.DeserializeObject(json); + return response; } }