diff --git a/Habitica.Todoist.Integration.Console/App.config b/Habitica.Todoist.Integration.Console/App.config
index 7b7ea32..91a7e94 100644
--- a/Habitica.Todoist.Integration.Console/App.config
+++ b/Habitica.Todoist.Integration.Console/App.config
@@ -57,6 +57,10 @@
+
+
+
+
diff --git a/Habitica.Todoist.Integration.Console/Habitica.Todoist.Integration.Console.csproj b/Habitica.Todoist.Integration.Console/Habitica.Todoist.Integration.Console.csproj
index 7222040..8c6bf24 100644
--- a/Habitica.Todoist.Integration.Console/Habitica.Todoist.Integration.Console.csproj
+++ b/Habitica.Todoist.Integration.Console/Habitica.Todoist.Integration.Console.csproj
@@ -13,6 +13,8 @@
true
true
+
+
AnyCPU
@@ -34,6 +36,15 @@
4
+
+ ..\packages\Microsoft.Azure.Cosmos.Table.1.0.6\lib\netstandard2.0\Microsoft.Azure.Cosmos.Table.dll
+
+
+ ..\packages\Microsoft.Azure.DocumentDB.Core.2.1.3\lib\netstandard1.6\Microsoft.Azure.DocumentDB.Core.dll
+
+
+ ..\packages\Microsoft.Azure.KeyVault.Core.1.0.0\lib\net40\Microsoft.Azure.KeyVault.Core.dll
+
..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
@@ -61,24 +72,121 @@
..\packages\Microsoft.Extensions.Primitives.3.1.2\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll
+
+ ..\packages\Microsoft.OData.Core.7.5.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Core.dll
+
+
+ ..\packages\Microsoft.OData.Edm.7.5.0\lib\portable-net45+win8+wpa81\Microsoft.OData.Edm.dll
+
+
+ ..\packages\Microsoft.Spatial.7.5.0\lib\portable-net45+win8+wpa81\Microsoft.Spatial.dll
+
..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.dll
..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.Extensions.dll
+
+ ..\packages\Microsoft.Win32.Primitives.4.0.1\lib\net46\Microsoft.Win32.Primitives.dll
+ True
+ True
+
+
+ ..\packages\WindowsAzure.Storage.9.3.3\lib\net45\Microsoft.WindowsAzure.Storage.dll
+
..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
+
+ ..\packages\System.AppContext.4.1.0\lib\net463\System.AppContext.dll
+ True
+ True
+
..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll
+
+ ..\packages\System.Collections.NonGeneric.4.0.1\lib\net46\System.Collections.NonGeneric.dll
+ True
+ True
+
+
+ ..\packages\System.Collections.Specialized.4.0.1\lib\net46\System.Collections.Specialized.dll
+ True
+ True
+
+
+
+ ..\packages\System.Console.4.0.0\lib\net46\System.Console.dll
+ True
+ True
+
+
+ ..\packages\System.Diagnostics.DiagnosticSource.4.0.0\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+ ..\packages\System.Diagnostics.TraceSource.4.0.0\lib\net46\System.Diagnostics.TraceSource.dll
+ True
+ True
+
+
+ ..\packages\System.Diagnostics.Tracing.4.1.0\lib\net462\System.Diagnostics.Tracing.dll
+ True
+ True
+
+
+ ..\packages\System.Globalization.Calendars.4.0.1\lib\net46\System.Globalization.Calendars.dll
+ True
+ True
+
+
+ ..\packages\System.IO.4.3.0\lib\net462\System.IO.dll
+ True
+ True
+
+
+ ..\packages\System.IO.Compression.4.1.0\lib\net46\System.IO.Compression.dll
+ True
+ True
+
+
+
+ ..\packages\System.IO.Compression.ZipFile.4.0.1\lib\net46\System.IO.Compression.ZipFile.dll
+ True
+ True
+
+
+ ..\packages\System.IO.FileSystem.4.0.1\lib\net46\System.IO.FileSystem.dll
+ True
+ True
+
+
+ ..\packages\System.IO.FileSystem.Primitives.4.0.1\lib\net46\System.IO.FileSystem.Primitives.dll
+ True
+ True
+
+
+ ..\packages\System.Linq.4.1.0\lib\net463\System.Linq.dll
+ True
+ True
+
+
+ ..\packages\System.Linq.Expressions.4.1.0\lib\net463\System.Linq.Expressions.dll
+ True
+ True
+
..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll
+
+ ..\packages\System.Net.Http.4.1.0\lib\net46\System.Net.Http.dll
+ True
+ True
+
..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Extensions.dll
@@ -86,19 +194,100 @@
..\packages\Microsoft.Net.Http.2.2.22\lib\net45\System.Net.Http.Primitives.dll
+
+ ..\packages\System.Net.NameResolution.4.0.0\lib\net46\System.Net.NameResolution.dll
+ True
+ True
+
+
+ ..\packages\System.Net.NetworkInformation.4.1.0\lib\net46\System.Net.NetworkInformation.dll
+ True
+ True
+
+
+ ..\packages\System.Net.Security.4.3.2\lib\net46\System.Net.Security.dll
+ True
+ True
+
+
+ ..\packages\System.Net.Sockets.4.1.0\lib\net46\System.Net.Sockets.dll
+ True
+ True
+
..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+ ..\packages\System.Reflection.4.1.0\lib\net462\System.Reflection.dll
+ True
+ True
+
+
+ ..\packages\System.Runtime.4.3.0\lib\net462\System.Runtime.dll
+ True
+ True
+
..\packages\System.Runtime.CompilerServices.Unsafe.4.7.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
+
+ ..\packages\System.Runtime.Extensions.4.1.0\lib\net462\System.Runtime.Extensions.dll
+ True
+ True
+
+
+ ..\packages\System.Runtime.InteropServices.4.1.0\lib\net462\System.Runtime.InteropServices.dll
+ True
+ True
+
+
+ ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.0.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
+ True
+ True
+
+
+
+ ..\packages\System.Runtime.Serialization.Primitives.4.1.1\lib\net46\System.Runtime.Serialization.Primitives.dll
+ True
+ True
+
+
+ ..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net463\System.Security.Cryptography.Algorithms.dll
+ True
+ True
+
+
+ ..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll
+ True
+ True
+
+
+ ..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll
+ True
+ True
+
+
+ ..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll
+ True
+ True
+
+
+ ..\packages\System.Security.SecureString.4.0.0\lib\net46\System.Security.SecureString.dll
+ True
+ True
+
..\packages\System.Text.Encodings.Web.4.7.0\lib\netstandard2.0\System.Text.Encodings.Web.dll
..\packages\System.Text.Json.4.7.1\lib\net461\System.Text.Json.dll
+
+ ..\packages\System.Text.RegularExpressions.4.1.0\lib\net463\System.Text.RegularExpressions.dll
+ True
+ True
+
..\packages\System.Threading.Tasks.Extensions.4.5.2\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
@@ -110,7 +299,6 @@
-
@@ -140,4 +328,11 @@
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
\ No newline at end of file
diff --git a/Habitica.Todoist.Integration.Console/Program.cs b/Habitica.Todoist.Integration.Console/Program.cs
index 3c246fe..c9527c8 100644
--- a/Habitica.Todoist.Integration.Console/Program.cs
+++ b/Habitica.Todoist.Integration.Console/Program.cs
@@ -1,4 +1,6 @@
using Habitica.Todoist.Integration.Model.Habitica;
+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.Extensions.Configuration;
@@ -20,30 +22,79 @@ namespace Habitica.Todoist.Integration.Console
private static string habiticaApiUrl => "https://habitica.com/api/v3/";
private static string habiticaUserId => configuration["habitica:userId"];
private static string habiticaApiKey => configuration["habitica:apiKey"];
-
private static string todoistApiUrl => "https://api.todoist.com/sync/v8/";
private static string todoistApiKey => configuration["todoist:apiKey"];
+ private static string tableStorageConnectionString => configuration["tableStorage:connectionString"];
+ private static string giosUserId => "0b6ec4eb-8878-4b9e-8585-7673764a6541";
static void Main(string[] args)
{
ConfigBuild();
- var todoistClient = new TodoistClientService(todoistApiKey);
- var syncResponse = todoistClient.GetUpdatedItems().ConfigureAwait(false).GetAwaiter().GetResult();
-
- foreach (var item in syncResponse.Items)
- {
- var newTask = new Task
- {
- Text = item.GetCleanContent(),
- Type = TaskType.Todo,
- Date = item.Due?.ToJavaScriptDateStr(),
- Priority = GetHabiticaDifficulty(item.GetDifficulty().GetValueOrDefault())
- };
+ //var habiticaClient2 = new HabiticaServiceClient(habiticaUserId, habiticaApiKey);
- var habiticaClient = new HabiticaClientService(habiticaUserId, habiticaApiKey);
- var task = habiticaClient.CreateUserTask(newTask).ConfigureAwait(false).GetAwaiter().GetResult();
+ //var tasks = habiticaClient2.ReadTasks().ConfigureAwait(false).GetAwaiter().GetResult().Data;
+ //foreach (var task in tasks)
+ // habiticaClient2.DeleteTask(task.Id).ConfigureAwait(false).GetAwaiter().GetResult();
+
+ //return;
+
+ // 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 { }
+
+ // get all changed items from todoist
+ var response = todoistClient.GetChangedItems(syncToken).ConfigureAwait(false).GetAwaiter().GetResult();
+ var changedItems = response.Items;
+
+ // filter out items by actions
+ var addItems = changedItems.Where(x => !tableStorageClient.Exists(giosUserId, x.Id)
+ .ConfigureAwait(false).GetAwaiter().GetResult() && x.Is_deleted == 0).ToList();
+ var updateItems = changedItems.Where(x => tableStorageClient.Exists(giosUserId, x.Id)
+ .ConfigureAwait(false).GetAwaiter().GetResult() && x.Is_deleted == 0 && x.Date_completed == null).ToList();
+ var completeItems = changedItems.Where(x => x.Is_deleted == 0 && x.Date_completed != null).ToList();
+ var deleteItems = changedItems.Where(x => tableStorageClient.Exists(giosUserId, x.Id)
+ .ConfigureAwait(false).GetAwaiter().GetResult() && x.Is_deleted == 1).ToList();
+
+ foreach (var addItem in addItems)
+ {
+ var task = habiticaClient.CreateTask(TaskFromTodoistItem(addItem)).ConfigureAwait(false).GetAwaiter().GetResult().Data;
+ var link = new TodoHabitLink(giosUserId, addItem.Id, task.Id);
+
+ tableStorageClient.InsertOrUpdate(link).ConfigureAwait(false).GetAwaiter().GetResult();
+ tableStorageClient.InsertOrUpdate(link.Reverse()).ConfigureAwait(false).GetAwaiter().GetResult();
}
+
+ foreach (var updateItem in updateItems)
+ {
+ var habiticaId = tableStorageClient.Query().Where(x => x.PartitionKey == giosUserId && x.RowKey == updateItem.Id)
+ .ToList().First().HabiticaId;
+ habiticaClient.UpdateTask(TaskFromTodoistItem(updateItem, habiticaId)).ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+
+ foreach (var completeItem in completeItems)
+ {
+ var habiticaId = tableStorageClient.Query().Where(x => x.PartitionKey == giosUserId && x.RowKey == completeItem.Id)
+ .ToList().First().HabiticaId;
+ habiticaClient.ScoreTask(habiticaId, ScoreAction.Up).ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+
+ foreach (var deleteItem in deleteItems)
+ {
+ var habiticaId = tableStorageClient.Query().Where(x => x.PartitionKey == giosUserId && x.RowKey == deleteItem.Id)
+ .ToList().First().HabiticaId;
+ habiticaClient.DeleteTask(habiticaId).ConfigureAwait(false).GetAwaiter().GetResult();
+ }
+
+ // store sync token
+ var todoistSync = new TodoistSync(giosUserId, response.Sync_token);
+ tableStorageClient.InsertOrUpdate(todoistSync).ConfigureAwait(false).GetAwaiter().GetResult();
}
public static string GetHabiticaDifficulty(int todoistDifficulty)
@@ -62,6 +113,21 @@ namespace Habitica.Todoist.Integration.Console
return null;
}
+ public static Task TaskFromTodoistItem(Item item, string id = null)
+ {
+ var taskTypeStr = Enum.GetName(typeof(TaskType), TaskType.Todo).ToLower();
+ var task = new Task
+ {
+ Id = id,
+ Text = item.Content,
+ Type = taskTypeStr,
+ Date = item.Due?.ToJavaScriptDateStr(),
+ Priority = GetHabiticaDifficulty(item.Priority)
+ };
+
+ return task;
+ }
+
static void ConfigBuild()
{
new ConfigurationBuilder()
diff --git a/Habitica.Todoist.Integration.Console/packages.config b/Habitica.Todoist.Integration.Console/packages.config
index ba66f62..727577d 100644
--- a/Habitica.Todoist.Integration.Console/packages.config
+++ b/Habitica.Todoist.Integration.Console/packages.config
@@ -1,5 +1,8 @@
+
+
+
@@ -13,13 +16,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Habitica.Todoist.Integration.Model/Habitica.Todoist.Integration.Model.csproj b/Habitica.Todoist.Integration.Model/Habitica.Todoist.Integration.Model.csproj
index 6e86919..a0a2fa5 100644
--- a/Habitica.Todoist.Integration.Model/Habitica.Todoist.Integration.Model.csproj
+++ b/Habitica.Todoist.Integration.Model/Habitica.Todoist.Integration.Model.csproj
@@ -5,6 +5,7 @@
+
diff --git a/Habitica.Todoist.Integration.Model/Habitica/Enums/ScoreAction.cs b/Habitica.Todoist.Integration.Model/Habitica/Enums/ScoreAction.cs
new file mode 100644
index 0000000..635efce
--- /dev/null
+++ b/Habitica.Todoist.Integration.Model/Habitica/Enums/ScoreAction.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Habitica.Todoist.Integration.Model.Habitica.Enums
+{
+ public enum ScoreAction
+ {
+ Up = 0,
+ Down = 1
+ }
+}
diff --git a/Habitica.Todoist.Integration.Model/Habitica/Enums/TaskType.cs b/Habitica.Todoist.Integration.Model/Habitica/Enums/TaskType.cs
new file mode 100644
index 0000000..8ec5f92
--- /dev/null
+++ b/Habitica.Todoist.Integration.Model/Habitica/Enums/TaskType.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Habitica.Todoist.Integration.Model.Habitica.Enums
+{
+ public enum TaskType
+ {
+ Habit = 0,
+ Daily = 1,
+ Todo = 2,
+ Reward = 3
+ }
+}
diff --git a/Habitica.Todoist.Integration.Model/Habitica/Responses/HabiticaResponse.cs b/Habitica.Todoist.Integration.Model/Habitica/Responses/HabiticaResponse.cs
new file mode 100644
index 0000000..878f9ca
--- /dev/null
+++ b/Habitica.Todoist.Integration.Model/Habitica/Responses/HabiticaResponse.cs
@@ -0,0 +1,17 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Habitica.Todoist.Integration.Model.Habitica.Responses
+{
+ public class HabiticaReponse
+ {
+ [JsonProperty("success")]
+ public bool Success { get; set; }
+ [JsonProperty("data")]
+ public T Data { get; set; }
+ [JsonProperty("notifications")]
+ public object Notifications { get; set; }
+ }
+}
diff --git a/Habitica.Todoist.Integration.Model/Habitica/TaskType.cs b/Habitica.Todoist.Integration.Model/Habitica/TaskType.cs
deleted file mode 100644
index 1968351..0000000
--- a/Habitica.Todoist.Integration.Model/Habitica/TaskType.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Habitica.Todoist.Integration.Model.Habitica
-{
- public static class TaskType
- {
- public static string Habit = "habit";
- public static string Daily = "daily";
- public static string Todo = "todo";
- public static string Reward = "reward";
- }
-}
diff --git a/Habitica.Todoist.Integration.Model/Storage/TodoAction.cs b/Habitica.Todoist.Integration.Model/Storage/Enums/TodoAction.cs
similarity index 76%
rename from Habitica.Todoist.Integration.Model/Storage/TodoAction.cs
rename to Habitica.Todoist.Integration.Model/Storage/Enums/TodoAction.cs
index 00fff30..a4ffe51 100644
--- a/Habitica.Todoist.Integration.Model/Storage/TodoAction.cs
+++ b/Habitica.Todoist.Integration.Model/Storage/Enums/TodoAction.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
-namespace Habitica.Todoist.Integration.Model.Storage
+namespace Habitica.Todoist.Integration.Model.Storage.Enum
{
public enum TodoAction
{
diff --git a/Habitica.Todoist.Integration.Model/Storage/TodoApp.cs b/Habitica.Todoist.Integration.Model/Storage/Enums/TodoApp.cs
similarity index 72%
rename from Habitica.Todoist.Integration.Model/Storage/TodoApp.cs
rename to Habitica.Todoist.Integration.Model/Storage/Enums/TodoApp.cs
index 0f81a11..c16dbe0 100644
--- a/Habitica.Todoist.Integration.Model/Storage/TodoApp.cs
+++ b/Habitica.Todoist.Integration.Model/Storage/Enums/TodoApp.cs
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;
-namespace Habitica.Todoist.Integration.Model.Storage
+namespace Habitica.Todoist.Integration.Model.Storage.Enum
{
public enum TodoApp
{
diff --git a/Habitica.Todoist.Integration.Model/Storage/HabitTodoLink.cs b/Habitica.Todoist.Integration.Model/Storage/HabitTodoLink.cs
index 0d6bb28..8ed54d2 100644
--- a/Habitica.Todoist.Integration.Model/Storage/HabitTodoLink.cs
+++ b/Habitica.Todoist.Integration.Model/Storage/HabitTodoLink.cs
@@ -1,12 +1,26 @@
-using System;
+using Microsoft.Azure.Cosmos.Table;
+using System;
using System.Collections.Generic;
using System.Text;
namespace Habitica.Todoist.Integration.Model.Storage
{
- public class HabitTodoLink
+ public class HabitTodoLink : TableEntity
{
- public string HabiticaId { get; set; }
+ public HabitTodoLink() { }
+
+ public HabitTodoLink(string userId, string habiticaId, string todoistId)
+ {
+ PartitionKey = userId;
+ RowKey = habiticaId;
+ TodoistId = todoistId;
+ }
+
public string TodoistId { get; set; }
+
+ public TodoHabitLink Reverse()
+ {
+ return new TodoHabitLink(PartitionKey, TodoistId, RowKey);
+ }
}
}
diff --git a/Habitica.Todoist.Integration.Model/Storage/TodoChange.cs b/Habitica.Todoist.Integration.Model/Storage/TodoChange.cs
index 7e670e4..a7569e1 100644
--- a/Habitica.Todoist.Integration.Model/Storage/TodoChange.cs
+++ b/Habitica.Todoist.Integration.Model/Storage/TodoChange.cs
@@ -1,12 +1,22 @@
-using System;
+using Habitica.Todoist.Integration.Model.Storage.Enum;
+using Microsoft.Azure.Cosmos.Table;
+using System;
using System.Collections.Generic;
using System.Text;
namespace Habitica.Todoist.Integration.Model.Storage
{
- public class TodoChange
+ /* TODO: Rework structure */
+ public class TodoChange : TableEntity
{
- public string Id { get; set; }
+ public TodoChange() { }
+
+ public TodoChange(string userId, string todoId)
+ {
+ PartitionKey = userId;
+ RowKey = todoId;
+ }
+
public TodoApp Application { get; set; }
public TodoAction Action { get; set; }
public bool Applied { get; set; }
diff --git a/Habitica.Todoist.Integration.Model/Storage/TodoHabitLink.cs b/Habitica.Todoist.Integration.Model/Storage/TodoHabitLink.cs
index 0394d52..3ac8ddb 100644
--- a/Habitica.Todoist.Integration.Model/Storage/TodoHabitLink.cs
+++ b/Habitica.Todoist.Integration.Model/Storage/TodoHabitLink.cs
@@ -1,12 +1,26 @@
-using System;
+using Microsoft.Azure.Cosmos.Table;
+using System;
using System.Collections.Generic;
using System.Text;
namespace Habitica.Todoist.Integration.Model.Storage
{
- public class TodoHabitLink
+ public class TodoHabitLink : TableEntity
{
- public string TodoistId { get; set; }
+ public TodoHabitLink() { }
+
+ public TodoHabitLink(string userId, string todoistId, string habiticaId)
+ {
+ PartitionKey = userId;
+ RowKey = todoistId;
+ HabiticaId = habiticaId;
+ }
+
public string HabiticaId { get; set; }
+
+ public HabitTodoLink Reverse()
+ {
+ return new HabitTodoLink(PartitionKey, HabiticaId, RowKey);
+ }
}
}
diff --git a/Habitica.Todoist.Integration.Model/Storage/TodoistSync.cs b/Habitica.Todoist.Integration.Model/Storage/TodoistSync.cs
index 4264baf..1f925a4 100644
--- a/Habitica.Todoist.Integration.Model/Storage/TodoistSync.cs
+++ b/Habitica.Todoist.Integration.Model/Storage/TodoistSync.cs
@@ -1,11 +1,18 @@
-using System;
+using Microsoft.Azure.Cosmos.Table;
+using System;
using System.Collections.Generic;
using System.Text;
namespace Habitica.Todoist.Integration.Model.Storage
{
- public class TodoistSync
+ public class TodoistSync : TableEntity
{
- public string SyncToken { get; set; }
+ public TodoistSync() { }
+
+ public TodoistSync(string userId, string syncToken)
+ {
+ PartitionKey = userId;
+ RowKey = syncToken;
+ }
}
}
diff --git a/Habitica.Todoist.Integration.Model/Todoist/Item.cs b/Habitica.Todoist.Integration.Model/Todoist/Item.cs
index 215c59d..bad23a4 100644
--- a/Habitica.Todoist.Integration.Model/Todoist/Item.cs
+++ b/Habitica.Todoist.Integration.Model/Todoist/Item.cs
@@ -6,27 +6,17 @@ namespace Habitica.Todoist.Integration.Model.Todoist
{
public class Item
{
+ [JsonProperty("id")]
+ public string Id { get; set; }
[JsonProperty("content")]
public string Content { get; set; }
- [JsonProperty("Id")]
- public string Id { get; set; }
[JsonProperty("due")]
public Due Due { get; set; }
+ [JsonProperty("priority")]
+ public int Priority { get; set; }
[JsonProperty("is_deleted")]
public int Is_deleted { get; set; }
[JsonProperty("date_completed")]
public string Date_completed { get; set; }
-
- public int? GetDifficulty()
- {
- try { return int.Parse(Content.Split('-').Last().Last().ToString()); } catch { }
- return null;
- }
-
- public string GetCleanContent()
- {
- try { return Content.Split('-').First(); } catch { }
- return null;
- }
}
}
diff --git a/Habitica.Todoist.Integration.Model/Todoist/SyncResponse.cs b/Habitica.Todoist.Integration.Model/Todoist/Responses/SyncResponse.cs
similarity index 78%
rename from Habitica.Todoist.Integration.Model/Todoist/SyncResponse.cs
rename to Habitica.Todoist.Integration.Model/Todoist/Responses/SyncResponse.cs
index ffcf01f..e5edd8b 100644
--- a/Habitica.Todoist.Integration.Model/Todoist/SyncResponse.cs
+++ b/Habitica.Todoist.Integration.Model/Todoist/Responses/SyncResponse.cs
@@ -3,7 +3,7 @@ using System;
using System.Collections.Generic;
using System.Text;
-namespace Habitica.Todoist.Integration.Model.Todoist
+namespace Habitica.Todoist.Integration.Model.Todoist.Responses
{
public class SyncResponse
{
@@ -11,7 +11,7 @@ namespace Habitica.Todoist.Integration.Model.Todoist
public string Sync_token { get; set; }
[JsonProperty("full_sync")]
public bool Full_sync { get; set; }
- [JsonProperty("itmes")]
+ [JsonProperty("items")]
public List- Items { get; set; }
}
}
diff --git a/Habitica.Todoist.Integration.Services/HabitTodoStorageClient.cs b/Habitica.Todoist.Integration.Services/HabitTodoStorageClient.cs
deleted file mode 100644
index cdb7ac4..0000000
--- a/Habitica.Todoist.Integration.Services/HabitTodoStorageClient.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using Habitica.Todoist.Integration.Model.Storage;
-using Microsoft.Azure.Cosmos.Table;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace Habitica.Todoist.Integration.Services
-{
- public class HabitTodoStorageClient
- {
- private CloudStorageAccount storageAccount { get; set; }
-
- public HabitTodoStorageClient(string connectionString)
- {
- this.storageAccount = CloudStorageAccount.Parse(connectionString);
- }
-
- //public TodoLink CreateTodoLink(TodoLink todoLink)
- //{
- // return null;
- //}
- }
-}
diff --git a/Habitica.Todoist.Integration.Services/HabiticaClientService.cs b/Habitica.Todoist.Integration.Services/HabiticaClientService.cs
deleted file mode 100644
index 823b80f..0000000
--- a/Habitica.Todoist.Integration.Services/HabiticaClientService.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using HabiticaTask = Habitica.Todoist.Integration.Model.Habitica.Task;
-using System;
-using System.Net;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-
-namespace Habitica.Todoist.Integration.Services
-{
- public class HabiticaClientService
- {
- private string userId { get; set; }
- private string apiKey { get; set; }
-
- private string baseUrl => "https://habitica.com/api/v3/";
-
- public HabiticaClientService(string userId, string apiKey)
- {
- this.userId = userId;
- this.apiKey = apiKey;
- }
-
- public async Task CreateUserTask(HabiticaTask task)
- {
- using (var client = CreateWebClient())
- {
- var request = JsonConvert.SerializeObject(task);
- var json = await client.UploadStringTaskAsync($"{baseUrl}/tasks/user", "POST", request);
-
- return JsonConvert.DeserializeObject(json);
- }
- }
-
- private WebClient CreateWebClient()
- {
- var client = new WebClient();
-
- client.Headers[HttpRequestHeader.ContentType] = "application/json";
- client.Headers["x-api-user"] = userId;
- client.Headers["x-api-key"] = apiKey;
- client.Headers["x-client"] = "dotnet-habitica-client";
-
- return client;
- }
- }
-}
diff --git a/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs b/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs
new file mode 100644
index 0000000..067becc
--- /dev/null
+++ b/Habitica.Todoist.Integration.Services/HabiticaServiceClient.cs
@@ -0,0 +1,85 @@
+using HabiticaTask = Habitica.Todoist.Integration.Model.Habitica.Task;
+using System.Net;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using System.Collections.Generic;
+using Habitica.Todoist.Integration.Model.Habitica.Responses;
+using Habitica.Todoist.Integration.Model.Habitica.Enums;
+using System;
+
+namespace Habitica.Todoist.Integration.Services
+{
+ public class HabiticaServiceClient
+ {
+ private string userId { get; set; }
+ private string apiKey { get; set; }
+
+ private string baseUrl => "https://habitica.com/api/v3/";
+
+ public HabiticaServiceClient(string userId, string apiKey)
+ {
+ this.userId = userId;
+ this.apiKey = apiKey;
+ }
+
+ public async Task> CreateTask(HabiticaTask task)
+ {
+ using (var client = CreateWebClient())
+ {
+ var request = JsonConvert.SerializeObject(task);
+ var json = await client.UploadStringTaskAsync($"{baseUrl}/tasks/user", "POST", request);
+
+ return JsonConvert.DeserializeObject>(json);
+ }
+ }
+
+ public async Task>> ReadTasks(TaskType taskType = TaskType.Todo)
+ {
+ var taskTypeStr = Enum.GetName(taskType.GetType(), taskType).ToLower();
+ using (var client = CreateWebClient())
+ {
+ var json = await client.DownloadStringTaskAsync($"{baseUrl}/tasks/user");
+ var response = JsonConvert.DeserializeObject>>(json);
+ response.Data.RemoveAll(x => x.Type != taskTypeStr);
+
+ return response;
+ }
+ }
+
+ public async Task UpdateTask(HabiticaTask task)
+ {
+ using (var client = CreateWebClient())
+ {
+ var request = JsonConvert.SerializeObject(task);
+ var json = await client.UploadStringTaskAsync($"{baseUrl}/tasks/{task.Id}", "PUT", request);
+
+ return JsonConvert.DeserializeObject(json);
+ }
+ }
+
+ public async Task DeleteTask(string taskId)
+ {
+ using (var client = CreateWebClient())
+ await client.UploadStringTaskAsync($"{baseUrl}/tasks/{taskId}", "DELETE", "");
+ }
+
+ public async Task ScoreTask(string taskId, ScoreAction action)
+ {
+ var actionStr = Enum.GetName(action.GetType(), action).ToLower();
+ using (var client = CreateWebClient())
+ await client.UploadStringTaskAsync($"{baseUrl}/tasks/{taskId}/score/{actionStr}", "POST", "");
+ }
+
+ private WebClient CreateWebClient()
+ {
+ var client = new WebClient();
+
+ client.Headers[HttpRequestHeader.ContentType] = "application/json";
+ client.Headers["x-api-user"] = userId;
+ client.Headers["x-api-key"] = apiKey;
+ client.Headers["x-client"] = "dotnet-habitica-client";
+
+ return client;
+ }
+ }
+}
diff --git a/Habitica.Todoist.Integration.Services/TableStorageClient.cs b/Habitica.Todoist.Integration.Services/TableStorageClient.cs
new file mode 100644
index 0000000..5a95c72
--- /dev/null
+++ b/Habitica.Todoist.Integration.Services/TableStorageClient.cs
@@ -0,0 +1,83 @@
+using Habitica.Todoist.Integration.Model.Storage;
+using Microsoft.Azure.Cosmos.Table;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Habitica.Todoist.Integration.Services
+{
+ public class TableStorageClient
+ {
+ private CloudStorageAccount storageAccount { get; set; }
+ private CloudTableClient tableClient { get; set; }
+
+ /* TODO: change this so it reads from classes available instead of hardcoding */
+ private static List tableNames = new List()
+ {
+ "habittodolink",
+ "todohabitlink",
+ "todochange",
+ "todoistsync"
+ };
+
+ private Dictionary tables = new Dictionary();
+
+ public TableStorageClient(string connectionString)
+ {
+ storageAccount = CloudStorageAccount.Parse(connectionString);
+ tableClient = storageAccount.CreateCloudTableClient(new TableClientConfiguration());
+
+ // initialize all tables to use
+ foreach (var tableName in tableNames)
+ {
+ var table = tableClient.GetTableReference(tableName);
+ table.CreateIfNotExists();
+ tables[tableName] = table;
+ }
+ }
+
+ public async Task InsertOrUpdate(T entity) where T : TableEntity, new()
+ {
+ var tableName = typeof(T).Name.ToLower();
+ var table = tables[tableName];
+
+ var operation = TableOperation.InsertOrReplace(entity); // TODO: InsertOrReplace vs InsertOrMerge
+ var result = await table.ExecuteAsync(operation);
+
+ return result.Result as T;
+ }
+
+ public async Task Exists(string partitionKey, string rowKey) where T : TableEntity, new()
+ {
+ var tableName = typeof(T).Name.ToLower();
+ var table = tables[tableName];
+
+ var operation = TableOperation.Retrieve(partitionKey, rowKey);
+ var result = await table.ExecuteAsync(operation);
+
+ return result.Result != null;
+ }
+
+
+ //public async Task
> Read(string partitionKey, string rowKey) where T : TableEntity
+ //{
+ // var tableName = typeof(T).Name.ToLower();
+ // var table = tables[tableName];
+
+ // var operation = TableOperation.Retrieve(partitionKey, rowKey);
+ // var result = await table.ExecuteAsync(operation);
+
+ // return result.Result != null;
+ //}
+
+ public TableQuery Query() where T : TableEntity, new()
+ {
+ var tableName = typeof(T).Name.ToLower();
+ var table = tables[tableName];
+
+ return table.CreateQuery();
+ }
+ }
+}
diff --git a/Habitica.Todoist.Integration.Services/TodoistClientService.cs b/Habitica.Todoist.Integration.Services/TodoistServiceClient.cs
similarity index 83%
rename from Habitica.Todoist.Integration.Services/TodoistClientService.cs
rename to Habitica.Todoist.Integration.Services/TodoistServiceClient.cs
index c886c10..96da07b 100644
--- a/Habitica.Todoist.Integration.Services/TodoistClientService.cs
+++ b/Habitica.Todoist.Integration.Services/TodoistServiceClient.cs
@@ -1,4 +1,5 @@
using Habitica.Todoist.Integration.Model.Todoist;
+using Habitica.Todoist.Integration.Model.Todoist.Responses;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -8,18 +9,21 @@ using System.Threading.Tasks;
namespace Habitica.Todoist.Integration.Services
{
- public class TodoistClientService
+ public class TodoistServiceClient
{
private string apiKey { get; set; }
private string baseUrl => "https://api.todoist.com/sync/v8/";
- public TodoistClientService(string apiKey)
+ public TodoistServiceClient(string apiKey)
{
this.apiKey = apiKey;
}
- public async Task GetUpdatedItems(string syncToken = "*")
+ public async Task GetChangedItems(string syncToken = null)
{
+ if (string.IsNullOrEmpty(syncToken))
+ syncToken = "*";
+
using (var client = CreateWebClient())
{
var body = InitializeRequestBody();