Fleshed out the table storage service and started syncing logic

This commit is contained in:
2020-03-19 19:09:03 -04:00
parent 59377a7749
commit 0bfab99f1b
22 changed files with 630 additions and 131 deletions

View File

@@ -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;
//}
}
}

View File

@@ -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<HabiticaTask> 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<HabiticaTask>(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;
}
}
}

View File

@@ -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<HabiticaReponse<HabiticaTask>> 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<HabiticaReponse<HabiticaTask>>(json);
}
}
public async Task<HabiticaReponse<List<HabiticaTask>>> 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<HabiticaReponse<List<HabiticaTask>>>(json);
response.Data.RemoveAll(x => x.Type != taskTypeStr);
return response;
}
}
public async Task<HabiticaTask> 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<HabiticaTask>(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;
}
}
}

View File

@@ -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<string> tableNames = new List<string>()
{
"habittodolink",
"todohabitlink",
"todochange",
"todoistsync"
};
private Dictionary<string, CloudTable> tables = new Dictionary<string, CloudTable>();
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<T> InsertOrUpdate<T>(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<bool> Exists<T>(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<List<T>> Read<T>(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<T> Query<T>() where T : TableEntity, new()
{
var tableName = typeof(T).Name.ToLower();
var table = tables[tableName];
return table.CreateQuery<T>();
}
}
}

View File

@@ -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<SyncResponse> GetUpdatedItems(string syncToken = "*")
public async Task<SyncResponse> GetChangedItems(string syncToken = null)
{
if (string.IsNullOrEmpty(syncToken))
syncToken = "*";
using (var client = CreateWebClient())
{
var body = InitializeRequestBody();