refactor logic into another habitica service and modified license
This commit is contained in:
@@ -37,6 +37,17 @@ namespace Habitica.Todoist.Integration.Data
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<T> RetrieveRecord<T>(string partitionKey, string rowKey) where T : TableEntity, new()
|
||||
{
|
||||
var tableName = typeof(T).Name.ToLower();
|
||||
var table = tables[tableName];
|
||||
|
||||
var operation = TableOperation.Retrieve<T>(partitionKey, rowKey);
|
||||
var result = await table.ExecuteAsync(operation);
|
||||
|
||||
return result.Result as T;
|
||||
}
|
||||
|
||||
public async Task<T> InsertOrUpdate<T>(T entity) where T : TableEntity, new()
|
||||
{
|
||||
var tableName = typeof(T).Name.ToLower();
|
||||
@@ -45,7 +56,7 @@ namespace Habitica.Todoist.Integration.Data
|
||||
var operation = TableOperation.InsertOrReplace(entity); // TODO: InsertOrReplace vs InsertOrMerge
|
||||
var result = await table.ExecuteAsync(operation);
|
||||
|
||||
return result.Result as T;
|
||||
return result.Result as T; // TODO: might not work
|
||||
}
|
||||
|
||||
public async Task<bool> ExistsAsync<T>(string partitionKey, string rowKey) where T : TableEntity, new()
|
||||
@@ -53,7 +64,7 @@ namespace Habitica.Todoist.Integration.Data
|
||||
var tableName = typeof(T).Name.ToLower();
|
||||
var table = tables[tableName];
|
||||
|
||||
var operation = TableOperation.Retrieve(partitionKey, rowKey);
|
||||
var operation = TableOperation.Retrieve<T>(partitionKey, rowKey);
|
||||
var result = await table.ExecuteAsync(operation);
|
||||
|
||||
return result.Result != null;
|
||||
|
||||
@@ -26,54 +26,26 @@ namespace Habitica.Todoist.Integration.Function.Sync
|
||||
[FunctionName("HttpSyncFunction")]
|
||||
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
|
||||
{
|
||||
// initialize all the clients
|
||||
var habiticaClient = new HabiticaServiceClient(HttpConfiguration.HabiticaUserId, HttpConfiguration.HabiticaApiKey);
|
||||
var todoistClient = new TodoistServiceClient(HttpConfiguration.TodoistApiKey);
|
||||
var storageClient = new TableStorageClient(HttpConfiguration.TableStorageConnectionString);
|
||||
|
||||
// initialize integration services
|
||||
var todoistIntegration = new TodoistIntegrationService(todoistClient, storageClient, HttpConfiguration.GiosUserId);
|
||||
var giosUserId = HttpConfiguration.GiosUserId;
|
||||
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 todoistIntegration.ReadItemChanges();
|
||||
var items = await todoistService.ReadItemChanges();
|
||||
|
||||
// perform actions
|
||||
foreach (var addedItem in items.WhereAdded())
|
||||
{
|
||||
var task = (await habiticaClient.CreateTask(TaskFromTodoistItem(addedItem))).Data;
|
||||
var link = new TodoHabitLink(giosUserId, addedItem.Id, task.Id);
|
||||
|
||||
await storageClient.InsertOrUpdate(link);
|
||||
await storageClient.InsertOrUpdate(link.Reverse());
|
||||
}
|
||||
|
||||
foreach (var updatedItem in items.WhereUpdated())
|
||||
{
|
||||
var habiticaId = storageClient.Query<TodoHabitLink>()
|
||||
.Where(x => x.PartitionKey == giosUserId && x.RowKey == updatedItem.Id)
|
||||
.ToList().First().HabiticaId;
|
||||
await habiticaClient.UpdateTask(TaskFromTodoistItem(updatedItem, habiticaId));
|
||||
}
|
||||
|
||||
foreach (var completedItem in items.WhereCompleted())
|
||||
{
|
||||
var habiticaId = storageClient.Query<TodoHabitLink>()
|
||||
.Where(x => x.PartitionKey == giosUserId && x.RowKey == completedItem.Id)
|
||||
.ToList().First().HabiticaId;
|
||||
await habiticaClient.ScoreTask(habiticaId, ScoreAction.Up);
|
||||
}
|
||||
|
||||
foreach (var deleteItem in items.WhereDeleted())
|
||||
{
|
||||
var habiticaId = storageClient.Query<TodoHabitLink>()
|
||||
.Where(x => x.PartitionKey == giosUserId && x.RowKey == deleteItem.Id)
|
||||
.ToList().First().HabiticaId;
|
||||
await habiticaClient.DeleteTask(habiticaId);
|
||||
}
|
||||
await habiticaService.AddTasks(items.WhereAdded());
|
||||
await habiticaService.UpdateTasks(items.WhereUpdated());
|
||||
await habiticaService.CompleteTasks(items.WhereCompleted());
|
||||
await habiticaService.DeleteTasks(items.WhereDeleted());
|
||||
|
||||
// commit read changes
|
||||
await todoistIntegration.CommitRead();
|
||||
await todoistService.CommitRead();
|
||||
|
||||
// return success
|
||||
return new OkResult();
|
||||
|
||||
@@ -23,54 +23,26 @@ namespace Habitica.Todoist.Integration.Function.Sync
|
||||
[FunctionName("ScheduledSyncFunction")]
|
||||
public static async Task Run([TimerTrigger("0 0 * * * *")]TimerInfo myTimer, ILogger log)
|
||||
{
|
||||
// initialize all the clients
|
||||
var habiticaClient = new HabiticaServiceClient(ScheduledConfiguration.HabiticaUserId, ScheduledConfiguration.HabiticaApiKey);
|
||||
var todoistClient = new TodoistServiceClient(ScheduledConfiguration.TodoistApiKey);
|
||||
var storageClient = new TableStorageClient(ScheduledConfiguration.TableStorageConnectionString);
|
||||
|
||||
// initialize integration services
|
||||
var todoistIntegration = new TodoistIntegrationService(todoistClient, storageClient, ScheduledConfiguration.GiosUserId);
|
||||
var giosUserId = ScheduledConfiguration.GiosUserId;
|
||||
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 todoistIntegration.ReadItemChanges();
|
||||
var items = await todoistService.ReadItemChanges();
|
||||
|
||||
// perform actions
|
||||
foreach (var addedItem in items.WhereAdded())
|
||||
{
|
||||
var task = (await habiticaClient.CreateTask(TaskFromTodoistItem(addedItem))).Data;
|
||||
var link = new TodoHabitLink(giosUserId, addedItem.Id, task.Id);
|
||||
|
||||
await storageClient.InsertOrUpdate(link);
|
||||
await storageClient.InsertOrUpdate(link.Reverse());
|
||||
}
|
||||
|
||||
foreach (var updatedItem in items.WhereUpdated())
|
||||
{
|
||||
var habiticaId = storageClient.Query<TodoHabitLink>()
|
||||
.Where(x => x.PartitionKey == giosUserId && x.RowKey == updatedItem.Id)
|
||||
.ToList().First().HabiticaId;
|
||||
await habiticaClient.UpdateTask(TaskFromTodoistItem(updatedItem, habiticaId));
|
||||
}
|
||||
|
||||
foreach (var completedItem in items.WhereCompleted())
|
||||
{
|
||||
var habiticaId = storageClient.Query<TodoHabitLink>()
|
||||
.Where(x => x.PartitionKey == giosUserId && x.RowKey == completedItem.Id)
|
||||
.ToList().First().HabiticaId;
|
||||
await habiticaClient.ScoreTask(habiticaId, ScoreAction.Up);
|
||||
}
|
||||
|
||||
foreach (var deleteItem in items.WhereDeleted())
|
||||
{
|
||||
var habiticaId = storageClient.Query<TodoHabitLink>()
|
||||
.Where(x => x.PartitionKey == giosUserId && x.RowKey == deleteItem.Id)
|
||||
.ToList().First().HabiticaId;
|
||||
await habiticaClient.DeleteTask(habiticaId);
|
||||
}
|
||||
await habiticaService.AddTasks(items.WhereAdded());
|
||||
await habiticaService.UpdateTasks(items.WhereUpdated());
|
||||
await habiticaService.CompleteTasks(items.WhereCompleted());
|
||||
await habiticaService.DeleteTasks(items.WhereDeleted());
|
||||
|
||||
// commit read changes
|
||||
await todoistIntegration.CommitRead();
|
||||
await todoistService.CommitRead();
|
||||
}
|
||||
|
||||
private static string GetHabiticaDifficulty(int todoistDifficulty)
|
||||
|
||||
43
Habitica.Todoist.Integration.Services/Extensions.cs
Normal file
43
Habitica.Todoist.Integration.Services/Extensions.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using Habitica.Todoist.Integration.Model.Habitica;
|
||||
using Habitica.Todoist.Integration.Model.Habitica.Enums;
|
||||
using Habitica.Todoist.Integration.Model.Todoist;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Habitica.Todoist.Integration.Services.Extensions
|
||||
{
|
||||
public static class Extensions
|
||||
{
|
||||
public static Task ToHabiticaTask(this Item item, string habiticaId = null)
|
||||
{
|
||||
var taskTypeStr = Enum.GetName(typeof(TaskType), TaskType.Todo).ToLower();
|
||||
var task = new Task
|
||||
{
|
||||
Id = habiticaId,
|
||||
Text = item.Content,
|
||||
Type = taskTypeStr,
|
||||
Date = item.Due?.ToJavaScriptDateStr(),
|
||||
Priority = GetHabiticaDifficulty(item.Priority)
|
||||
};
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
private static string GetHabiticaDifficulty(int todoistPriority)
|
||||
{
|
||||
switch (todoistPriority)
|
||||
{
|
||||
case 1:
|
||||
return "0.1";
|
||||
case 2:
|
||||
return "1";
|
||||
case 3:
|
||||
return "1.5";
|
||||
case 4:
|
||||
return "2";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
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.Extensions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Habitica.Todoist.Integration.Services
|
||||
{
|
||||
public class HabiticaIntegrationService
|
||||
{
|
||||
private HabiticaServiceClient habiticaClient { get; set; }
|
||||
private TableStorageClient storageClient { get; set; }
|
||||
|
||||
private string userId { get; set; }
|
||||
|
||||
public HabiticaIntegrationService(string habiticaUserId,
|
||||
string habiticaApiKey,
|
||||
string storageConnectionString,
|
||||
string userId)
|
||||
{
|
||||
this.habiticaClient = new HabiticaServiceClient(habiticaUserId, habiticaApiKey);
|
||||
this.storageClient = new TableStorageClient(storageConnectionString);
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public async Task AddTasks(IEnumerable<Item> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
await AddTask(item);
|
||||
}
|
||||
|
||||
public async Task AddTask(Item item)
|
||||
{
|
||||
var task = (await habiticaClient.CreateTask(item.ToHabiticaTask())).Data;
|
||||
var link = new TodoHabitLink(userId, item.Id, task.Id);
|
||||
|
||||
await storageClient.InsertOrUpdate(link);
|
||||
await storageClient.InsertOrUpdate(link.Reverse());
|
||||
}
|
||||
|
||||
public async Task UpdateTasks(IEnumerable<Item> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
await UpdateTask(item);
|
||||
}
|
||||
|
||||
public async Task UpdateTask(Item item)
|
||||
{
|
||||
var habiticaId = (await storageClient.RetrieveRecord<TodoHabitLink>(userId, item.Id)).HabiticaId;
|
||||
await habiticaClient.UpdateTask(item.ToHabiticaTask(habiticaId));
|
||||
}
|
||||
|
||||
public async Task CompleteTasks(IEnumerable<Item> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
await CompleteTask(item);
|
||||
}
|
||||
|
||||
public async Task CompleteTask(Item item)
|
||||
{
|
||||
await CompleteTask(item.Id);
|
||||
}
|
||||
|
||||
public async Task CompleteTask(string todoistId)
|
||||
{
|
||||
var habiticaId = (await storageClient.RetrieveRecord<TodoHabitLink>(userId, todoistId)).HabiticaId;
|
||||
await habiticaClient.ScoreTask(habiticaId, ScoreAction.Up);
|
||||
}
|
||||
|
||||
public async Task DeleteTasks(IEnumerable<Item> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
await DeleteTask(item);
|
||||
}
|
||||
|
||||
public async Task DeleteTask(Item item)
|
||||
{
|
||||
await DeleteTask(item.Id);
|
||||
}
|
||||
|
||||
public async Task DeleteTask(string todoistId)
|
||||
{
|
||||
var habiticaId = (await storageClient.RetrieveRecord<TodoHabitLink>(userId, todoistId)).HabiticaId;
|
||||
await habiticaClient.DeleteTask(habiticaId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,12 @@ namespace Habitica.Todoist.Integration.Services
|
||||
private string userId { get; set; }
|
||||
private string latestSyncToken { get; set; } = string.Empty;
|
||||
|
||||
public TodoistIntegrationService(TodoistServiceClient todoistClient,
|
||||
TableStorageClient storageClient,
|
||||
public TodoistIntegrationService(string todoistApiKey,
|
||||
string storageConnectionString,
|
||||
string userId)
|
||||
{
|
||||
this.todoistClient = todoistClient;
|
||||
this.storageClient = storageClient;
|
||||
this.todoistClient = new TodoistServiceClient(todoistApiKey);
|
||||
this.storageClient = new TableStorageClient(storageConnectionString);
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
|
||||
23
LICENSE.txt
23
LICENSE.txt
@@ -1,22 +1,9 @@
|
||||
Microsoft Public License (Ms-PL)
|
||||
Copyright (c) 2020 Giovani Rodriguez
|
||||
|
||||
This license governs use of the accompanying software. If you use the software, you
|
||||
accept this license. If you do not accept the license, do not use the software.
|
||||
Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own.
|
||||
|
||||
1. Definitions
|
||||
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
|
||||
same meaning here as under U.S. copyright law.
|
||||
A "contribution" is the original software, or any additions or changes to the software.
|
||||
A "contributor" is any person that distributes its contribution under this license.
|
||||
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
|
||||
The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from the author.
|
||||
|
||||
2. Grant of Rights
|
||||
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
|
||||
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
|
||||
Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project, as well as provide a link to the original project.
|
||||
|
||||
3. Conditions and Limitations
|
||||
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
|
||||
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
|
||||
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
|
||||
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
|
||||
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
|
||||
Reference in New Issue
Block a user