Skip to content

Instantly share code, notes, and snippets.

@one-data-cookie
Last active January 13, 2021 20:11
Show Gist options
  • Save one-data-cookie/6fb47a434d9bf29730beb74220231af2 to your computer and use it in GitHub Desktop.
Save one-data-cookie/6fb47a434d9bf29730beb74220231af2 to your computer and use it in GitHub Desktop.
function doPost(e) {
// get the parameters
var params = e.parameter
// run if command sends request
if (params.call == "command") {
// create payload
var trigger_id = params.trigger_id
var modal_payload = {
"trigger_id": trigger_id,
// create view itself
"view": {
"type": "modal",
"callback_id": "shopping_modal",
"title": {
"type": "plain_text",
"text": "Shopping Request"
},
"submit": {
"type": "plain_text",
"text": "Submit"
},
"close": {
"type": "plain_text",
"text": "Cancel"
},
"blocks": [
// build category block
{
"type": "input",
"block_id": "category",
"label": {
"type": "plain_text",
"text": "What to buy?"
},
"optional": false,
"element": {
"action_id": "single_select",
"type": "static_select",
"placeholder": {
"type": "plain_text",
"text": "Choose a category"
},
"options": [
{
"value": "food",
"text": {
"type": "plain_text",
"text": "Food"
}
},
{
"value": "stationary",
"text": {
"type": "plain_text",
"text": "Stationary"
}
},
{
"value": "other",
"text": {
"type": "plain_text",
"text": "Other"
}
}
]
}
},
// build items block
{
"type": "input",
"block_id": "items",
"label": {
"type": "plain_text",
"text": "What items?"
},
"optional": false,
"element": {
"action_id": "comment_box",
"type": "plain_text_input",
"multiline": true,
"placeholder": {
"type": "plain_text",
"text": "List what you need"
}
}
},
// build date block
{
"type": "input",
"block_id": "date",
"label": {
"type": "plain_text",
"text": "By when do you need it?"
},
"optional": true,
"element": {
"action_id": "date_picker",
"type": "datepicker"
}
},
// build comments block
{
"type": "input",
"block_id": "comment",
"label": {
"type": "plain_text",
"text": "Any comments?"
},
"optional": true,
"element": {
"action_id": "comment_box",
"type": "plain_text_input",
"multiline": true,
"placeholder": {
"type": "plain_text",
"text": "Provide extra details, if necessary"
}
}
}
]
}
}
// initiate modal in Slack
sendToSlack("https://slack.com/api/views.open", modal_payload)
}
// run when interaction sends request
else if (params.call == "interaction") {
var payload = JSON.parse(params.payload)
// run when sent modal and the right modal
if (payload.type == "view_submission" && payload.view.callback_id == "shopping_modal") {
// send results to #shopping app channel
var user_id = payload.user.id
var user_name = getUserName(user_id)
var date = new Date()
var date_string = Utilities.formatDate(date, "GMT", "yyyy-MM-dd")
var date_unix = Math.floor((date.getTime()/1000)).toString()
var view_vls = payload.view.state.values
var category = view_vls.category.single_select.selected_option.text.text
var items = view_vls.items.comment_box.value
var deadline = view_vls.date.date_picker.selected_date || "NA"
var comment = view_vls.comment.comment_box.value || "NA"
var ticket_info = {
"user_id": user_id,
"user_name": user_name,
"date": date_string,
"category": category,
"items": items,
"deadline": deadline,
"comment": comment
}
var ticket_info_str = JSON.stringify(ticket_info)
var result = {
"text": "A new request!",
"blocks": [
{
"type": "section",
"block_id": "text",
"text": {
"type": "mrkdwn",
"text": "You have a *new request*! :eyes:"
}
}
],
"attachments": [
{
"color": "#2469EC",
"fallback": "Shopping request",
"blocks": [
{
"type": "section",
"block_id": "category_items",
"fields": [
{
"type": "mrkdwn",
"text": "*Category*\n" + category
},
{
"type": "mrkdwn",
"text": "*Items*\n" + items
}
]
},
{
"type": "section",
"block_id": "deadline_comment",
"fields": [
{
"type": "mrkdwn",
"text": "*Deadline*\n" + deadline
},
{
"type": "mrkdwn",
"text": "*Comment*\n" + comment
}
]
},
{
"type": "context",
"block_id": "context",
"elements": [
{
"type": "mrkdwn",
"text": "Submitted by " + user_name + " | <!date^" + date_unix + "^{date_short_pretty} at {time}|" + date + ">"
}
]
}
]
},
{
"fallback": "Action buttons",
"blocks": [
{
"type": "actions",
"block_id": "action_buttons",
"elements": [
{
"type": "button",
"action_id": "approve_button",
"value": ticket_info_str,
"style": "primary",
"text": {
"type": "plain_text",
"text": "Approve"
}
},
{
"type": "button",
"action_id": "decline_button",
"value": ticket_info_str,
"style": "danger",
"text": {
"type": "plain_text",
"text": "Decline"
}
}
]
}
]
}
]
}
// send ticket to #shopping
sendToSlack("https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXXXX/xxxxxxxxxxxxxxxxxxxxxxxx", result)
// send notification to user
var msg = {
"channel": user_id,
"text": "Your shopping request was submitted.",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Your shopping request was *submitted* to <#CXXXXXXXXXX> channel. :pencil:"
}
}
]
}
sendToSlack("https://slack.com/api/chat.postMessage", msg)
}
// run when interaction with buttons happened
else if (payload.type == "block_actions") {
var response_user_id = payload.user.id
var response_user_name = getUserName(response_user_id)
var channel_id = payload.channel.id
var response_url = payload.response_url
var response_time = new Date()
var response_time_unix = Math.floor((response_time.getTime()/1000)).toString()
var ticket_blocks = payload.message.attachments[0].blocks
var ticket_ts = payload.message.ts
var action_id = payload.actions[0].action_id
// get ticket values
var ticket_info = JSON.parse(payload.actions[0].value)
var user_id = ticket_info.user_id
var user_name = getUserName(user_id)
var date = ticket_info.date
var category = ticket_info.category
var items = ticket_info.items
var deadline = ticket_info.deadline
var comment = ticket_info.comment
// get ticket permalink
var ticket_origin = {
"channel": channel_id,
"message_ts": ticket_ts
}
var ticket_permalink = getMsgUrl(ticket_origin)
// run when approved
if (action_id == "approve_button") {
// send info to sheet
var ticket_data = [user_name, date, category, items, deadline, comment]
var ss_id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
sendToSheet(ss_id, ticket_data)
// prepare result and message
var result = {
"channel": user_id,
"blocks": [
{
"type": "section",
"block_id": "text",
"text": {
"type": "mrkdwn",
"text": "This request was *approved*. :white_check_mark:"
}
}
],
"attachments": [
{
"color": "#36A54F",
"blocks": ticket_blocks
},
{
"blocks": [
{
"type": "context",
"block_id": "status",
"elements": [
{
"type": "mrkdwn",
"text": "Approved by " + response_user_name + " | <!date^" + response_time_unix + "^{date_short_pretty} at {time}|" + response_time + ">"
}
]
}
]
}
]
}
var msg = {
"channel": user_id,
"text": "Your shopping request was approved.",
"unfurl_links": true,
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<" + ticket_permalink + "|Your shopping request> was *approved*. :white_check_mark:"
}
}
]
}
}
// run when declined
else if (action_id == "decline_button") {
// prepare result and message
var result = {
"channel": response_user_id,
"blocks": [
{
"type": "section",
"block_id": "text",
"text": {
"type": "mrkdwn",
"text": "This request was *declined*. :x:"
}
}
],
"attachments": [
{
"color": "#E83436",
"blocks": ticket_blocks
},
{
"blocks": [
{
"type": "context",
"block_id": "status",
"elements": [
{
"type": "mrkdwn",
"text": "Declined by " + response_user_name + " | <!date^" + response_time_unix + "^{date_short_pretty} at {time}|" + response_time + ">"
}
]
}
]
}
]
}
var msg = {
"channel": response_user_id,
"text": "Your shopping request was declined.",
"unfurl_links": true,
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "<" + ticket_permalink + "|Your shopping request> was *declined*. :x:"
}
}
]
}
}
// update the message with appropriate result
sendToSlack(response_url, result)
// send notification to the user
sendToSlack("https://slack.com/api/chat.postMessage", msg)
}
}
// respond with basic acknowledgment response
return ContentService.createTextOutput("")
}
// function that sends data to Slack
function sendToSlack(url, payload) {
var options = {
"method": "post",
"contentType": "application/json",
"payload": JSON.stringify(payload),
"headers": {"Authorization": "Bearer xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"}
}
return UrlFetchApp.fetch(url, options)
}
// function that gets user name from Slack
function getUserName(user_id) {
var options = {
"method": "get",
"contentType": "application/x-www-form-urlencoded",
"payload": {
"user": user_id
},
"headers": {"Authorization": "Bearer xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"}
}
var resp = UrlFetchApp.fetch("https://slack.com/api/users.info", options)
return JSON.parse(resp).user.profile.display_name_normalized
}
// function that gets URL of message from Slack
function getMsgUrl(payload) {
var options = {
"method": "get",
"contentType": "application/x-www-form-urlencoded",
"payload": payload,
"headers": {"Authorization": "Bearer xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"}
}
var resp = UrlFetchApp.fetch("https://slack.com/api/chat.getPermalink", options)
return JSON.parse(resp).permalink
}
// function that writes data to Sheets
function sendToSheet(spreadsheet_id, data) {
var ss = SpreadsheetApp.openById(spreadsheet_id)
var sheet = ss.getSheetByName("Requests")
var last_row = sheet.getLastRow();
return sheet.getRange(last_row + 1, 1, 1, data.length).setValues([data])
}
@one-data-cookie
Copy link
Author

Frankly, I don't have any experience with this as I've never needed it myself.

From the top of my head, I think you can only let Google Apps Script wait through Utilities.sleep(milliseconds); for up to a few minutes. Then, the script timeouts and stops. Should you need the wait to be longer, I think you'll need to setup another script, probably with a time-based trigger as you mention.

Just an idea – maybe you could store the modal submissions with its timestamp in a Google Sheet. They, you'd set up a separate script that would run each hour (as that's the most often you can do, I believe) and let it run the action you desire once required amount of time passed from the submission timestamp.

It's hardly the best that can be done, but it might work for you. If not, I'd suggest posting a question to Stackoverflow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment