Skip to content

Commit

Permalink
integrations: Add ClickUp integration.
Browse files Browse the repository at this point in the history
Creates an incoming webhook integration for ClickUp.
The main use case is getting notifications when new ClickUp
items such as task, list, folder, space, goals are created,
updated or deleted.

Fixes zulip#26529.
  • Loading branch information
PieterCK committed Sep 16, 2024
1 parent 93e0561 commit 204f275
Show file tree
Hide file tree
Showing 37 changed files with 1,366 additions and 0 deletions.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added static/images/integrations/clickup/001.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions static/images/integrations/logos/clickup.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions zerver/lib/integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
WebhookIntegration("buildbot", ["continuous-integration"], display_name="Buildbot"),
WebhookIntegration("canarytoken", ["monitoring"], display_name="Thinkst Canarytokens"),
WebhookIntegration("circleci", ["continuous-integration"], display_name="CircleCI"),
WebhookIntegration("clickup", ["project-management"], display_name="ClickUp"),
WebhookIntegration("clubhouse", ["project-management"]),
WebhookIntegration("codeship", ["continuous-integration", "deployment"]),
WebhookIntegration("crashlytics", ["monitoring"]),
Expand Down Expand Up @@ -726,6 +727,7 @@ def __init__(self, name: str, *args: Any, **kwargs: Any) -> None:
ScreenshotConfig("bitbucket_job_completed.json", image_name="001.png"),
ScreenshotConfig("github_job_completed.json", image_name="002.png"),
],
"clickup": [ScreenshotConfig("task_moved.json")],
"clubhouse": [ScreenshotConfig("story_create.json")],
"codeship": [ScreenshotConfig("error_build.json")],
"crashlytics": [ScreenshotConfig("issue_message.json")],
Expand Down
1 change: 1 addition & 0 deletions zerver/webhooks/clickup/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

33 changes: 33 additions & 0 deletions zerver/webhooks/clickup/api_endpoints.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from typing import Any
from urllib.parse import urljoin

import requests

from zerver.lib.outgoing_http import OutgoingSession


class ClickUpSession(OutgoingSession):
def __init__(self, **kwargs: Any) -> None:
super().__init__(role="clickup", timeout=5, **kwargs) # nocoverage


def get_clickup_api_data(clickup_api_path: str, **kwargs: Any) -> dict[str, Any]:
if not kwargs.get("token"):
raise AssertionError("ClickUp API 'token' missing in kwargs")
token = kwargs.pop("token")

headers = {
"Content-Type": "application/json",
"Authorization": token,
}

base_url = "https://api.clickup.com/api/v2/"
api_endpoint = urljoin(base_url, clickup_api_path)
print("api_endpoint: ", api_endpoint)
response = ClickUpSession(headers=headers).get(
api_endpoint,
)
if response.status_code == requests.codes.ok:
return response.json()
else:
raise Exception(f"HTTP error accessing the ClickUp API. Error: {response.status_code}")
14 changes: 14 additions & 0 deletions zerver/webhooks/clickup/callback_fixtures/get_folder.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"id": "457",
"name": "Lord Foldemort",
"orderindex": 0,
"override_statuses": false,
"hidden": false,
"space": {
"id": "789",
"name": "Space Name",
"access": true
},
"task_count": "0",
"lists": []
}
33 changes: 33 additions & 0 deletions zerver/webhooks/clickup/callback_fixtures/get_goal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"goal": {
"id": "e53a033c-900e-462d-a849-4a216b06d930",
"name": "hat-trick",
"team_id": "512",
"date_created": "1568044355026",
"start_date": null,
"due_date": "1568036964079",
"description": "Updated Goal Description",
"private": false,
"archived": false,
"creator": 183,
"color": "#32a852",
"pretty_id": "6",
"multiple_owners": true,
"folder_id": null,
"members": [],
"owners": [
{
"id": 182,
"username": "Pieter CK",
"email": "[email protected]",
"color": "#7b68ee",
"initials": "PK",
"profilePicture": "https://attachments-public.clickup.com/profilePictures/182_abc.jpg"
}
],
"key_results": [],
"percent_completed": 0,
"history": [],
"pretty_url": "https://app.clickup.com/512/goals/6"
}
}
49 changes: 49 additions & 0 deletions zerver/webhooks/clickup/callback_fixtures/get_list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{
"id": "124",
"name": "Listener",
"orderindex": 1,
"content": "Updated List Content",
"status": {
"status": "red",
"color": "#e50000",
"hide_label": true
},
"priority": {
"priority": "high",
"color": "#f50000"
},
"assignee": null,
"due_date": "1567780450202",
"due_date_time": true,
"start_date": null,
"start_date_time": null,
"folder": {
"id": "456",
"name": "Folder Name",
"hidden": false,
"access": true
},
"space": {
"id": "789",
"name": "Space Name",
"access": true
},
"inbound_address": "add.task.124.ac725f.31518a6a-05bb-4997-92a6-1dcfe2f527ca@tasks.clickup.com",
"archived": false,
"override_statuses": false,
"statuses": [
{
"status": "to do",
"orderindex": 0,
"color": "#d3d3d3",
"type": "open"
},
{
"status": "complete",
"orderindex": 1,
"color": "#6bc950",
"type": "closed"
}
],
"permission_level": "create"
}
52 changes: 52 additions & 0 deletions zerver/webhooks/clickup/callback_fixtures/get_space.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"id": "790",
"name": "the Milky Way",
"private": false,
"statuses": [
{
"status": "to do",
"type": "open",
"orderindex": 0,
"color": "#d3d3d3"
},
{
"status": "complete",
"type": "closed",
"orderindex": 1,
"color": "#6bc950"
}
],
"multiple_assignees": false,
"features": {
"due_dates": {
"enabled": false,
"start_date": false,
"remap_due_dates": false,
"remap_closed_due_date": false
},
"time_tracking": {
"enabled": false
},
"tags": {
"enabled": false
},
"time_estimates": {
"enabled": false
},
"checklists": {
"enabled": true
},
"custom_fields": {
"enabled": true
},
"remap_dependencies": {
"enabled": false
},
"dependency_warning": {
"enabled": false
},
"portfolios": {
"enabled": false
}
}
}
63 changes: 63 additions & 0 deletions zerver/webhooks/clickup/callback_fixtures/get_task.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"id": "string",
"custom_id": "string",
"custom_item_id": 0,
"name": "Tanswer",
"text_content": "string",
"description": "string",
"status": {
"status": "in progress",
"color": "#d3d3d3",
"orderindex": 1,
"type": "custom"
},
"orderindex": "string",
"date_created": "string",
"date_updated": "string",
"date_closed": "string",
"creator": {
"id": 183,
"username": "Pieter CK",
"color": "#827718",
"profilePicture": "https://attachments-public.clickup.com/profilePictures/183_abc.jpg"
},
"assignees": ["string"],
"checklists": ["string"],
"tags": ["string"],
"parent": "string",
"priority": "string",
"due_date": "string",
"start_date": "string",
"time_estimate": "string",
"time_spent": "string",
"custom_fields": [
{
"id": "string",
"name": "string",
"type": "string",
"type_config": {},
"date_created": "string",
"hide_from_guests": true,
"value": {
"id": 183,
"username": "Pieter CK",
"email": "[email protected]",
"color": "#7b68ee",
"initials": "PK",
"profilePicture": null
},
"required": true
}
],
"list": {
"id": "123"
},
"folder": {
"id": "456"
},
"space": {
"id": "789"
},
"url": "https://app.clickup.com/XXXXXXXX/home",
"markdown_description": "string"
}
57 changes: 57 additions & 0 deletions zerver/webhooks/clickup/doc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Zulip ClickUp integration

