├── LICENSE ├── MiniJson.cs ├── README.md ├── Trello.cs ├── TrelloCard.cs └── TrelloException.cs /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ben Follington 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MiniJson.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Calvin Rien 3 | * 4 | * Based on the JSON parser by Patrick van Bergen 5 | * http://techblog.procurios.nl/k/618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html 6 | * 7 | * Simplified it so that it doesn't throw exceptions 8 | * and can be used in Unity iPhone with maximum code stripping. 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining 11 | * a copy of this software and associated documentation files (the 12 | * "Software"), to deal in the Software without restriction, including 13 | * without limitation the rights to use, copy, modify, merge, publish, 14 | * distribute, sublicense, and/or sell copies of the Software, and to 15 | * permit persons to whom the Software is furnished to do so, subject to 16 | * the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be 19 | * included in all copies or substantial portions of the Software. 20 | * 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 25 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | */ 29 | using System; 30 | using System.Collections; 31 | using System.Collections.Generic; 32 | using System.IO; 33 | using System.Text; 34 | 35 | namespace MiniJSON { 36 | // Example usage: 37 | // 38 | // using UnityEngine; 39 | // using System.Collections; 40 | // using System.Collections.Generic; 41 | // using MiniJSON; 42 | // 43 | // public class MiniJSONTest : MonoBehaviour { 44 | // void Start () { 45 | // var jsonString = "{ \"array\": [1.44,2,3], " + 46 | // "\"object\": {\"key1\":\"value1\", \"key2\":256}, " + 47 | // "\"string\": \"The quick brown fox \\\"jumps\\\" over the lazy dog \", " + 48 | // "\"unicode\": \"\\u3041 Men\u00fa sesi\u00f3n\", " + 49 | // "\"int\": 65536, " + 50 | // "\"float\": 3.1415926, " + 51 | // "\"bool\": true, " + 52 | // "\"null\": null }"; 53 | // 54 | // var dict = Json.Deserialize(jsonString) as Dictionary; 55 | // 56 | // Debug.Log("deserialized: " + dict.GetType()); 57 | // Debug.Log("dict['array'][0]: " + ((List) dict["array"])[0]); 58 | // Debug.Log("dict['string']: " + (string) dict["string"]); 59 | // Debug.Log("dict['float']: " + (double) dict["float"]); // floats come out as doubles 60 | // Debug.Log("dict['int']: " + (long) dict["int"]); // ints come out as longs 61 | // Debug.Log("dict['unicode']: " + (string) dict["unicode"]); 62 | // 63 | // var str = Json.Serialize(dict); 64 | // 65 | // Debug.Log("serialized: " + str); 66 | // } 67 | // } 68 | 69 | /// 70 | /// This class encodes and decodes JSON strings. 71 | /// Spec. details, see http://www.json.org/ 72 | /// 73 | /// JSON uses Arrays and Objects. These correspond here to the datatypes IList and IDictionary. 74 | /// All numbers are parsed to doubles. 75 | /// 76 | public static class Json { 77 | /// 78 | /// Parses the string json into a value 79 | /// 80 | /// A JSON string. 81 | /// An List<object>, a Dictionary<string, object>, a double, an integer,a string, null, true, or false 82 | public static object Deserialize(string json) { 83 | // save the string for debug information 84 | if (json == null) { 85 | return null; 86 | } 87 | 88 | return Parser.Parse(json); 89 | } 90 | 91 | sealed class Parser : IDisposable { 92 | const string WORD_BREAK = "{}[],:\""; 93 | 94 | public static bool IsWordBreak(char c) { 95 | return Char.IsWhiteSpace(c) || WORD_BREAK.IndexOf(c) != -1; 96 | } 97 | 98 | enum TOKEN { 99 | NONE, 100 | CURLY_OPEN, 101 | CURLY_CLOSE, 102 | SQUARED_OPEN, 103 | SQUARED_CLOSE, 104 | COLON, 105 | COMMA, 106 | STRING, 107 | NUMBER, 108 | TRUE, 109 | FALSE, 110 | NULL 111 | }; 112 | 113 | StringReader json; 114 | 115 | Parser(string jsonString) { 116 | json = new StringReader(jsonString); 117 | } 118 | 119 | public static object Parse(string jsonString) { 120 | using (var instance = new Parser(jsonString)) { 121 | return instance.ParseValue(); 122 | } 123 | } 124 | 125 | public void Dispose() { 126 | json.Dispose(); 127 | json = null; 128 | } 129 | 130 | Dictionary ParseObject() { 131 | Dictionary table = new Dictionary(); 132 | 133 | // ditch opening brace 134 | json.Read(); 135 | 136 | // { 137 | while (true) { 138 | switch (NextToken) { 139 | case TOKEN.NONE: 140 | return null; 141 | case TOKEN.COMMA: 142 | continue; 143 | case TOKEN.CURLY_CLOSE: 144 | return table; 145 | default: 146 | // name 147 | string name = ParseString(); 148 | if (name == null) { 149 | return null; 150 | } 151 | 152 | // : 153 | if (NextToken != TOKEN.COLON) { 154 | return null; 155 | } 156 | // ditch the colon 157 | json.Read(); 158 | 159 | // value 160 | table[name] = ParseValue(); 161 | break; 162 | } 163 | } 164 | } 165 | 166 | List ParseArray() { 167 | List array = new List(); 168 | 169 | // ditch opening bracket 170 | json.Read(); 171 | 172 | // [ 173 | var parsing = true; 174 | while (parsing) { 175 | TOKEN nextToken = NextToken; 176 | 177 | switch (nextToken) { 178 | case TOKEN.NONE: 179 | return null; 180 | case TOKEN.COMMA: 181 | continue; 182 | case TOKEN.SQUARED_CLOSE: 183 | parsing = false; 184 | break; 185 | default: 186 | object value = ParseByToken(nextToken); 187 | 188 | array.Add(value); 189 | break; 190 | } 191 | } 192 | 193 | return array; 194 | } 195 | 196 | object ParseValue() { 197 | TOKEN nextToken = NextToken; 198 | return ParseByToken(nextToken); 199 | } 200 | 201 | object ParseByToken(TOKEN token) { 202 | switch (token) { 203 | case TOKEN.STRING: 204 | return ParseString(); 205 | case TOKEN.NUMBER: 206 | return ParseNumber(); 207 | case TOKEN.CURLY_OPEN: 208 | return ParseObject(); 209 | case TOKEN.SQUARED_OPEN: 210 | return ParseArray(); 211 | case TOKEN.TRUE: 212 | return true; 213 | case TOKEN.FALSE: 214 | return false; 215 | case TOKEN.NULL: 216 | return null; 217 | default: 218 | return null; 219 | } 220 | } 221 | 222 | string ParseString() { 223 | StringBuilder s = new StringBuilder(); 224 | char c; 225 | 226 | // ditch opening quote 227 | json.Read(); 228 | 229 | bool parsing = true; 230 | while (parsing) { 231 | 232 | if (json.Peek() == -1) { 233 | parsing = false; 234 | break; 235 | } 236 | 237 | c = NextChar; 238 | switch (c) { 239 | case '"': 240 | parsing = false; 241 | break; 242 | case '\\': 243 | if (json.Peek() == -1) { 244 | parsing = false; 245 | break; 246 | } 247 | 248 | c = NextChar; 249 | switch (c) { 250 | case '"': 251 | case '\\': 252 | case '/': 253 | s.Append(c); 254 | break; 255 | case 'b': 256 | s.Append('\b'); 257 | break; 258 | case 'f': 259 | s.Append('\f'); 260 | break; 261 | case 'n': 262 | s.Append('\n'); 263 | break; 264 | case 'r': 265 | s.Append('\r'); 266 | break; 267 | case 't': 268 | s.Append('\t'); 269 | break; 270 | case 'u': 271 | var hex = new char[4]; 272 | 273 | for (int i=0; i< 4; i++) { 274 | hex[i] = NextChar; 275 | } 276 | 277 | s.Append((char) Convert.ToInt32(new string(hex), 16)); 278 | break; 279 | } 280 | break; 281 | default: 282 | s.Append(c); 283 | break; 284 | } 285 | } 286 | 287 | return s.ToString(); 288 | } 289 | 290 | object ParseNumber() { 291 | string number = NextWord; 292 | 293 | if (number.IndexOf('.') == -1) { 294 | long parsedInt; 295 | Int64.TryParse(number, out parsedInt); 296 | return parsedInt; 297 | } 298 | 299 | double parsedDouble; 300 | Double.TryParse(number, out parsedDouble); 301 | return parsedDouble; 302 | } 303 | 304 | void EatWhitespace() { 305 | while (Char.IsWhiteSpace(PeekChar)) { 306 | json.Read(); 307 | 308 | if (json.Peek() == -1) { 309 | break; 310 | } 311 | } 312 | } 313 | 314 | char PeekChar { 315 | get { 316 | return Convert.ToChar(json.Peek()); 317 | } 318 | } 319 | 320 | char NextChar { 321 | get { 322 | return Convert.ToChar(json.Read()); 323 | } 324 | } 325 | 326 | string NextWord { 327 | get { 328 | StringBuilder word = new StringBuilder(); 329 | 330 | while (!IsWordBreak(PeekChar)) { 331 | word.Append(NextChar); 332 | 333 | if (json.Peek() == -1) { 334 | break; 335 | } 336 | } 337 | 338 | return word.ToString(); 339 | } 340 | } 341 | 342 | TOKEN NextToken { 343 | get { 344 | EatWhitespace(); 345 | 346 | if (json.Peek() == -1) { 347 | return TOKEN.NONE; 348 | } 349 | 350 | switch (PeekChar) { 351 | case '{': 352 | return TOKEN.CURLY_OPEN; 353 | case '}': 354 | json.Read(); 355 | return TOKEN.CURLY_CLOSE; 356 | case '[': 357 | return TOKEN.SQUARED_OPEN; 358 | case ']': 359 | json.Read(); 360 | return TOKEN.SQUARED_CLOSE; 361 | case ',': 362 | json.Read(); 363 | return TOKEN.COMMA; 364 | case '"': 365 | return TOKEN.STRING; 366 | case ':': 367 | return TOKEN.COLON; 368 | case '0': 369 | case '1': 370 | case '2': 371 | case '3': 372 | case '4': 373 | case '5': 374 | case '6': 375 | case '7': 376 | case '8': 377 | case '9': 378 | case '-': 379 | return TOKEN.NUMBER; 380 | } 381 | 382 | switch (NextWord) { 383 | case "false": 384 | return TOKEN.FALSE; 385 | case "true": 386 | return TOKEN.TRUE; 387 | case "null": 388 | return TOKEN.NULL; 389 | } 390 | 391 | return TOKEN.NONE; 392 | } 393 | } 394 | } 395 | 396 | /// 397 | /// Converts a IDictionary / IList object or a simple type (string, int, etc.) into a JSON string 398 | /// 399 | /// A Dictionary<string, object> / List<object> 400 | /// A JSON encoded string, or null if object 'json' is not serializable 401 | public static string Serialize(object obj) { 402 | return Serializer.Serialize(obj); 403 | } 404 | 405 | sealed class Serializer { 406 | StringBuilder builder; 407 | 408 | Serializer() { 409 | builder = new StringBuilder(); 410 | } 411 | 412 | public static string Serialize(object obj) { 413 | var instance = new Serializer(); 414 | 415 | instance.SerializeValue(obj); 416 | 417 | return instance.builder.ToString(); 418 | } 419 | 420 | void SerializeValue(object value) { 421 | IList asList; 422 | IDictionary asDict; 423 | string asStr; 424 | 425 | if (value == null) { 426 | builder.Append("null"); 427 | } else if ((asStr = value as string) != null) { 428 | SerializeString(asStr); 429 | } else if (value is bool) { 430 | builder.Append((bool) value ? "true" : "false"); 431 | } else if ((asList = value as IList) != null) { 432 | SerializeArray(asList); 433 | } else if ((asDict = value as IDictionary) != null) { 434 | SerializeObject(asDict); 435 | } else if (value is char) { 436 | SerializeString(new string((char) value, 1)); 437 | } else { 438 | SerializeOther(value); 439 | } 440 | } 441 | 442 | void SerializeObject(IDictionary obj) { 443 | bool first = true; 444 | 445 | builder.Append('{'); 446 | 447 | foreach (object e in obj.Keys) { 448 | if (!first) { 449 | builder.Append(','); 450 | } 451 | 452 | SerializeString(e.ToString()); 453 | builder.Append(':'); 454 | 455 | SerializeValue(obj[e]); 456 | 457 | first = false; 458 | } 459 | 460 | builder.Append('}'); 461 | } 462 | 463 | void SerializeArray(IList anArray) { 464 | builder.Append('['); 465 | 466 | bool first = true; 467 | 468 | foreach (object obj in anArray) { 469 | if (!first) { 470 | builder.Append(','); 471 | } 472 | 473 | SerializeValue(obj); 474 | 475 | first = false; 476 | } 477 | 478 | builder.Append(']'); 479 | } 480 | 481 | void SerializeString(string str) { 482 | builder.Append('\"'); 483 | 484 | char[] charArray = str.ToCharArray(); 485 | foreach (var c in charArray) { 486 | switch (c) { 487 | case '"': 488 | builder.Append("\\\""); 489 | break; 490 | case '\\': 491 | builder.Append("\\\\"); 492 | break; 493 | case '\b': 494 | builder.Append("\\b"); 495 | break; 496 | case '\f': 497 | builder.Append("\\f"); 498 | break; 499 | case '\n': 500 | builder.Append("\\n"); 501 | break; 502 | case '\r': 503 | builder.Append("\\r"); 504 | break; 505 | case '\t': 506 | builder.Append("\\t"); 507 | break; 508 | default: 509 | int codepoint = Convert.ToInt32(c); 510 | if ((codepoint >= 32) && (codepoint <= 126)) { 511 | builder.Append(c); 512 | } else { 513 | builder.Append("\\u"); 514 | builder.Append(codepoint.ToString("x4")); 515 | } 516 | break; 517 | } 518 | } 519 | 520 | builder.Append('\"'); 521 | } 522 | 523 | void SerializeOther(object value) { 524 | // NOTE: decimals lose precision during serialization. 525 | // They always have, I'm just letting you know. 526 | // Previously floats and doubles lost precision too. 527 | if (value is float) { 528 | builder.Append(((float) value).ToString("R")); 529 | } else if (value is int 530 | || value is uint 531 | || value is long 532 | || value is sbyte 533 | || value is byte 534 | || value is short 535 | || value is ushort 536 | || value is ulong) { 537 | builder.Append(value); 538 | } else if (value is double 539 | || value is decimal) { 540 | builder.Append(Convert.ToDouble(value).ToString("R")); 541 | } else { 542 | SerializeString(value.ToString()); 543 | } 544 | } 545 | } 546 | } 547 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Trello Cards For Unity 2 | ================== 3 | 4 | [![Twitter](https://img.shields.io/twitter/follow/vivavolt?label=%40vivavolt&style=flat&colorA=000000&colorB=000000&logo=twitter&logoColor=000000)](https://twitter.com/vivavolt) 5 | [![Donate (ETH)](https://img.shields.io/badge/Donate-(ETH)-f5f5f5?style=flat&colorA=000000&colorB=000000)](https://blockchain.com/eth/address/0x981e493b795A7a28c43Bf8d7a8E125C419435Fa7) 6 | [![Donate ($)](https://img.shields.io/badge/Donate-($)-f5f5f5?style=flat&colorA=000000&colorB=000000)](https://ko-fi.com/vivavolt) 7 | ![Language](https://img.shields.io/github/languages/top/bfollington/Trello-Cards-Unity?style=flat&colorA=000000&colorB=000000) 8 | ![License](https://img.shields.io/github/license/bfollington/Trello-Cards-Unity?style=flat&colorA=000000&colorB=000000) 9 | 10 | This is a simple C# system for creating Trello cards in your own boards from your Unity app or game. Some use cases may be crash reports, significant events etc. 11 | 12 | ## Installation 13 | 14 | Just drag these `.cs` files into your scripts folder, wherever you like. If you already have `MiniJson` in your project, you may get a namespace conflict. No matter, just delete the one from this repo. 15 | 16 | ## Usage 17 | 18 | Go ahead and grab a Trello Application Key from: https://trello.com/1/appKey/generate. Grab the application key, I'll refer to this as the `key` from now on. 19 | 20 | Now head to: https://trello.com/1/connect?key=[yourkeygoeshere]&name=Your%20App&response_type=token&scope=read,write&expiration=never 21 | 22 | In your browser (make sure to fill in your key from just before). You'll be taken to https://trello.com/1/token/approve, and the token code given will be your `token`. 23 | 24 | ## Example Code 25 | 26 | ```cs 27 | using UnityEngine; 28 | using System.Collections; 29 | using MiniJSON; 30 | using System.Collections.Generic; 31 | using Trello; 32 | 33 | public class RunAtStart : MonoBehaviour { 34 | 35 | // Use this for initialization 36 | IEnumerator Start () { 37 | 38 | var trello = new Trello.Trello(YOUR-KEY, YOUR-TOKEN); 39 | 40 | // Async, do not block 41 | yield return trello.populateBoards(); 42 | trello.setCurrentBoard("Your Game"); 43 | 44 | // Async, do not block 45 | yield return trello.populateLists(); 46 | trello.setCurrentList("Achievements"); 47 | 48 | var card = trello.newCard(); 49 | card.name = "Unity Test"; 50 | card.desc = "Description"; 51 | card.due = "11/12/2014"; 52 | 53 | yield return trello.uploadCard(card); 54 | 55 | // You can use the helper method to upload exceptions with relevant data 56 | try 57 | { 58 | throw new UnityException("Testing"); 59 | } catch (UnityException e) 60 | { 61 | trello.uploadExceptionCard(e); 62 | } 63 | 64 | } 65 | } 66 | ``` 67 | 68 | ## Errors 69 | 70 | If you see a `401 Unauthorized` message returnd, it likely means your `key` or `token` are invalid or have expired. Try generate new ones and trying again, if you're having trouble get in touch with me. 71 | -------------------------------------------------------------------------------- /Trello.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using MiniJSON; 5 | using System; 6 | 7 | namespace Trello 8 | { 9 | public class Trello { 10 | 11 | private string token; 12 | private string key; 13 | private List boards; 14 | private List lists; 15 | private const string memberBaseUrl = "https://api.trello.com/1/members/me"; 16 | private const string boardBaseUrl = "https://api.trello.com/1/boards/"; 17 | private const string cardBaseUrl = "https://api.trello.com/1/cards/"; 18 | private string currentBoardId = ""; 19 | private string currentListId = ""; 20 | 21 | public Trello(string key, string token) 22 | { 23 | this.key = key; 24 | this.token = token; 25 | } 26 | 27 | /// 28 | /// Checks if a WWW objects has resulted in an error, and if so throws an exception to deal with it. 29 | /// 30 | /// Error message. 31 | /// The request object. 32 | private void checkWwwStatus(string errorMessage, WWW www) 33 | { 34 | if (!string.IsNullOrEmpty(www.error)) 35 | { 36 | throw new TrelloException(errorMessage + ": " + www.error); 37 | } 38 | } 39 | 40 | /// 41 | /// Download the list of available boards for the user, these are cached and allow populateLists() to function. 42 | /// 43 | /// A parsed JSON list of boards. 44 | public List populateBoards() 45 | { 46 | boards = null; 47 | WWW www = new WWW(memberBaseUrl + "?" + "key=" + key + "&token=" + token + "&boards=all"); 48 | 49 | // Wait for request to return 50 | while (!www.isDone) 51 | { 52 | checkWwwStatus("Connection to the Trello servers was not possible", www); 53 | } 54 | 55 | var dict = Json.Deserialize(www.text) as Dictionary; 56 | 57 | Debug.Log (www.text); 58 | 59 | boards = (List)dict["boards"]; 60 | return boards; 61 | } 62 | 63 | /// 64 | /// Sets the current board to search for lists in. 65 | /// 66 | /// Name of the board we're after. 67 | public void setCurrentBoard(string name) 68 | { 69 | if (boards == null) 70 | { 71 | throw new TrelloException("You have not yet populated the list of boards, so one cannot be selected."); 72 | } 73 | 74 | for (int i = 0; i < boards.Count; i++) 75 | { 76 | var board = (Dictionary)boards[i]; 77 | if ( (string)board["name"] == name) 78 | { 79 | currentBoardId = (string)board["id"]; 80 | return; 81 | } 82 | } 83 | 84 | currentBoardId = ""; 85 | throw new TrelloException("No such board found."); 86 | } 87 | 88 | /// 89 | /// Populate the lists for the current board, these are cached for easy card uploading later. 90 | /// 91 | /// A parsed JSON list of lists. 92 | public List populateLists() 93 | { 94 | lists = null; 95 | 96 | if (currentBoardId == "") 97 | { 98 | throw new TrelloException("Cannot retreive the lists, you have not selected a board yet."); 99 | } 100 | 101 | WWW www = new WWW(boardBaseUrl + currentBoardId + "?" + "key=" + key + "&token=" + token + "&lists=all"); 102 | 103 | 104 | // Wait for request to return 105 | while (!www.isDone) 106 | { 107 | checkWwwStatus("Connection to the Trello servers was not possible", www); 108 | } 109 | 110 | var dict = Json.Deserialize(www.text) as Dictionary; 111 | 112 | Debug.Log (www.text); 113 | 114 | lists = (List)dict["lists"]; 115 | return lists; 116 | } 117 | 118 | /// 119 | /// Updates the current list to upload cards to. 120 | /// 121 | /// Name of the list. 122 | public void setCurrentList(string name) 123 | { 124 | if (lists == null) 125 | { 126 | throw new TrelloException("You have not yet populated the list of lists, so one cannot be selected."); 127 | } 128 | 129 | for (int i = 0; i < lists.Count; i++) 130 | { 131 | var list = (Dictionary)lists[i]; 132 | if ( (string)list["name"] == name) 133 | { 134 | currentListId = (string)list["id"]; 135 | Debug.Log (currentListId); 136 | return; 137 | } 138 | } 139 | 140 | currentListId = ""; 141 | throw new TrelloException("No such list found."); 142 | } 143 | 144 | /// 145 | /// Retrieve a new Trello card objects, with the correct list id populated already. 146 | /// 147 | /// The card object. 148 | public TrelloCard newCard() 149 | { 150 | if (currentListId == "") 151 | { 152 | throw new TrelloException("Cannot create a card when you have not set selected a list."); 153 | } 154 | 155 | var card = new TrelloCard(); 156 | card.idList = currentListId; 157 | return card; 158 | } 159 | 160 | /// 161 | /// Given an exception object, a TrelloCard is created and populated with the relevant information from the exception. This is then uploaded to the Trello server. 162 | /// 163 | /// The exception card. 164 | /// E. 165 | public TrelloCard uploadExceptionCard(Exception e) 166 | { 167 | TrelloCard card = new TrelloCard(); 168 | card.name = e.GetType().ToString(); 169 | card.due = DateTime.Now.ToString(); 170 | card.desc = e.Message; 171 | card.idList = currentListId; 172 | 173 | return uploadCard(card); 174 | } 175 | 176 | /// 177 | /// Uploads a given TrelloCard object to the Trello servers. 178 | /// 179 | /// Your card. 180 | /// Your card. 181 | public TrelloCard uploadCard(TrelloCard card) 182 | { 183 | WWWForm post = new WWWForm(); 184 | post.AddField("name", card.name); 185 | post.AddField("desc", card.desc); 186 | post.AddField("due", card.due); 187 | post.AddField("idList", card.idList); 188 | post.AddField("urlSource", card.urlSource); 189 | 190 | WWW www = new WWW(cardBaseUrl + "?" + "key=" + key + "&token=" + token, post); 191 | 192 | // Wait for request to return 193 | while (!www.isDone) 194 | { 195 | checkWwwStatus("Could not upload Trello card", www); 196 | } 197 | 198 | return card; 199 | } 200 | 201 | 202 | 203 | } 204 | } -------------------------------------------------------------------------------- /TrelloCard.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | namespace Trello 5 | { 6 | public class TrelloCard { 7 | 8 | public string name = ""; 9 | public string desc = ""; 10 | public string due = "null"; 11 | public string idList = ""; 12 | public string urlSource = "null"; 13 | 14 | public TrelloCard() 15 | { 16 | 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TrelloException.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using System; 4 | 5 | namespace Trello 6 | { 7 | public class TrelloException : Exception { 8 | 9 | public TrelloException() : base() 10 | { 11 | 12 | } 13 | 14 | public TrelloException(string message) : base(message) 15 | { 16 | 17 | } 18 | 19 | public TrelloException(string format, params object[] args) : base(string.Format(format, args)) 20 | { 21 | 22 | } 23 | 24 | public TrelloException(string message, Exception innerException) : base(message, innerException) 25 | { 26 | 27 | } 28 | 29 | public TrelloException(string format, Exception innerException, params object[] args) : base(string.Format(format, args), innerException) 30 | { 31 | 32 | } 33 | } 34 | } --------------------------------------------------------------------------------