Add Trello integration script
This is a small Python script to create Trello Webhooks for Zulip. It builds and sends the Trello API requests required to create the Trello webhook.
This commit is contained in:
parent
401674016c
commit
2f4b276799
16
zulip/integrations/trello/README.md
Normal file
16
zulip/integrations/trello/README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Easy Trello integration for Zulip
|
||||
|
||||
An easy Trello integration for Zulip
|
||||
|
||||
Usage :
|
||||
|
||||
1. Fill the needed information in `zulip_trello_config.py` :
|
||||
|
||||
- The bot API KEY,
|
||||
- The Trello API KEY,
|
||||
- The Trello TOKEN,
|
||||
- The Zulip host
|
||||
|
||||
2. Execute the script :
|
||||
|
||||
$ python zulip_trello.py <stream_name> <trello_board_name> <trello_board_id>
|
0
zulip/integrations/trello/requirements.txt
Normal file
0
zulip/integrations/trello/requirements.txt
Normal file
236
zulip/integrations/trello/zulip_trello.py
Executable file
236
zulip/integrations/trello/zulip_trello.py
Executable file
|
@ -0,0 +1,236 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# An easy Trello integration for Zulip.
|
||||
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
import requests
|
||||
|
||||
# Import configuration
|
||||
import zulip_trello_config as configuration
|
||||
|
||||
|
||||
VERSION = '0.2'
|
||||
|
||||
|
||||
# argument's settings
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument(
|
||||
'stream_name',
|
||||
help='The stream to which to integrate Trello.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'trello_board_name',
|
||||
help='The Trello board name.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'trello_board_id',
|
||||
help='The Trello board short id.'
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'-v',
|
||||
'--version',
|
||||
help='Display Version and exit',
|
||||
action='version',
|
||||
version='zulip_trello v'+VERSION
|
||||
)
|
||||
|
||||
|
||||
def check_configuration() -> bool:
|
||||
"""check_configuration
|
||||
|
||||
Check if configuration fields have been populated in
|
||||
zulip_trello_config.py
|
||||
|
||||
:returns: config imported from module zulip_trello_config
|
||||
|
||||
"""
|
||||
|
||||
errors = []
|
||||
|
||||
if not configuration.BOT_API_KEY:
|
||||
errors.append('Error: BOT_API_KEY is not defined in zulip_trello_config.py')
|
||||
|
||||
if not configuration.TRELLO_API_KEY:
|
||||
errors.append('Error: TRELLO_API_KEY is not defined in zulip_trello_config.py')
|
||||
|
||||
if not configuration.TRELLO_TOKEN:
|
||||
errors.append('Error: TRELLO_TOKEN is not defined in zulip_trello_config.py')
|
||||
|
||||
if not configuration.ZULIP_HOST:
|
||||
errors.append('Error: ZULIP_HOST is not defined in zulip_trello_config.py')
|
||||
|
||||
if len(errors) > 0:
|
||||
for error in errors:
|
||||
print(error)
|
||||
|
||||
sys.exit(1)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_model_id(options: argparse.Namespace) -> str:
|
||||
"""get_model_id
|
||||
|
||||
Get Model Id from Trello API
|
||||
|
||||
:options: argparse.Namespace arguments
|
||||
|
||||
:returns: str id_model Trello board idModel
|
||||
|
||||
"""
|
||||
|
||||
trello_api_url = 'https://api.trello.com/1/board/%s' % (
|
||||
options.trello_board_id
|
||||
)
|
||||
|
||||
params = {
|
||||
'key': configuration.TRELLO_API_KEY,
|
||||
'token': configuration.TRELLO_TOKEN,
|
||||
}
|
||||
|
||||
trello_response = requests.get(
|
||||
trello_api_url,
|
||||
params=params
|
||||
)
|
||||
|
||||
if trello_response.status_code is not 200:
|
||||
print('Error: Can\'t get the idModel. Please check the configuration')
|
||||
sys.exit(1)
|
||||
|
||||
board_info_json = trello_response.json()
|
||||
|
||||
return board_info_json['id']
|
||||
|
||||
|
||||
def get_webhook_id(options: argparse.Namespace, id_model: str) -> str:
|
||||
"""get_webhook_id
|
||||
|
||||
Get webhook id from Trello API
|
||||
|
||||
:options: argparse.Namespace arguments
|
||||
:id_model: str Trello board idModel
|
||||
|
||||
:returns: str id_webhook Trello webhook id
|
||||
|
||||
"""
|
||||
|
||||
trello_api_url = 'https://api.trello.com/1/webhooks/'
|
||||
|
||||
data = {
|
||||
'key': configuration.TRELLO_API_KEY,
|
||||
'token': configuration.TRELLO_TOKEN,
|
||||
'description': 'Webhook for Zulip integration (From Trello %s to Zulip %s)' % (
|
||||
options.trello_board_name,
|
||||
options.stream_name
|
||||
),
|
||||
'callbackURL': '%s' % (
|
||||
'https://%s/api/v1/external/trello?api_key=%s&stream=%s' % (
|
||||
configuration.ZULIP_HOST,
|
||||
configuration.BOT_API_KEY,
|
||||
options.stream_name
|
||||
),
|
||||
),
|
||||
'idModel': id_model
|
||||
}
|
||||
|
||||
trello_response = requests.post(
|
||||
trello_api_url,
|
||||
data=data
|
||||
)
|
||||
|
||||
if trello_response.status_code is not 200:
|
||||
print('Error: Can\'t create the Webhook:', trello_response.text)
|
||||
sys.exit(1)
|
||||
|
||||
webhook_info_json = trello_response.json()
|
||||
|
||||
return webhook_info_json['id']
|
||||
|
||||
|
||||
def log_webhook_info(options: argparse.Namespace, id_webhook: str) -> bool:
|
||||
"""log_webhook_info
|
||||
|
||||
Log webhook info in csv file for possible future use
|
||||
|
||||
:options: argparse.Namespace arguments
|
||||
:id_webhook: str Trello webhook id
|
||||
|
||||
:returns: bool
|
||||
|
||||
"""
|
||||
|
||||
with open('zulip_trello_webhooks.csv', 'a') as webhooks_file:
|
||||
webhooks_file.write(
|
||||
'%s,%s,%s\n' % (
|
||||
options.stream_name,
|
||||
options.trello_board_name,
|
||||
id_webhook
|
||||
)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def create_webhook(options: argparse.Namespace) -> bool:
|
||||
"""create_webhook
|
||||
|
||||
Create Trello webhook
|
||||
|
||||
:options: argparse.Namespace arguments
|
||||
|
||||
:returns: bool
|
||||
|
||||
"""
|
||||
|
||||
# first, we need to get the idModel
|
||||
print('Getting Trello idModel for the %s board...' % (options.trello_board_name))
|
||||
|
||||
id_model = get_model_id(options)
|
||||
|
||||
if id_model:
|
||||
print('Success! The idModel is', id_model)
|
||||
|
||||
# Next, we need to create the webhook
|
||||
print('Creating the webhook for the %s stream...' % (options.stream_name))
|
||||
|
||||
id_webhook = get_webhook_id(options, id_model)
|
||||
|
||||
if id_webhook:
|
||||
print('Success! The webhook id is', id_webhook)
|
||||
|
||||
# The webhook was successfully created,
|
||||
# Log informations for possible future needs
|
||||
print('Logging webhook information')
|
||||
|
||||
was_logged = log_webhook_info(options, id_webhook)
|
||||
|
||||
if was_logged:
|
||||
print(
|
||||
'Success! The webhook for the %s stream from the %s Trello board was successfully created.' % (
|
||||
options.stream_name,
|
||||
options.trello_board_name
|
||||
)
|
||||
)
|
||||
|
||||
print('\nYou can find the webhooks information in the zulip_trello_webhooks.csv file.')
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def main() -> None:
|
||||
options = parser.parse_args()
|
||||
if check_configuration():
|
||||
creation_status = create_webhook(options)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
52
zulip/integrations/trello/zulip_trello_config.py
Normal file
52
zulip/integrations/trello/zulip_trello_config.py
Normal file
|
@ -0,0 +1,52 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2014 Zulip, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
|
||||
### REQUIRED CONFIGURATION ###
|
||||
|
||||
# It needs some API KEY and Token (from Zulip and Trello)
|
||||
# For more information, please visit https://zulipchat.com/integrations/doc/trello
|
||||
|
||||
# BOT_API_KEY
|
||||
#
|
||||
# In Zulip, create a new bot for *incomming Webhook*.
|
||||
# It will generate an API KEY
|
||||
BOT_API_KEY = ""
|
||||
|
||||
# TRELLO_API_KEY
|
||||
#
|
||||
# Visit https://trello.com/1/appkey/generate to generate
|
||||
# an APPLICATION_KEY (needs to be logged into Trello)
|
||||
TRELLO_API_KEY = ""
|
||||
|
||||
# TRELLO_TOKEN
|
||||
#
|
||||
# To generate a Trello read access Token, visit (needs to be logged into Trello)
|
||||
# https://trello.com/1/authorize?key=<TRELLO_API_KEY>&name=Issue+Manager&expiration=never&response_type=token&scope=read
|
||||
#
|
||||
# Take care to replace <TRELLO_API_KEY> with the appropriate value
|
||||
TRELLO_TOKEN = ""
|
||||
|
||||
# ZULIP_HOST
|
||||
#
|
||||
# The hostname of your Zulip application
|
||||
ZULIP_HOST = ""
|
1
zulip/integrations/trello/zulip_trello_webhooks.csv
Normal file
1
zulip/integrations/trello/zulip_trello_webhooks.csv
Normal file
|
@ -0,0 +1 @@
|
|||
stream_name,trello_board_name,id_webhook
|
|
Loading…
Reference in a new issue