Loading
Loading
This is a relatively complex Functions, featuring multiple triggers and custom error handling.
This function will create a Jira ticket based on a Slack thread if either
main.py file
import datetime
import json
import os
import requests
import openai
is_reaction_trigger = "reaction" in zapier.trigger_output["trigger_name"]
is_message_trigger = "message" in zapier.trigger_output["trigger_name"]
formatted_date = ""
# get message depending on the trigger type
def get_message():
if is_reaction_trigger:
return zapier.trigger_output["message"]
else:
return zapier.trigger_output
# send a message to the triggering Slack thread
def send_slack_message(message):
trigger_message = get_message()
thread_ts = trigger_message["ts"]
channel_id = trigger_message["channel"]["id"]
formatted_message = f"""{message}
:star: _Powered by <https://functions.zapier.com | Zapier Functions>_ :star:
"""
# TODO: Type CNTRL + Space to select your account id
zapier.action.slack.channel_message(
account_id=,
params={
"channel":channel_id, # Channel
"text": formatted_message, # Message Text
"as_bot":"yes", # Send as a bot? | Valid inputs: "no", "yes"
"username":"JiraFairy", # Bot Name
"icon":":jira-fairy:", # Bot Icon
# "add_edit_link":"", # Include a link to this Zap? | Valid inputs: "no", "yes"
# "image_url":"", # Attach Image by URL
# "unfurl":"", # Auto-Expand Links? | Valid inputs: "no", "yes"
# "link_names":"", # Link Usernames and Channel Names? | Valid inputs: "no", "yes"
# "post_at":"", # Schedule At
# "file":"", # File
"thread_ts":thread_ts, # Thread
# "reply_broadcast":"", # Send Channel Message? | Valid inputs: "no", "yes"
},
type_of="write",
)
# Get the thread for the Slack trigger message and put it into a format consumable by OpenAI
def create_conversation_for_openai():
message = get_message()
# TODO: Type CNTRL + Space to select your account id
slack_thread_response = zapier.action.slack._zap_raw_request(
account_id=,
params={
# "raw_request_user_info":"", # Raw Request User Info
"method":"GET", # HTTP Method | Valid inputs: "PATCH", "PUT", "POST", "GET", "DELETE"
"url":"https://slack.com/api/conversations.replies", # URL
"querystring": {
"channel": message["channel"]["id"],
"ts": message["ts"],
}, # Query String Parameters
# "header_info":"", # Headers
# "headers":"", # Additional Request Headers
# "body":"", # Body
# "api_docs_info":"", # Api Docs Info
},
type_of="write",
)
body = slack_thread_response[0]["response"]["body"]
json_body = json.loads(body)
messages = json_body["messages"]
# sent to OpenAI as the conversation
conversation = []
# Loop through the messages and get the user's real name for each message
for m in messages:
if m.get("user") is not None:
# TODO: Type CNTRL + Space to select your account id
user_response = zapier.action.slack.user_by_id(
account_id=,
params={
"id":m.get("user"), # ID
# "raw":"", # Return Raw Results? | Valid inputs: "false", "true"
# "_zap_search_success_on_miss":"", # Should this step be considered a "success" when nothing is found? | Valid inputs: "true", "false"
},
type_of="search",
)
user_name = "unknown"
if user_response[0] is not None:
user_name = user_response[0].get("real_name", "unknown")
# add to the conversation, which will be sent to OpenAI
conversation.append({"user": user_name, "message": m.get("text")})
return conversation
def create_openai_completion(conversation, ticket_types):
formatted_ticket_types = " | ".join(string_ticket_types)
english_ticket_types = " or ".join(string_ticket_types)
prompt = """The following is a Slack conversation between employees of Zapier.
Create a Jira ticket to solve the problem identified by this conversation.
List out any acceptance criteria that may be mentioned in the conversation.
Do not use any pronouns in your response to refer to people other than "they", "them", or "their".
The response should include an "issueType" that is {english_ticket_types}.
The response should be in a JSON object shaped like the following:
{ "summary": string, "description": string, "issueType": {formatted_ticket_types} }
"""
openai_response = openai.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{
"role": "user",
"content": prompt},
{
"role": "user",
"content": json.dumps(conversation)
}]
)
openai_message_content = json.loads(openai_response.choices[0].message.content.strip())
print(openai_message_content)
issue_type = openai_message_content.get("issueType")
summary = openai_message_content.get("summary")
description = openai_message_content.get("description")
if issue_type not in ticket_types:
issue_type = ticket_types[0]
type_map = {
"Task": "10002",
"Bug": "10004",
"Story": "10001"
}
jira_description = description + f"""
This ticket was generated by {user_real_name} via OpenAI based on this Slack thread: {slack_thread}.
"""
return {
"summary": summary,
"description": jira_description,
"issue_type_code": type_map[issue_type],
"issue_type": issue_type
}
try:
trigger_message = get_message()
# # Variables that are used throughout the rest of the function
trigger_user = zapier.trigger_output["user"]
now = datetime.datetime.now()
formatted_date = now.strftime("%m/%d/%y")
channel_id = trigger_message["channel"]["id"]
thread_ts = trigger_message["ts"]
channel = trigger_message["channel"]["name"]
slack_thread = trigger_message["permalink"]
user_real_name = trigger_user["real_name"]
user_email = trigger_user["profile"]["email"]
string_ticket_types = ["Task", "Bug", "Story"]
conversation = create_conversation_for_openai()
print("Conversation sent to OpenAI: ", conversation)
openai_completion = create_openai_completion(conversation, string_ticket_types)
print("OpenAI completion:", openai_completion)
issue_type = openai_completion["issue_type"]
issue_type_code = openai_completion["issue_type_code"]
description = openai_completion["description"]
summary = openai_completion["summary"]
# TODO: Type CNTRL + Space to select your account id and project
jira_create_response = zapier.action.jira_software_cloud.create_issue(
account_id=,
params={
"project":, # Project
"issuetype": issue_type_code, # Issue Type
# "info_actions":"", # Info Actions
# "info":"", # Info
# "user::assignee":, # Assignee
#"array::components":, # Components
# "any::customfield_10008":, # Epic Link
# "date::customfield_10051":"", # Start date
# "string::customfield_10275::doc":"", # Zendesk Ticket IDs
# "option::customfield_10346":"", # Work Type | Valid inputs: "10585", "10586", "11646"
"string::description":description,
# "date::duedate":"", # Due date
# "array::fixVersions":[], # Version
"array::labels":["openai-generated"], # Labels
# "issuelink::parent":, # Parent
# "priority::priority":"", # Priority | Valid inputs: "1", "2", "3", "4", "5", "10000"
"string::summary":summary, # Summary
},
type_of="write"
)
if jira_create_response is None:
raise RuntimeError("Something went wrong when creating a Jira issue. There may be a mistake in the access control table.")
print("JIRA_CREATE_RESPONSE: ", jira_create_response)
ticket_number = jira_create_response[0]["key"]
message_text = f""":jira: A {issue_type} ticket <https://zapierorg.atlassian.net/browse/{ticket_number} |
{ticket_number}> was just created based on the contents of this conversation."""
send_slack_message(message_text)
except Exception as e:
error_message = str(e)
print(error_message)
trigger_message = get_message()
channel_id = trigger_message["channel"]["id"]
thread_link = trigger_message["permalink"]
slack_message = f"Hmmm...something went wrong when I tried to create a Jira ticket just now. Here's the error: {error_message}"
send_slack_message(slack_message)