From aff6e361f03f1a7e269edc184884313557c94362 Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Sun, 26 Dec 2021 11:16:06 +0200 Subject: [PATCH] Added api.py for using newest Trello API, to show Trello boards/cards/actions/reactions JSON and download Trello attachments as binary files from S3. Thanks to xet7 ! Related #4261, related #3950 --- trello/CHANGELOG.md | 8 +++ trello/LICENSE | 21 ++++++ trello/api.py | 154 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 trello/CHANGELOG.md create mode 100644 trello/LICENSE create mode 100755 trello/api.py diff --git a/trello/CHANGELOG.md b/trello/CHANGELOG.md new file mode 100644 index 000000000..9c247dab8 --- /dev/null +++ b/trello/CHANGELOG.md @@ -0,0 +1,8 @@ +# v1.0 2021-12-26 WeKan ® Python Trello API CLI release + +This release adds the following new features: + +- Added api.py for using newest Trello API, to show Trello boards/cards/actions/reactions JSON and download Trello attachments as binary files from S3. + Thanks to xet7. + +Thanks to above GitHub users for their contributions and translators for their translations. diff --git a/trello/LICENSE b/trello/LICENSE new file mode 100644 index 000000000..7997dfe4c --- /dev/null +++ b/trello/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2021-2022 The Wekan Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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 NONINFRINGEMENT. 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. diff --git a/trello/api.py b/trello/api.py new file mode 100755 index 000000000..b0f66e6fc --- /dev/null +++ b/trello/api.py @@ -0,0 +1,154 @@ +#! /usr/bin/env python3 +# -*- coding: utf-8 -*- +# vi:ts=4:et + +# Trello API Python CLI +# License: MIT / WeKan Team + +try: + # python 3 + from urllib.parse import urlencode + from urllib.request import urlretrieve +except ImportError: + # python 2 + from urllib import urlencode + +import json +import requests +import sys + + +# ------- TRELLO SETTINGS START ------------- + +# CHECK RATE LIMITS: https://developer.atlassian.com/cloud/trello/guides/rest-api/rate-limits/ +# See https://developer.atlassian.com/cloud/trello/guides/rest-api/api-introduction/ +# Get developer API key and create token at top of https://trello.com/app-key + +key = 'TRELLO-API-KEY-HERE' +token = 'TRELLO-API-TOKEN-HERE' + +# ------- TRELLO SETTINGS END ------------- + +arguments = len(sys.argv) - 1 + +if arguments == 0: + print("=== Trello API Python CLI ===") + print("License: MIT / WeKan Team") + print("See settings in this api.py script for api key and token.") + print("If *nix: chmod +x api.py => ./api.py users") + print("Syntax:") + print(" python3 api.py emoji # List all available emoji") + print(" python3 api.py boards # List All Boards") + print(" python3 api.py board BOARDID # Info of BOARDID") + print(" python3 api.py card CARDID # Info of CARDID") + print(" python3 api.py actions BOARDID # Actions of BOARDID") + print(" python3 api.py reactions ACTIONID # Reactions of ACTIONID") + print(" python3 api.py attachments CARDID # List attachments of CARDID") + print(" python3 api.py download ATTACHMENTURL # Download file from attachment URL like https://.../image.png with streaming and minimal RAM usage") + exit + +if arguments == 2: + + if sys.argv[1] == 'board': + + # ------- BOARD START ----------- + #headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)} + headers = {'Accept': 'application/json'} + boardid = sys.argv[2] + print("=== ONE BOARD ===\n") + listboard = 'https://api.trello.com/1/boards/' + boardid + '?key=' + key + '&token=' + token + body = requests.get(listboard, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- BOARD END ----------- + + if sys.argv[1] == 'card': + + # ------- CARD START ----------- + headers = {'Accept': 'application/json'} + cardid = sys.argv[2] + print("=== ONE CARD ===\n") + listcard = 'https://api.trello.com/1/cards/' + cardid + '?fields=all&key=' + key + '&token=' + token + body = requests.get(listcard, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- BOARD END ----------- + + if sys.argv[1] == 'actions': + + # ------- BOARD ACTIONS START ----------- + headers = {'Accept': 'application/json'} + boardid = sys.argv[2] + print("=== ONE BOARD ACTIONS ===\n") + listboardactions = 'https://api.trello.com/1/boards/' + boardid + '/actions?key=' + key + '&token=' + token + body = requests.get(listboardactions, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- BOARD ACTIONS END ----------- + + if sys.argv[1] == 'reactions': + + # ------- REACTIONS OF ACTIONID START ----------- + headers = {'Accept': 'application/json'} + actionid = sys.argv[2] + print("=== REACTIONS OF ACTIONID ===\n") + listreactions = 'https://api.trello.com/1/actions/' + actionid + '/reactionsSummary?key=' + key + '&token=' + token + body = requests.get(listreactions, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- REACTIONS OF ACTIONID END ----------- + + if sys.argv[1] == 'attachments': + + # ------- LIST CARD ATTACHMENTS START ----------- + headers = {'Accept': 'application/json'} + cardid = sys.argv[2] + print("=== LIST CARD ATTACHMENTS ===\n") + listcardattachments = 'https://api.trello.com/1/cards/' + cardid + '/attachments?key=' + key + '&token=' + token + body = requests.get(listcardattachments, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- LIST CARD ATTACHMENTS END ----------- + + if sys.argv[1] == 'download': + + # ------- DOWNLOAD BOARD ATTACHMENT START ----------- + headers = {'Accept': 'application/json', 'Authorization': 'OAuth oauth_consumer_key="' + key + '", oauth_token="' + token + '"'} + url = sys.argv[2] + print("=== DOWNLOAD BOARD ATTACHMENT ===\n") + local_filename = url.split('/')[-1] + # NOTE the stream=True parameter below. Does streaming download with minimal RAM usage. + with requests.get(url, stream=True, headers=headers) as r: + r.raise_for_status() + with open(local_filename, 'wb') as f: + for chunk in r.iter_content(chunk_size=8192): + # If you have chunk encoded response uncomment if + # and set chunk_size parameter to None. + #if chunk: + f.write(chunk) + print("filename: " + local_filename + "\n") + # ------- DOWNLOAD BOARD ATTACHMENT END ----------- + +if arguments == 1: + + if sys.argv[1] == 'boards': + + # ------- LIST OF BOARDS START ----------- + headers = {'Accept': 'application/json'} + print("=== BOARDS ===\n") + listboards = 'https://api.trello.com/1/members/me/boards?key=' + key + '&token=' + token + body = requests.get(listboards, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- LIST OF BOARDS END ----------- + + if sys.argv[1] == 'emoji': + + # ------- LIST OF EMOJI START ----------- + headers = {'Accept': 'application/json'} + print("=== LIST OF ALL EMOJI ===\n") + listemoji = 'https://api.trello.com/1/emoji?key=' + key + '&token=' + token + body = requests.get(listemoji, headers=headers) + data2 = body.text.replace('}',"}\n") + print(data2) + # ------- LIST OF EMOJI END -----------