@pipedream/trello 0.3.14 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/actions/add-attachment-to-card/add-attachment-to-card.mjs +131 -0
  2. package/actions/add-checklist/add-checklist.mjs +50 -42
  3. package/actions/add-comment/add-comment.mjs +44 -35
  4. package/actions/add-existing-label-to-card/add-existing-label-to-card.mjs +19 -14
  5. package/actions/add-member-to-card/add-member-to-card.mjs +19 -14
  6. package/actions/archive-card/archive-card.mjs +15 -10
  7. package/actions/{common.mjs → common/common.mjs} +2 -2
  8. package/actions/complete-checklist-item/complete-checklist-item.mjs +51 -31
  9. package/actions/create-board/create-board.mjs +86 -88
  10. package/actions/create-card/create-card.mjs +102 -53
  11. package/actions/create-checklist-item/create-checklist-item.mjs +54 -39
  12. package/actions/create-label/create-label.mjs +38 -50
  13. package/actions/create-list/create-list.mjs +43 -42
  14. package/actions/delete-checklist/delete-checklist.mjs +17 -14
  15. package/actions/find-labels/find-labels.mjs +14 -12
  16. package/actions/find-list/find-list.mjs +13 -10
  17. package/actions/get-card/get-card.mjs +13 -9
  18. package/actions/get-list/get-list.mjs +29 -15
  19. package/actions/move-card-to-list/move-card-to-list.mjs +17 -13
  20. package/actions/remove-label-from-card/remove-label-from-card.mjs +20 -13
  21. package/actions/rename-list/rename-list.mjs +24 -10
  22. package/actions/search-boards/search-boards.mjs +22 -18
  23. package/actions/search-cards/search-cards.mjs +23 -18
  24. package/actions/search-checklists/search-checklists.mjs +96 -59
  25. package/actions/search-members/search-members.mjs +44 -34
  26. package/actions/update-card/update-card.mjs +68 -50
  27. package/common/constants.mjs +128 -0
  28. package/common/fields.mjs +1 -0
  29. package/package.json +5 -3
  30. package/sources/card-archived/card-archived.mjs +22 -18
  31. package/sources/card-archived/test-event.mjs +64 -0
  32. package/sources/card-due-date-reminder/card-due-date-reminder.mjs +118 -39
  33. package/sources/card-due-date-reminder/test-event.mjs +75 -0
  34. package/sources/card-moved/card-moved.mjs +30 -27
  35. package/sources/card-moved/test-event.mjs +78 -0
  36. package/sources/card-updates/card-updates.mjs +29 -27
  37. package/sources/card-updates/test-event.mjs +86 -0
  38. package/sources/common/actions.mjs +206 -0
  39. package/sources/common/common-board-based.mjs +16 -9
  40. package/sources/common/common-webhook.mjs +86 -32
  41. package/sources/common/common.mjs +7 -4
  42. package/sources/custom-webhook-events/custom-webhook-events.mjs +37 -49
  43. package/sources/new-activity/new-activity.mjs +25 -32
  44. package/sources/new-attachment/new-attachment.mjs +42 -35
  45. package/sources/new-attachment/test-event.mjs +69 -0
  46. package/sources/new-board/new-board.mjs +21 -12
  47. package/sources/new-board/test-event.mjs +100 -0
  48. package/sources/new-card/new-card.mjs +29 -27
  49. package/sources/new-card/test-event.mjs +79 -0
  50. package/sources/new-checklist/new-checklist.mjs +42 -13
  51. package/sources/new-checklist/test-event.mjs +22 -0
  52. package/sources/new-comment-added-to-card/new-comment-added-to-card.mjs +49 -34
  53. package/sources/new-comment-added-to-card/test-event.mjs +298 -0
  54. package/sources/new-label/new-label.mjs +17 -14
  55. package/sources/new-label/test-event.mjs +7 -0
  56. package/sources/new-label-added-to-card/new-label-added-to-card.mjs +38 -29
  57. package/sources/new-label-added-to-card/test-event.mjs +85 -0
  58. package/sources/new-member-on-card/new-member-on-card.mjs +21 -18
  59. package/sources/new-member-on-card/test-event.mjs +83 -0
  60. package/sources/new-notification/new-notification.mjs +8 -7
  61. package/trello.app.mjs +454 -494
  62. package/actions/add-attachment-to-card-via-url/add-attachment-to-card-via-url.mjs +0 -73
  63. package/actions/add-file-as-attachment-via-url/add-file-as-attachment-via-url.mjs +0 -72
  64. package/actions/add-image-attachment/add-image-attachment.mjs +0 -75
  65. package/actions/add-label-to-card/add-label-to-card.mjs +0 -55
  66. package/actions/close-board/close-board.mjs +0 -25
  67. package/actions/copy-board/copy-board.mjs +0 -174
  68. package/actions/create-checklist/create-checklist.mjs +0 -66
  69. package/actions/create-comment-on-card/create-comment-on-card.mjs +0 -42
  70. package/sources/new-list/new-list.mjs +0 -29
  71. /package/{common → sources/common}/events.mjs +0 -0
@@ -1,54 +1,69 @@
1
- import common from "../common/common-polling.mjs";
1
+ import taskScheduler from "../../../pipedream/sources/new-scheduled-tasks/new-scheduled-tasks.mjs";
2
+ import trello from "../../trello.app.mjs";
3
+ import ms from "ms";
4
+ import constants from "../../common/constants.mjs";
5
+ import sampleEmit from "./test-event.mjs";
2
6
 
3
7
  export default {
4
- ...common,
5
8
  key: "trello-card-due-date-reminder",
6
- name: "Card Due Date Reminder",
9
+ name: "Card Due Date Reminder", /* eslint-disable-line pipedream/source-name */
7
10
  description: "Emit new event at a specified time before a card is due.",
8
- version: "0.0.10",
11
+ version: "0.1.1",
9
12
  type: "source",
10
13
  dedupe: "unique",
11
14
  props: {
12
- ...common.props,
15
+ pipedream: taskScheduler.props.pipedream,
16
+ trello,
17
+ db: "$.service.db",
18
+ http: "$.interface.http",
13
19
  board: {
14
20
  propDefinition: [
15
- common.props.trello,
21
+ trello,
16
22
  "board",
17
23
  ],
18
24
  },
19
25
  timeBefore: {
20
- type: "integer",
26
+ type: "string",
21
27
  label: "Time Before",
22
- description: "How far before the due time the event should trigger.",
23
- default: 5,
28
+ description: "How far before the due time the event should trigger. For example, `5 minutes`, `10 minutes`, `1 hour`.",
29
+ default: "5 minutes",
30
+ options: constants.NOTIFICATION_TIMES,
31
+ reloadProps: true,
24
32
  },
25
- timeBeforeUnit: {
26
- type: "integer",
27
- label: "Time Before (Unit)",
28
- description: "Unit of time for Time Before.",
29
- options: [
30
- {
31
- label: "Minutes",
32
- value: 60000,
33
- },
34
- {
35
- label: "Hours",
36
- value: 3600000,
37
- },
38
- {
39
- label: "Days",
40
- value: 86400000,
41
- },
42
- {
43
- label: "Weeks",
44
- value: 604800000,
33
+ },
34
+ async additionalProps() {
35
+ const props = {};
36
+ if (this.timeBefore) {
37
+ props.timer = {
38
+ type: "$.interface.timer",
39
+ description: "Poll the API to schedule alerts for any newly created events",
40
+ default: {
41
+ intervalSeconds: ms(this.timeBefore) / 1000,
45
42
  },
46
- ],
47
- default: 60000,
43
+ };
44
+ }
45
+ return props;
46
+ },
47
+ hooks: {
48
+ async deactivate() {
49
+ const ids = this._getScheduledEventIds();
50
+ if (!ids?.length) {
51
+ return;
52
+ }
53
+ for (const id of ids) {
54
+ if (await this.deleteEvent({
55
+ body: {
56
+ id,
57
+ },
58
+ })) {
59
+ console.log("Cancelled scheduled event");
60
+ }
61
+ }
62
+ this._setScheduledEventIds();
48
63
  },
49
64
  },
50
65
  methods: {
51
- ...common.methods,
66
+ ...taskScheduler.methods,
52
67
  generateMeta({
53
68
  id, name: summary,
54
69
  }, now) {
@@ -58,23 +73,87 @@ export default {
58
73
  ts: now,
59
74
  };
60
75
  },
76
+ _getScheduledEventIds() {
77
+ return this.db.get("scheduledEventIds");
78
+ },
79
+ _setScheduledEventIds(ids) {
80
+ this.db.set("scheduledEventIds", ids);
81
+ },
82
+ _getScheduledCardIds() {
83
+ return this.db.get("scheduledCardIds");
84
+ },
85
+ _setScheduledCardIds(ids) {
86
+ this.db.set("scheduledCardIds", ids);
87
+ },
88
+ _hasDeployed() {
89
+ const result = this.db.get("hasDeployed");
90
+ this.db.set("hasDeployed", true);
91
+ return result;
92
+ },
61
93
  emitEvent(card, now) {
62
94
  const meta = this.generateMeta(card, now);
63
95
  this.$emit(card, meta);
64
96
  },
65
97
  },
66
98
  async run(event) {
67
- const boardId = this.board;
68
99
  const now = event.timestamp * 1000;
69
100
 
70
- const cards = await this.trello.getCards(boardId);
101
+ // self subscribe only on the first time
102
+ if (!this._hasDeployed()) {
103
+ await this.selfSubscribe();
104
+ }
105
+
106
+ let scheduledEventIds = this._getScheduledEventIds() || [];
107
+
108
+ // incoming scheduled event
109
+ if (event.$channel === this.selfChannel()) {
110
+ const remainingScheduledEventIds = scheduledEventIds.filter((id) => id !== event["$id"]);
111
+ this._setScheduledEventIds(remainingScheduledEventIds);
112
+ this.emitEvent(event, now);
113
+ return;
114
+ }
115
+
116
+ // schedule new events
117
+ const scheduledCardIds = this._getScheduledCardIds() || {};
118
+ const cards = await this.trello.getCards({
119
+ boardId: this.board,
120
+ });
121
+
71
122
  for (const card of cards) {
72
- if (!card.due) continue;
73
- const due = Date.parse(card.due);
74
- const notifyAt = due - this.timeBefore * this.timeBeforeUnit;
75
- if (notifyAt <= now) {
76
- this.emitEvent(card, now);
123
+ const dueDate = card.due
124
+ ? new Date(card.due)
125
+ : null;
126
+ if (!dueDate || dueDate.getTime() < Date.now()) {
127
+ delete scheduledCardIds[card.id];
128
+ continue;
129
+ }
130
+
131
+ const later = new Date(dueDate.getTime() - ms(this.timeBefore));
132
+
133
+ if (scheduledCardIds[card.id]) {
134
+ // reschedule if card's due date has changed
135
+ if (card.due !== scheduledCardIds[card.id].dueDate) {
136
+ await this.deleteEvent({
137
+ body: {
138
+ id: scheduledCardIds[card.id].eventId,
139
+ },
140
+ });
141
+ scheduledEventIds = scheduledEventIds
142
+ .filter((id) => id !== scheduledCardIds[card.id].eventId);
143
+ } else {
144
+ continue;
145
+ }
77
146
  }
147
+
148
+ const scheduledEventId = this.emitScheduleEvent(card, later);
149
+ scheduledEventIds.push(scheduledEventId);
150
+ scheduledCardIds[card.id] = {
151
+ eventId: scheduledEventId,
152
+ dueDate: card.due,
153
+ };
78
154
  }
155
+ this._setScheduledEventIds(scheduledEventIds);
156
+ this._setScheduledCardIds(scheduledCardIds);
79
157
  },
158
+ sampleEmit,
80
159
  };
@@ -0,0 +1,75 @@
1
+ export default {
2
+ "id": "61818a303e545129af23695d",
3
+ "badges": {
4
+ "attachmentsByType": {
5
+ "trello": {
6
+ "board": 0,
7
+ "card": 0
8
+ }
9
+ },
10
+ "externalSource": null,
11
+ "location": false,
12
+ "votes": 0,
13
+ "viewingMemberVoted": false,
14
+ "subscribed": true,
15
+ "fogbugz": "",
16
+ "checkItems": 1,
17
+ "checkItemsChecked": 1,
18
+ "checkItemsEarliestDue": null,
19
+ "comments": 2,
20
+ "attachments": 1,
21
+ "description": false,
22
+ "due": "2024-10-01T19:20:00.000Z",
23
+ "dueComplete": false,
24
+ "start": null,
25
+ "lastUpdatedByAi": false
26
+ },
27
+ "checkItemStates": [
28
+ {
29
+ "idCheckItem": "6181a5f18e239e6aff9799a4",
30
+ "state": "complete"
31
+ }
32
+ ],
33
+ "closed": false,
34
+ "dueComplete": false,
35
+ "dateLastActivity": "2024-10-01T19:08:51.312Z",
36
+ "desc": "",
37
+ "descData": {
38
+ "emoji": {}
39
+ },
40
+ "due": "2024-10-01T19:20:00.000Z",
41
+ "dueReminder": -1,
42
+ "email": null,
43
+ "idBoard": "5f4d7be6c45c22583f75fa02",
44
+ "idChecklists": [
45
+ "6181a5ef401ae66c357732b4"
46
+ ],
47
+ "idList": "5f4d7f78bdd7ce4d2d25fdda",
48
+ "idMembers": [],
49
+ "idMembersVoted": [],
50
+ "idShort": 68,
51
+ "idAttachmentCover": "62c884dce32d46579ecfd5f0",
52
+ "labels": [],
53
+ "idLabels": [],
54
+ "manualCoverAttachment": false,
55
+ "name": "test",
56
+ "pinned": false,
57
+ "pos": 131071,
58
+ "shortLink": "QVLahShU",
59
+ "shortUrl": "https://trello.com/c/QVLahShU",
60
+ "start": null,
61
+ "subscribed": true,
62
+ "url": "https://trello.com/c/QVLahShU/68-sfsfdsfd",
63
+ "cover": {
64
+ "idAttachment": "62c884dce32d46579ecfd5f0",
65
+ "color": null,
66
+ "idUploadedBackground": null,
67
+ "size": "normal",
68
+ "brightness": "dark",
69
+ "idPlugin": null
70
+ },
71
+ "isTemplate": false,
72
+ "cardRole": null,
73
+ "$channel": "self",
74
+ "$id": "62377726-40b9-41a8-85c7-b01f3f5f8fbe"
75
+ }
@@ -1,40 +1,46 @@
1
1
  import common from "../common/common-webhook.mjs";
2
+ import sampleEmit from "./test-event.mjs";
2
3
 
3
4
  export default {
4
5
  ...common,
5
6
  key: "trello-card-moved",
6
- name: "Card Moved (Instant)",
7
+ name: "Card Moved (Instant)", /* eslint-disable-line pipedream/source-name */
7
8
  description: "Emit new event each time a card is moved to a list.",
8
- version: "0.0.12",
9
+ version: "0.1.1",
9
10
  type: "source",
10
11
  props: {
11
12
  ...common.props,
12
13
  board: {
13
14
  propDefinition: [
14
- common.props.trello,
15
+ common.props.app,
15
16
  "board",
16
17
  ],
17
18
  },
18
19
  lists: {
19
20
  propDefinition: [
20
- common.props.trello,
21
+ common.props.app,
21
22
  "lists",
22
23
  (c) => ({
23
24
  board: c.board,
24
25
  }),
25
26
  ],
27
+ description: "If specified, events will only be emitted if a card is moved to or from one of the selected lists",
26
28
  },
27
29
  },
28
30
  methods: {
29
31
  ...common.methods,
30
32
  async getSampleEvents() {
31
- const cards = this.lists && this.lists.length > 0
32
- ? await this.trello.getCardsInList(this.lists[0])
33
- : await this.trello.getCards(this.board);
34
- return {
35
- sampleEvents: cards,
36
- sortFilter: "dateLastActivity",
37
- };
33
+ const cards = this.lists?.length > 0
34
+ ? await this.app.getCardsInList({
35
+ listId: this.lists[0],
36
+ })
37
+ : await this.app.getCards({
38
+ boardId: this.board,
39
+ });
40
+ return cards;
41
+ },
42
+ getSortField() {
43
+ return "dateLastActivity";
38
44
  },
39
45
  _getListAfter() {
40
46
  return this.db.get("listAfter");
@@ -42,35 +48,31 @@ export default {
42
48
  _setListAfter(listAfter) {
43
49
  this.db.set("listAfter", listAfter);
44
50
  },
45
- isCorrectEventType(event) {
46
- const eventTranslationKey = event.body?.action?.display?.translationKey;
47
- return eventTranslationKey === "action_move_card_from_list_to_list";
51
+ isCorrectEventType({ display }) {
52
+ return display?.translationKey === "action_move_card_from_list_to_list";
48
53
  },
49
- async getResult(event) {
50
- const cardId = event.body?.action?.data?.card?.id;
51
- const listAfter = event.body?.action?.data?.listAfter?.name;
54
+ getResult({ data }) {
52
55
  /** Record listAfter to use in generateMeta() */
53
- this._setListAfter(listAfter);
54
- return this.trello.getCard(cardId);
56
+ this._setListAfter(data?.listAfter?.name);
57
+ return this.app.getCard({
58
+ cardId: data?.card?.id,
59
+ });
55
60
  },
56
61
  isRelevant({
57
- result: card, event,
62
+ result: card, action,
58
63
  }) {
59
- const listIdAfter = event.body?.action?.data?.listAfter?.id;
60
- const listIdBefore = event.body?.action?.data?.listBefore?.id;
61
-
62
64
  return (
63
65
  (!this.board || this.board === card.idBoard) &&
64
- (!this.lists ||
65
- this.lists.length === 0 ||
66
- this.lists.includes(listIdAfter) ||
67
- this.lists.includes(listIdBefore))
66
+ (!this.lists?.length ||
67
+ this.lists.includes(action?.data?.listAfter?.id) ||
68
+ this.lists.includes(action?.data?.listBefore?.id))
68
69
  );
69
70
  },
70
71
  generateMeta({
71
72
  id, name,
72
73
  }) {
73
74
  const listAfter = this._getListAfter();
75
+ name = name || id;
74
76
  const summary = listAfter
75
77
  ? `${name} - moved to ${listAfter}`
76
78
  : name;
@@ -81,4 +83,5 @@ export default {
81
83
  };
82
84
  },
83
85
  },
86
+ sampleEmit,
84
87
  };
@@ -0,0 +1,78 @@
1
+ export default {
2
+ "id": "60836bac2ed2ef78f4cf850d",
3
+ "badges": {
4
+ "attachmentsByType": {
5
+ "trello": {
6
+ "board": 0,
7
+ "card": 0
8
+ }
9
+ },
10
+ "externalSource": null,
11
+ "location": false,
12
+ "votes": 0,
13
+ "viewingMemberVoted": false,
14
+ "subscribed": true,
15
+ "fogbugz": "",
16
+ "checkItems": 1,
17
+ "checkItemsChecked": 0,
18
+ "checkItemsEarliestDue": null,
19
+ "comments": 3,
20
+ "attachments": 1,
21
+ "description": false,
22
+ "due": "2021-05-10T21:50:00.000Z",
23
+ "dueComplete": false,
24
+ "start": null,
25
+ "lastUpdatedByAi": false
26
+ },
27
+ "checkItemStates": [],
28
+ "closed": false,
29
+ "dueComplete": false,
30
+ "dateLastActivity": "2021-11-02T23:02:44.876Z",
31
+ "desc": "",
32
+ "descData": null,
33
+ "due": "2021-05-10T21:50:00.000Z",
34
+ "dueReminder": 1440,
35
+ "email": null,
36
+ "idBoard": "5f4d7be6c45c22583f75fa02",
37
+ "idChecklists": [
38
+ "608b2037ea7ac07da59c17be"
39
+ ],
40
+ "idList": "5f4ec9f69028408fed04c0b1",
41
+ "idMembers": [],
42
+ "idMembersVoted": [],
43
+ "idShort": 54,
44
+ "idAttachmentCover": "6099aece406c0b7a97e71535",
45
+ "labels": [
46
+ {
47
+ "id": "608b2273586147300cc73046",
48
+ "idBoard": "5f4d7be6c45c22583f75fa02",
49
+ "idOrganization": "6047c17c2f558003144e04d7",
50
+ "name": "orange",
51
+ "nodeId": "ari:cloud:trello::label/workspace/6047c17c2f558003144e04d7/608b2273586147300cc73046",
52
+ "color": "orange",
53
+ "uses": 4
54
+ },
55
+ ],
56
+ "idLabels": [
57
+ "608b2273586147300cc73046",
58
+ ],
59
+ "manualCoverAttachment": false,
60
+ "name": "new card",
61
+ "pinned": false,
62
+ "pos": 655359,
63
+ "shortLink": "fo2GH2y2",
64
+ "shortUrl": "https://trello.com/c/fo2GH2y2",
65
+ "start": null,
66
+ "subscribed": true,
67
+ "url": "https://trello.com/c/fo2GH2y2/54-new-card",
68
+ "cover": {
69
+ "idAttachment": "6099aece406c0b7a97e71535",
70
+ "color": null,
71
+ "idUploadedBackground": null,
72
+ "size": "normal",
73
+ "brightness": "dark",
74
+ "idPlugin": null
75
+ },
76
+ "isTemplate": false,
77
+ "cardRole": null
78
+ }
@@ -1,72 +1,74 @@
1
1
  import common from "../common/common-webhook.mjs";
2
+ import sampleEmit from "./test-event.mjs";
2
3
 
3
4
  export default {
4
5
  ...common,
5
6
  key: "trello-card-updates",
6
- name: "Card Updates (Instant)",
7
+ name: "Card Updated (Instant)", /* eslint-disable-line pipedream/source-name */
7
8
  description: "Emit new event for each update to a Trello card.",
8
- version: "0.0.12",
9
+ version: "0.1.1",
9
10
  type: "source",
10
11
  props: {
11
12
  ...common.props,
12
13
  board: {
13
14
  propDefinition: [
14
- common.props.trello,
15
+ common.props.app,
15
16
  "board",
16
17
  ],
17
18
  },
18
19
  cards: {
19
20
  propDefinition: [
20
- common.props.trello,
21
+ common.props.app,
21
22
  "cards",
22
23
  (c) => ({
23
24
  board: c.board,
24
25
  }),
25
26
  ],
26
27
  },
27
- customFieldItems: {
28
- propDefinition: [
29
- common.props.trello,
30
- "customFieldItems",
31
- ],
32
- },
33
28
  },
34
29
  methods: {
35
30
  ...common.methods,
36
31
  async getSampleEvents() {
37
32
  let cards = [];
38
- if (this.cards && this.cards.length > 0) {
33
+ const params = {
34
+ customFieldItems: true,
35
+ };
36
+ if (this.cards?.length > 0) {
39
37
  for (const cardId of this.cards) {
40
- const card = await this.trello.getCard(cardId, {
41
- customFieldItems: this.customFieldItems,
38
+ const card = await this.app.getCard({
39
+ cardId,
40
+ params,
42
41
  });
43
42
  cards.push(card);
44
43
  }
45
44
  } else {
46
- cards = await this.trello.getCards(this.board, {
47
- customFieldItems: this.customFieldItems,
45
+ cards = await this.app.getCards({
46
+ boardId: this.board,
47
+ params,
48
48
  });
49
49
  }
50
- return {
51
- sampleEvents: cards,
52
- sortField: "dateLastActivity",
53
- };
50
+ return cards;
51
+ },
52
+ getSortField() {
53
+ return "dateLastActivity";
54
54
  },
55
- isCorrectEventType(event) {
56
- const eventType = event.body?.action?.type;
57
- return eventType === "updateCard";
55
+ isCorrectEventType({ type }) {
56
+ return type === "updateCard";
58
57
  },
59
- async getResult(event) {
60
- const cardId = event.body?.action?.data?.card?.id;
61
- return this.trello.getCard(cardId, {
62
- customFieldItems: this.customFieldItems,
58
+ getResult({ data }) {
59
+ return this.app.getCard({
60
+ cardId: data?.card?.id,
61
+ params: {
62
+ customFieldItems: true,
63
+ },
63
64
  });
64
65
  },
65
66
  isRelevant({ result: card }) {
66
67
  return (
67
68
  (!this.board || this.board === card.idBoard) &&
68
- (!this.cards || this.cards.length === 0 || this.cards.includes(card.id))
69
+ (!this.cards?.length || this.cards.includes(card.id))
69
70
  );
70
71
  },
71
72
  },
73
+ sampleEmit,
72
74
  };
@@ -0,0 +1,86 @@
1
+ export default {
2
+ "id": "620eb14ebda9570d72fddead",
3
+ "badges": {
4
+ "attachmentsByType": {
5
+ "trello": {
6
+ "board": 0,
7
+ "card": 0
8
+ }
9
+ },
10
+ "externalSource": null,
11
+ "location": false,
12
+ "votes": 0,
13
+ "viewingMemberVoted": false,
14
+ "subscribed": false,
15
+ "fogbugz": "",
16
+ "checkItems": 1,
17
+ "checkItemsChecked": 1,
18
+ "checkItemsEarliestDue": null,
19
+ "comments": 3,
20
+ "attachments": 1,
21
+ "description": false,
22
+ "due": "2021-05-10T21:50:00.000Z",
23
+ "dueComplete": false,
24
+ "start": null,
25
+ "lastUpdatedByAi": false
26
+ },
27
+ "checkItemStates": [
28
+ {
29
+ "idCheckItem": "620eb14fbda9570d72fde031",
30
+ "state": "complete"
31
+ }
32
+ ],
33
+ "closed": false,
34
+ "dueComplete": false,
35
+ "dateLastActivity": "2024-09-30T16:31:35.215Z",
36
+ "desc": "",
37
+ "descData": {
38
+ "emoji": {}
39
+ },
40
+ "due": "2021-05-10T21:50:00.000Z",
41
+ "dueReminder": null,
42
+ "email": null,
43
+ "idBoard": "5f4d7be6c45c22583f75fa02",
44
+ "idChecklists": [
45
+ "620eb14fbda9570d72fde030"
46
+ ],
47
+ "idList": "5f4d7f78bdd7ce4d2d25fdda",
48
+ "idMembers": [],
49
+ "idMembersVoted": [],
50
+ "idShort": 85,
51
+ "idAttachmentCover": "620eb14ebda9570d72fdded7",
52
+ "labels": [
53
+ {
54
+ "id": "5f4d7be6cdabcf46c027c792",
55
+ "idBoard": "5f4d7be6c45c22583f75fa02",
56
+ "idOrganization": "6047c17c2f558003144e04d7",
57
+ "name": "green label",
58
+ "nodeId": "ari:cloud:trello::label/workspace/6047c17c2f558003144e04d7/5f4d7be6cdabcf46c027c792",
59
+ "color": "green",
60
+ "uses": 9
61
+ },
62
+ ],
63
+ "idLabels": [
64
+ "5f4d7be6cdabcf46c027c792",
65
+ ],
66
+ "manualCoverAttachment": false,
67
+ "name": "new card",
68
+ "pinned": false,
69
+ "pos": 360447,
70
+ "shortLink": "dho6bOdR",
71
+ "shortUrl": "https://trello.com/c/dho6bOdR",
72
+ "start": null,
73
+ "subscribed": false,
74
+ "url": "https://trello.com/c/dho6bOdR/85-new-card",
75
+ "cover": {
76
+ "idAttachment": "620eb14ebda9570d72fdded7",
77
+ "color": null,
78
+ "idUploadedBackground": null,
79
+ "size": "normal",
80
+ "brightness": "dark",
81
+ "idPlugin": null
82
+ },
83
+ "isTemplate": false,
84
+ "cardRole": null,
85
+ "customFieldItems": []
86
+ }