Get Zulip notifications for your ClickUp space!

{start_tabs}

1. {!create-channel.md!}

1. {!create-an-incoming-webhook.md!}

1. {!generate-webhook-url-basic.md!}

1. Collect your ClickUp **Team ID** by going to your ClickUp home view.
The URL should look like `https://app.clickup.com/<TEAM_ID>/home`.
Note down the `<TEAM_ID>`.

1. Collect your ClickUp **Client ID** and **Client Secret** by following these steps:

- Go to your [ClickUp API menu][1] and click **Create an App**.

- You will be prompted for **Redirect URL(s)**, enter the URL for your Zulip organization.
e.g., `{{ zulip_url }}`.

- Note down the **Client ID** and **Client Secret**

1. Download [zulip-clickup.py][2]. `Ctrl+s` or `Cmd+s` on that page should
work in most browsers.

1. Make sure you have a working copy of [Python](https://realpython.com/installing-python/),
it will be needed to run the script.

1. Run the `zulip-clickup.py` script in a terminal, after replacing the all caps
arguments with the values collected above.

```
python zulip-clickup.py --clickup-team-id <clickup_team_id> \
--clickup-client-id <clickup_client_id> \
--clickup-client-secret <clickup_client_secret> \
--zulip-webhook-url "<zulip_webhook_url>"
```
1. Follow the instructions in the terminal and keep an eye on your browser as you
will be redirected to a ClickUp authorization page.
{end_tabs}
{!congrats.md!}
![](/static/images/integrations/clickup/001.png)
### Related documentation
{!webhooks-url-specification.md!}
[1]: https://app.clickup.com/settings/team/clickup-api
[2]: https://raw.githubusercontent.com/zulip/python-zulip-api/main/zulip/integrations/clickup/zulip_clickup.py
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/folder_created.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "folderCreated",
"folder_id": "96772212",
"webhook_id": "7fa3ec74-69a8-4530-a251-8a13730bd204"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/folder_deleted.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "folderDeleted",
"folder_id": "96772212",
"webhook_id": "7fa3ec74-69a8-4530-a251-8a13730bd204"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/folder_updated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "folderUpdated",
"folder_id": "96772212",
"webhook_id": "7fa3ec74-69a8-4530-a251-8a13730bd204"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/goal_created.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "goalCreated",
"goal_id": "a23e5a3d-74b5-44c2-ab53-917ebe85045a",
"webhook_id": "d5eddb2d-db2b-49e9-87d4-bc6cfbe2313b"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/goal_deleted.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "goalDeleted",
"goal_id": "a23e5a3d-74b5-44c2-ab53-917ebe85045a",
"webhook_id": "d5eddb2d-db2b-49e9-87d4-bc6cfbe2313b"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/goal_updated.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "goalUpdated",
"goal_id": "a23e5a3d-74b5-44c2-ab53-917ebe85045a",
"webhook_id": "d5eddb2d-db2b-49e9-87d4-bc6cfbe2313b"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/list_created.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "listCreated",
"list_id": "901601848935",
"webhook_id": "7fa3ec74-69a8-4530-a251-8a13730bd204"
}
5 changes: 5 additions & 0 deletions zerver/webhooks/clickup/fixtures/list_deleted.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"event": "listDeleted",
"list_id": "901601848935",
"webhook_id": "7fa3ec74-69a8-4530-a251-8a13730bd204"
}
Loading

0 comments on commit 204f275

Please sign in to comment.