/yaTDL/yaTDL.Core/Toodledo/ToodledoClientV2.cs
C# | 562 lines | 413 code | 140 blank | 9 comment | 67 complexity | 3d0f1a4b257b4d4a3ce607e414bc62bd MD5 | raw file
- //Copyright (c) 2010, Andreas Grünwald
- //All rights reserved.
-
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Globalization;
- using System.Linq;
- using System.Net;
- using System.Reflection;
- using System.Text;
- using System.Web;
- using System.Xml.Linq;
- using Newtonsoft.Json;
- using Newtonsoft.Json.Linq;
- using Slf;
- using yaTDL.Extensions;
- using System.Windows;
- using System.Diagnostics;
- using System.IO;
- using System.Security;
-
- namespace yaTDL.Core.Toodledo
- {
-
- //for Toodledeo API Documentation see http://api.toodledo.com/2/index.php
- public class ToodledoClientV2
- {
- static string toodledoBaseUrl = "http://api.toodledo.com/2/";
-
- static string appId = ""; //TODO: Insert AppId and AppToken
- static string appToken = "";
- static string appVersion = Assembly.GetExecutingAssembly().FullName.Split(',')[1].Substring(9).Replace(".", "");
- static string device = "Windows_Client";
- static string osVersion = Environment.OSVersion.Version.ToString().Replace(".", "");
-
-
- WebClient webClient = new WebClient();
-
- ILogger logger = LoggerService.GetLogger("ToodledoClient");
-
-
- public event EventHandler<ErrorEventArgsV2> ErrorOccurred;
-
- public DateTime FirstRequest { get; set; }
-
-
-
- public ToodledoClientV2()
- {
- FirstRequest = DateTime.Parse("01.01.0001");
- }
-
-
- public string GenerateSignature(string userId)
- {
- return (userId + appToken).GetMD5Hash();
- }
-
- public string GetSessionToken(string userId)
- {
- string url = String.Format("{0}account/token.php?userid={1};appid={2};vers={3};device={4};os={5};sig={6};f=xml",
- toodledoBaseUrl, userId, appId, appVersion, device, osVersion,GenerateSignature(userId));
-
-
- XElement response = makeRequest(url);
-
- if (response.Name == "token") return response.Value;
- else return null;
-
- }
-
- public ToodledoAPIKey GetKey(string sessionToken, SecureString password)
- {
- ToodledoAPIKey key = new ToodledoAPIKey();
- key.Key = (password.Unwrap().GetMD5Hash() + appToken + sessionToken).GetMD5Hash();
- key.Expires = DateTime.Now.AddHours(3.9);
-
- return key;
- }
-
- public ToodledoAccountInfoV2 GetAccountInfo(string key)
- {
- string url = toodledoBaseUrl + "account/get.php?key=" + key + ";f=xml";
-
- XElement response = makeRequest(url);
-
- if (response.Name == "account")
- {
- ToodledoAccountInfoV2 accountInfo = new ToodledoAccountInfoV2();
- accountInfo.UserId = response.Element("userid").Value;
- accountInfo.Alias = response.Element("alias").Value;
- if (response.Element("pro").Value == "1") accountInfo.IsProUser = true;
- accountInfo.DateFormat = Int32.Parse(response.Element("dateformat").Value);
- accountInfo.TimeZone = Int32.Parse(response.Element("timezone").Value);
- accountInfo.HideMonths = Int32.Parse(response.Element("hidemonths").Value);
- accountInfo.HotListPriority = Int32.Parse(response.Element("hotlistpriority").Value);
- accountInfo.HotListDueDate = Int32.Parse(response.Element("hotlistduedate").Value);
- accountInfo.ShowTabNums = Int32.Parse(response.Element("showtabnums").Value);
- accountInfo.LastFolderEdit = (double.Parse(response.Element("lastedit_folder").Value)).ToDateTime();
- accountInfo.LastContextEdit = (double.Parse(response.Element("lastedit_context").Value)).ToDateTime();
- accountInfo.LastGoalEdit = (double.Parse(response.Element("lastedit_goal").Value)).ToDateTime();
- accountInfo.LastTaskEdit = (double.Parse(response.Element("lastedit_task").Value)).ToDateTime();
- accountInfo.LastTaskDelete = (double.Parse(response.Element("lastdelete_task").Value)).ToDateTime();
-
- return accountInfo;
- }
- else
- { return null; }
- }
-
- public Collection<Project> GetFolders(string key)
- {
- Collection<Project> projects = new Collection<Project>();
-
- string url = toodledoBaseUrl + "/folders/get.php?key=" + key + ";f=xml";
-
- XElement xElement = makeRequest(url);
-
- foreach (XElement x in xElement.Elements("folder"))
- {
- Project p = new Project();
- p.Name = x.Element("name").Value;
- p.Id = x.Element("id").Value;
- p.Order = Int32.Parse(x.Element("order").Value);
- projects.Add(p);
- }
-
- return projects;
- }
-
- public bool AddFolder(string key, Project project)
- {
- string url = String.Format("{0}folders/add.php?name={1};key={2};f=xml", toodledoBaseUrl, project.Name, key);
-
- XElement xElement = makeRequest(url);
-
- if (xElement.Name == "folders")
- {
- project.Id = xElement.Element("folder").Element("id").Value;
- project.Order = Int32.Parse(xElement.Element("folder").Element("order").Value);
- return true;
- }
- else
- { return false; }
-
- }
-
- public bool UpdateFolder(string key, Project project)
- {
- string url = String.Format("{0}folders/edit.php?id={1};name={2};key={3};f=xml", toodledoBaseUrl, project.Id, project.Name, key);
-
- return makeRequest(url).Name == "folders" ? true : false;
- }
-
- public bool DeleteFolder(string key, int id)
- {
- string url = String.Format("{0}folders/delete.php?id={1};key={2};f=xml", toodledoBaseUrl, id, key);
-
- return makeRequest(url).Name == "deleted" ? true : false;
-
- }
-
- public Collection<Task> GetTasks(string key, List<Parameter> parameters)
- {
- string url = String.Format("{0}tasks/get.php?key={1};", toodledoBaseUrl, key);
-
-
- foreach (Parameter parameter in parameters)
- {
- url += parameter.Name + "=";
- switch (parameter.Name.ToLower())
- {
- case "id":
- case "start":
- case "num":
- url += parameter.Value.ToString();
- break;
-
- case "modbefore":
- case "modafter":
- url += ((DateTime)parameter.Value).ToUnixTime().ToString();
- break;
-
- case "comp":
- if (parameter.Value.GetType() == typeof(int))
- {
- url += ((int)parameter.Value).ToString();
- }
- if (parameter.Value.GetType() == typeof(bool))
- {
- if ((bool)parameter.Value) { url += "1"; }
- else { url += "0"; }
- }
- break;
-
- }
- url += ";";
- }
-
- url += "fields=folder,priority,duedate,repeat,repeatfrom,added;f=xml";
-
-
-
- Collection<Task> tasks = new Collection<Task>();
- XElement response = makeRequest(url);
-
- if (response.Name == "tasks")
- {
- foreach (XElement item in response.Elements("task"))
- {
- Task t = new Task();
- t.Id = item.Element("id").Value;
-
- t.Content = urlDecode(item.Element("title").Value);
- t.ProjectId = item.Element("folder").Value;
-
- if (String.IsNullOrEmpty(item.Element("modified").Value))
- {
- t.LastEdited = (double.Parse(item.Element("added").Value)).ToDateTime();
- }
- else
- {
- t.LastEdited = (double.Parse(item.Element("modified").Value)).ToDateTime();
- }
-
- if (String.IsNullOrEmpty(item.Element("duedate").Value) || item.Element("duedate").Value == "0")
- { t.DueDate = DateTime.Parse("01.01.0001"); }
- else
- {
- t.DueDate = (double.Parse(item.Element("duedate").Value)).ToDateTime().ToLocalTime();
- }
-
- if (String.IsNullOrEmpty(item.Element("completed").Value) || item.Element("completed").Value == "0")
- { t.Completed = false; }
- else
- { t.Completed = true; }
-
- t.Recurrence.AdvancedRepeat = item.Element("repeat").Value;
-
- t.Recurrence.Repeat = repeatFromToRepeat(Int32.Parse(item.Element("repeatfrom").Value), t.Recurrence.AdvancedRepeat);
-
-
- t.Priority = Int32.Parse(item.Element("priority").Value);
-
- tasks.Add(t);
- }
- }
-
- return tasks;
- }
-
-
- public bool AddTasks(string key, List<Task> tasks)
- {
- if (tasks.Count > 20)
- {
- List<List<Task>> taskLists = splitTaskList(20, tasks);
-
- List<bool> results = new List<bool>();
-
- foreach (List<Task> taskList in taskLists)
- {
- results.Add(AddTasks(key, taskList));
- }
-
- return results.Any(x=> x== false) ? false : true;
- }
-
- string serializedTasks = jsonSerialize(tasks, includeId:false, addIdAsMeta:true);
-
-
- if (!String.IsNullOrEmpty(serializedTasks))
- {
-
- string url = String.Format("{0}tasks/add.php?key={1};tasks={2};fields=folder,priority,duedate,repeat,meta;f=xml",
- toodledoBaseUrl, key, serializedTasks);
-
-
- XElement response = makeRequest(url);
-
- if (response.Name == "tasks")
- {
- foreach (XElement element in response.Elements("task"))
- {
- var matchingTasks = from task in tasks
- where task.Id == XElement.Parse(element.Element("meta").Value).Element("localId_original").Value
- select task;
-
- //var matchingTasks = from task in tasks
- // where task.Content == element.Element("title").Value
- // && task.ProjectId == element.Element("folder").Value
- // && task.Recurrence.AdvancedRepeat == element.Element("repeat").Value
- // && task.Recurrence.Repeat == repeatFromToRepeat(Int32.Parse(element.Element("repeatfrom").Value), element.Element("repeat").Value)
- // select task;
-
- if (matchingTasks.Any())
- {
- if (matchingTasks.Count() > 1)
- {
- Core.UI.Dialogs.ShowMessageBox("AddTasks: Found more than one matching Task. This should not have happend");
- logger.Error("AddTasks - Found more than one matching Task");
- return false;
- }
- matchingTasks.First().Id = element.Element("id").Value;
- }
- else
- {
- logger.Error("AddTasks: response did not contain a matching Task");
- return false;
- }
-
- }
- return true;
- }
- }
-
- return false;
- }
-
- public bool UpdateTasks(string key, List<Task> tasks)
- {
-
- if (tasks.Count > 25)
- {
- List<List<Task>> taskLists = splitTaskList(25, tasks);
-
- List<bool> results = new List<bool>();
-
- foreach (List<Task> taskList in taskLists)
- {
- results.Add(UpdateTasks(key, taskList));
- }
-
- var fails = from result in results
- where result == false
- select result;
-
- return fails.Any() ? false : true;
- }
-
- string url = String.Format("{0}tasks/edit.php?key={1};tasks={2};f=xml", toodledoBaseUrl, key, jsonSerialize(tasks, true));
-
- XElement response = makeRequest(url);
-
- if (response.Name == "tasks")
- return true;
- else
- return false;
-
- }
-
- public bool DeleteTasks(string key, List<int> ids)
- {
- string url = String.Format("{0}tasks/delete.php?key={1};tasks={2};f=xml", toodledoBaseUrl, key, JsonConvert.SerializeObject(ids.ToArray()).Replace("&", "%2C"));
-
- XElement response = makeRequest(url);
-
- return response.Name == "deleted" ? true : false;
- }
-
- public Collection<string> GetDeletedTasks(string key, DateTime after)
- {
- string url = String.Format("{0}tasks/deleted.php?key={1};after={2};f=xml", toodledoBaseUrl, key, after.ToUnixTime().ToString());
-
- XElement response = makeRequest(url);
-
- var _deleted = from task in response.Elements("task")
- select task.Element("id").Value;
-
- return new Collection<string>(_deleted.ToList<string>());
-
- }
-
-
-
- private void OnErrorOccurred(int errorCode, string errorMessage)
- {
- if (ErrorOccurred != null)
- {
- ErrorOccurred(this, new ErrorEventArgsV2() { ErrorCode = errorCode, ErrorMessage= errorMessage });
- }
- }
-
- int errorCounter = 1;
-
- private XElement makeRequest(string url)
- {
- if (FirstRequest == DateTime.Parse("01.01.0001")) { FirstRequest = DateTime.Now; }
-
- string responseString = webClient.DownloadString(url);
-
- XElement response = XElement.Parse(responseString);
-
- List<XElement> errors = response.DescendantsAndSelf("error").ToList<XElement>();
-
- foreach (XElement error in errors)
- {
- OnErrorOccurred(errorCode: Int32.Parse(error.Attribute("id").Value), errorMessage: error.Value);
- #if DEBUG
- if (error.Value.ToLower() == "no title")
- {
- logger.Error("url: {0}", url);
-
- File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "noTitleErrorUrl_" + errorCounter), url);
- errorCounter++;
- }
- #endif
- }
-
-
- return response;
- }
-
- private static List<List<Task>> splitTaskList(int maxLength, List<Task> longList)
- {
- List<List<Task>> result = new List<List<Task>>();
- List<Task> currentList = new List<Task>();
- while (longList.Count > maxLength)
- {
- if (currentList.Count < maxLength)
- {
- currentList.Add(longList.First());
- longList.RemoveAt(0);
- }
- else
- {
- result.Add(currentList);
- currentList = new List<Task>();
- }
- }
- result.Add(longList);
-
- return result;
- }
-
- [DebuggerStepThrough()]
- private static string jsonSerialize(List<Task> tasks, bool includeId, bool addIdAsMeta = false)
- {
- string result = "[";
-
- if (tasks.Count == 1)
- { result += jsonSerialize(tasks.First(), includeId,addIdAsMeta) + "]"; }
- else
- {
- foreach (Task t in tasks)
- {
- result += jsonSerialize(t, includeId, addIdAsMeta);
- if (t != tasks.Last())
- {
- result += "%2C";
- }
- }
-
- result += "]";
- }
-
- return result;
-
- }
-
- [DebuggerStepThrough()]
- private static string jsonSerialize(Task task, bool includeId, bool addIdAsMeta)
- {
- if (task == null) return "";
-
- if (String.IsNullOrEmpty(task.Content))
- {
- throw new Exception();
- }
-
- string baseString = "%2C\"{0}\"%3A\"{1}\"";
-
- string result = "{";
-
- if (includeId)
- {
- result += String.Format("\"id\"%3A\"{0}\"", task.Id);
- result += String.Format(baseString, "title", task.Content);
- }
- else
- {
- result += String.Format("\"title\"%3A\"{0}\"", task.Content);
- }
-
- result += String.Format(baseString, "priority", task.Priority);
- result += String.Format(baseString, "repeat", task.Recurrence.Repeat);
-
- if (task.ProjectId != "0")
- result += String.Format(baseString, "folder", task.ProjectId);
-
- if (task.DueDate.Date != DateTime.Parse("01.01.0001").Date)
- result += String.Format(baseString, "duedate", task.DueDate.ToUnixTime());
-
- if (task.Completed)
- result += String.Format(baseString, "completed", task.LastEdited.ToUnixTime());
- else
- result += String.Format(baseString, "completed", "0");
-
- if (addIdAsMeta)
- {
- XElement meta = new XElement("meta");
- meta.Add(new XElement("localId_original") { Value = task.Id });
- result += String.Format(baseString, "meta", meta.ToString().Replace("\r\n", ""));
- }
-
- result += "}";
-
- return result;
- }
-
-
- private static int repeatFromToRepeat(int repeatFrom, string advancedRepeat)
- {
- if (String.IsNullOrEmpty(advancedRepeat))
- {
- return 0;
- }
- else
- {
- return repeatFrom == 0 ? 50 : 150;
- }
- }
-
- private static bool isSameDueDate(DateTime localDueDate, double toodledoDueDate)
- {
- if (toodledoDueDate == 0 && localDueDate.Date == DateTime.Parse("01.01.0001"))
- return true;
- else
- return false;
- }
-
- private static string urlDecode(string content)
- {
- string result = HttpUtility.UrlDecode(content);
-
- result = result.Replace("ö", "ö");
- result = result.Replace("€", "€");
- result = result.Replace("ä", "ä");
- result = result.Replace("Ä", "Ä");
- result = result.Replace("ü", "ü");
- result = result.Replace("ß", "ß");
- result = result.Replace("Ö", "Ö");
- result = result.Replace("Ãœ", "Ü");
-
-
-
- return result;
- }
-
- }
-
-
- public class Parameter
- {
- public string Name { get; set; }
-
- public object Value { get; set; }
- }
-
-
- }