diff --git a/Habitica.Todoist.Integration.Function.Sync/Habitica.Todoist.Integration.Function.Sync.csproj b/Habitica.Todoist.Integration.Function.Sync/Habitica.Todoist.Integration.Function.Sync.csproj deleted file mode 100644 index d86f0b3..0000000 --- a/Habitica.Todoist.Integration.Function.Sync/Habitica.Todoist.Integration.Function.Sync.csproj +++ /dev/null @@ -1,23 +0,0 @@ - - - netcoreapp3.0 - v3 - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - Never - - - \ No newline at end of file diff --git a/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs b/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs deleted file mode 100644 index 312fe80..0000000 --- a/Habitica.Todoist.Integration.Function.Sync/HttpSyncFunction.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Habitica.Todoist.Integration.Data; -using Habitica.Todoist.Integration.Model.Habitica.Enums; -using Habitica.Todoist.Integration.Model.Storage; -using Habitica.Todoist.Integration.Model.Todoist; -using Habitica.Todoist.Integration.Services; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Host; -using Microsoft.Azure.WebJobs.Extensions.Http; -using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using HabiticaTask = Habitica.Todoist.Integration.Model.Habitica.Task; - -namespace Habitica.Todoist.Integration.Function.Sync -{ - public static class HttpSyncFunction - { - public static Configuration HttpConfiguration { get; set; } = new Configuration(); - - [Singleton("SyncLock", SingletonScope.Host)] - [FunctionName("HttpSyncFunction")] - public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) - { - // initialize integration services - var todoistService = new TodoistIntegrationService(HttpConfiguration.TodoistApiKey, - HttpConfiguration.TableStorageConnectionString, - HttpConfiguration.GiosUserId); - var habiticaService = new HabiticaIntegrationService(HttpConfiguration.HabiticaUserId, - HttpConfiguration.HabiticaApiKey, - HttpConfiguration.TableStorageConnectionString, - HttpConfiguration.GiosUserId); - - // get all changed items from todoist - var items = await todoistService.ReadItemChanges(); - - // perform actions - await habiticaService.Add(items.WhereAdded()); - await habiticaService.Update(items.WhereUpdated()); - await habiticaService.Complete(items.WhereCompleted()); - await habiticaService.Delete(items.WhereDeleted()); - - // commit read changes - await todoistService.CommitRead(); - - // return success - return new OkResult(); - } - } -} diff --git a/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs b/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs deleted file mode 100644 index 210a354..0000000 --- a/Habitica.Todoist.Integration.Function.Sync/ScheduledSyncFunction.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Habitica.Todoist.Integration.Data; -using Habitica.Todoist.Integration.Model.Habitica.Enums; -using Habitica.Todoist.Integration.Model.Storage; -using Habitica.Todoist.Integration.Model.Todoist; -using Habitica.Todoist.Integration.Services; -using Microsoft.Azure.WebJobs; -using Microsoft.Azure.WebJobs.Host; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.Logging; -using HabiticaTask = Habitica.Todoist.Integration.Model.Habitica.Task; - -namespace Habitica.Todoist.Integration.Function.Sync -{ - public static class ScheduledSyncFunction - { - public static Configuration ScheduledConfiguration { get; set; } = new Configuration(); - - [Singleton("SyncLock", SingletonScope.Host)] - [FunctionName("ScheduledSyncFunction")] - public static async Task Run([TimerTrigger("0 */30 * * * *")]TimerInfo myTimer, ILogger log) - { - // initialize integration services - var todoistService = new TodoistIntegrationService(ScheduledConfiguration.TodoistApiKey, - ScheduledConfiguration.TableStorageConnectionString, - ScheduledConfiguration.GiosUserId); - var habiticaService = new HabiticaIntegrationService(ScheduledConfiguration.HabiticaUserId, - ScheduledConfiguration.HabiticaApiKey, - ScheduledConfiguration.TableStorageConnectionString, - ScheduledConfiguration.GiosUserId); - - // get all changed items from todoist - var items = await todoistService.ReadItemChanges(); - - // perform actions - await habiticaService.Add(items.WhereAdded()); - await habiticaService.Update(items.WhereUpdated()); - await habiticaService.Complete(items.WhereCompleted()); - await habiticaService.Delete(items.WhereDeleted()); - - // commit read changes - await todoistService.CommitRead(); - } - } -} diff --git a/Habitica.Todoist.Integration.Function.Sync/host.json b/Habitica.Todoist.Integration.Function.Sync/host.json deleted file mode 100644 index b9f92c0..0000000 --- a/Habitica.Todoist.Integration.Function.Sync/host.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "version": "2.0" -} \ No newline at end of file diff --git a/Habittodo.Console/Habittodo.Console.csproj b/Habittodo.Console/Habittodo.Console.csproj index b0910e4..b6ed266 100644 --- a/Habittodo.Console/Habittodo.Console.csproj +++ b/Habittodo.Console/Habittodo.Console.csproj @@ -6,8 +6,6 @@ - - @@ -16,4 +14,10 @@ + + + Always + + + diff --git a/Habittodo.Console/Program.cs b/Habittodo.Console/Program.cs index 8b5eba0..5f8c5d0 100644 --- a/Habittodo.Console/Program.cs +++ b/Habittodo.Console/Program.cs @@ -1,9 +1,6 @@ -using Habittodo.Data; -using Habittodo.Model.Storage; -using Habittodo.Service; +using Habittodo.Service; using Microsoft.Extensions.Configuration; using System.IO; -using System.Linq; namespace Habitica.Todoist.Integration.Console { @@ -21,25 +18,26 @@ namespace Habitica.Todoist.Integration.Console { ConfigBuild(); - // initialize all the clients - var habiticaClient = new HabiticaServiceClient(habiticaUserId, habiticaApiKey); - var todoistClient = new TodoistServiceClient(todoistApiKey); - var tableStorageClient = new TableStorageClient(tableStorageConnectionString); - - // get todoist sync token if available - var syncToken = ""; - try { syncToken = tableStorageClient.Query().Where(x => x.PartitionKey == giosUserId).ToList() - .OrderByDescending(x => x.Timestamp).First().RowKey; } catch { } + // initialize integration services + var todoistService = new TodoistIntegrationService(todoistApiKey, + tableStorageConnectionString, + giosUserId); + var habiticaService = new HabiticaIntegrationService(habiticaUserId, + habiticaApiKey, + tableStorageConnectionString, + giosUserId); // get all changed items from todoist - var response = todoistClient.GetItemChanges(syncToken).ConfigureAwait(false).GetAwaiter().GetResult(); - var changedItems = response.Items; + var items = todoistService.ReadItemChanges().GetAwaiter().GetResult(); - /* TESTING */ - - // store sync token - var todoistSync = new TodoistSync(giosUserId, response.Sync_token); - tableStorageClient.InsertOrUpdate(todoistSync).ConfigureAwait(false).GetAwaiter().GetResult(); + // perform actions + habiticaService.Add(items.WhereAdded()).GetAwaiter().GetResult(); + habiticaService.Update(items.WhereUpdated()).GetAwaiter().GetResult(); + habiticaService.Complete(items.WhereCompleted()).GetAwaiter().GetResult(); + habiticaService.Delete(items.WhereDeleted()).GetAwaiter().GetResult(); + + // commit read changes + todoistService.CommitRead().GetAwaiter().GetResult(); } static void ConfigBuild() diff --git a/Habittodo.Console/secrets.json.sample b/Habittodo.Console/secrets.json.sample new file mode 100644 index 0000000..7f298e2 --- /dev/null +++ b/Habittodo.Console/secrets.json.sample @@ -0,0 +1,12 @@ +{ + "habitica": { + "userId": "4ef54610-742d-4503-ba88-faa5d820287c", + "apiKey": "d1446942-cc77-4aa7-aec9-adfda9f901b2" + }, + "todoist": { + "apiKey": "8ff2969e-84d0-4014-9d48-f96c2587fedf" + }, + "tableStorage": { + "connectionString": "your-azure-table-storage-connection-string-here" + } +} \ No newline at end of file diff --git a/Habitica.Todoist.Integration.Function.Sync/.gitignore b/Habittodo.FunctionApp/.gitignore similarity index 100% rename from Habitica.Todoist.Integration.Function.Sync/.gitignore rename to Habittodo.FunctionApp/.gitignore diff --git a/Habitica.Todoist.Integration.Function.Sync/Configuration.cs b/Habittodo.FunctionApp/Configuration.cs similarity index 78% rename from Habitica.Todoist.Integration.Function.Sync/Configuration.cs rename to Habittodo.FunctionApp/Configuration.cs index bdff26d..434270b 100644 --- a/Habitica.Todoist.Integration.Function.Sync/Configuration.cs +++ b/Habittodo.FunctionApp/Configuration.cs @@ -1,9 +1,6 @@ using Microsoft.Extensions.Configuration; -using System; -using System.Collections.Generic; -using System.Text; -namespace Habitica.Todoist.Integration.Function.Sync +namespace Habittodo.FunctionApp { public class Configuration { @@ -12,7 +9,7 @@ namespace Habitica.Todoist.Integration.Function.Sync public string HabiticaApiKey => configuration["habiticaApiKey"]; public string TodoistApiKey => configuration["todoistApiKey"]; public string TableStorageConnectionString => configuration["tableStorageConnectionString"]; - public string GiosUserId => "0b6ec4eb-8878-4b9e-8585-7673764a6541"; + public string UserId => "0b6ec4eb-8878-4b9e-8585-7673764a6541"; // Currently my userId (Gio) public Configuration() { diff --git a/Habittodo.FunctionApp/Habittodo.FunctionApp.csproj b/Habittodo.FunctionApp/Habittodo.FunctionApp.csproj new file mode 100644 index 0000000..a84e78f --- /dev/null +++ b/Habittodo.FunctionApp/Habittodo.FunctionApp.csproj @@ -0,0 +1,25 @@ + + + net5.0 + preview + V3 + Exe + <_FunctionsSkipCleanOutput>true + + + + + + + + + PreserveNewest + + + Always + + + + + + diff --git a/Habittodo.FunctionApp/Program.cs b/Habittodo.FunctionApp/Program.cs new file mode 100644 index 0000000..411edd4 --- /dev/null +++ b/Habittodo.FunctionApp/Program.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Configuration; +using System.IO; +using Microsoft.Extensions.Hosting; + +namespace Habittodo.FunctionApp +{ + public class Program + { + public static void Main() + { + var host = new HostBuilder() + .ConfigureFunctionsWorkerDefaults() + .Build(); + host.Run(); + } + } +} \ No newline at end of file diff --git a/Habittodo.FunctionApp/SyncFunction.cs b/Habittodo.FunctionApp/SyncFunction.cs new file mode 100644 index 0000000..2badcae --- /dev/null +++ b/Habittodo.FunctionApp/SyncFunction.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Worker; +using Habittodo.Service; + +namespace Habittodo.FunctionApp +{ + public static class SyncFunction + { + private static Configuration SyncConfiguration { get; } = new Configuration(); + + [Function("SyncFunction")] + public static async Task Run([TimerTrigger("0 */60 * * * *", RunOnStartup = true)] MyInfo t, FunctionContext c) + { + // initialize integration services + var todoistService = new TodoistIntegrationService(SyncConfiguration.TodoistApiKey, + SyncConfiguration.TableStorageConnectionString, + SyncConfiguration.UserId); + var habiticaService = new HabiticaIntegrationService(SyncConfiguration.HabiticaUserId, + SyncConfiguration.HabiticaApiKey, + SyncConfiguration.TableStorageConnectionString, + SyncConfiguration.UserId); + + // get all changed items from todoist + var items = await todoistService.ReadItemChanges(); + + // perform actions + await habiticaService.Add(items.WhereAdded()); + await habiticaService.Update(items.WhereUpdated()); + await habiticaService.Complete(items.WhereCompleted()); + await habiticaService.Delete(items.WhereDeleted()); + + // commit read changes + await todoistService.CommitRead(); + } + } + + public class MyInfo + { + public MyScheduleStatus ScheduleStatus { get; set; } + public bool IsPastDue { get; set; } + } + + public class MyScheduleStatus + { + public DateTime Last { get; set; } + public DateTime Next { get; set; } + public DateTime LastUpdated { get; set; } + } +} \ No newline at end of file diff --git a/Habittodo.FunctionApp/host.json b/Habittodo.FunctionApp/host.json new file mode 100644 index 0000000..beb2e40 --- /dev/null +++ b/Habittodo.FunctionApp/host.json @@ -0,0 +1,11 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + } + } + } +} \ No newline at end of file diff --git a/Habittodo.FunctionApp/local.settings.json.sample b/Habittodo.FunctionApp/local.settings.json.sample new file mode 100644 index 0000000..fc28441 --- /dev/null +++ b/Habittodo.FunctionApp/local.settings.json.sample @@ -0,0 +1,12 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "your-azure-storage-connection-string-here", + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", + "LocalConnection": "UseDevelopmentStorage=true", + "habiticaUserId": "4ef54610-742d-4503-ba88-faa5d820287c", + "habiticaApiKey": "d1446942-cc77-4aa7-aec9-adfda9f901b2", + "todoistApiKey": "8ff2969e-84d0-4014-9d48-f96c2587fedf", + "tableStorageConnectionString": "your-azure-table-storage-connection-string-here" + } +} \ No newline at end of file diff --git a/Habittodo.sln b/Habittodo.sln index 1af6df6..6322a2a 100644 --- a/Habittodo.sln +++ b/Habittodo.sln @@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Habittodo.Service", "Habitt EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Habittodo.Data", "Habittodo.Data\Habittodo.Data.csproj", "{8245731C-C053-49B2-AFAC-0A41C35F243C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Habittodo.FunctionApp", "Habittodo.FunctionApp\Habittodo.FunctionApp.csproj", "{652C5DA8-758F-44E2-963C-6E9FA3A9F798}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -33,6 +35,10 @@ Global {8245731C-C053-49B2-AFAC-0A41C35F243C}.Debug|Any CPU.Build.0 = Debug|Any CPU {8245731C-C053-49B2-AFAC-0A41C35F243C}.Release|Any CPU.ActiveCfg = Release|Any CPU {8245731C-C053-49B2-AFAC-0A41C35F243C}.Release|Any CPU.Build.0 = Release|Any CPU + {652C5DA8-758F-44E2-963C-6E9FA3A9F798}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {652C5DA8-758F-44E2-963C-6E9FA3A9F798}.Debug|Any CPU.Build.0 = Debug|Any CPU + {652C5DA8-758F-44E2-963C-6E9FA3A9F798}.Release|Any CPU.ActiveCfg = Release|Any CPU + {652C5DA8-758F-44E2-963C-6E9FA3A9F798}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE