Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update sample code and README #11

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .env.sample

This file was deleted.

79 changes: 51 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,74 @@
# Bolt for JavaScript Automation Template App
# Bolt for JavaScript Custom Function Template

This is a generic Bolt for JavaScript template app used to build out Slack automations.
This is a Bolt for JavaScript template app used to build custom functions in [Workflow Builder](https://api.slack.com/start#workflow-builder).

Before getting started, make sure you have a development workspace where you have permissions to install apps. If you don’t have one setup, go ahead and [create one](https://slack.com/create).
## Installation
## Setup

#### Create a Slack App
1. Open [https://api.slack.com/apps/new](https://api.slack.com/apps/new) and choose "From an app manifest"
2. Choose the workspace you want to install the application to
3. Copy the contents of [manifest.json](./manifest.json) into the text box that says `*Paste your manifest code here*` (within the JSON tab) and click *Next*
4. Review the configuration and click *Create*
5. Click *Install to Workspace* and *Allow* on the screen that follows. You'll then be redirected to the App Configuration dashboard.
Before getting started, first make sure you have a development workspace where
you have permission to install apps. **Please note that the features in this
project require that the workspace be part of
[a Slack paid plan](https://slack.com/pricing).**

#### Environment Variables
Before you can run the app, you'll need to store some environment variables.
### Install the Slack CLI

1. Rename `.env.sample` to `.env`
2. Open your apps configuration page from [this list](https://api.slack.com/apps), click *OAuth & Permissions* in the left hand menu, then copy the *Bot User OAuth Token* into your `.env` file under `SLACK_BOT_TOKEN`
misscoded marked this conversation as resolved.
Show resolved Hide resolved
3. Click *Basic Information* from the left hand menu and follow the steps in the *App-Level Tokens* section to create an app-level token with the `connections:write` scope. Copy that token into your `.env` as `SLACK_APP_TOKEN`.
To use this template, you need to install and configure the Slack CLI.
Step-by-step instructions can be found in our
[Quickstart Guide](https://api.slack.com/automation/quickstart).

### Clone the Template

Start by cloning this repository:

### Setup Your Local Project
```zsh
# Clone this project onto your machine
git clone https://github.com/slack-samples/bolt-js-automation-template.git
$ slack create my-app -t slack-samples/bolt-js-automation-template

# Change into the project directory
$ cd my-app
```

# Change into this project directory
cd bolt-js-automation-template
## Running Your Project Locally

zimeg marked this conversation as resolved.
Show resolved Hide resolved
# Install dependencies
npm install
While building your app, you can see your changes appear in your workspace in
real-time with `slack run`. You'll know an app is the development version if the
name has the string `(local)` appended.

# Run Bolt server
npm start
```zsh
# Run app locally
$ slack run

⚡️ Bolt app is running! ⚡️
```

#### Linting
To stop running locally, press `<CTRL> + C` to end the process.

### Linting
misscoded marked this conversation as resolved.
Show resolved Hide resolved
Run ESLint for code formatting and linting:

```zsh
# Run eslint for code formatting and linting
npm run lint
$ npm run lint
```

## Using Functions in Workflow Builder
With your server running, your function is now ready for use in [Workflow Builder](https://api.slack.com/start#workflow-builder)! Add it as a custom step in a new or existing workflow, then run the workflow while your app is running.

For more information on creating workflows and adding custom steps, read more [here](https://slack.com/help/articles/17542172840595-Create-a-new-workflow-in-Slack).

## Project Structure

misscoded marked this conversation as resolved.
Show resolved Hide resolved
### `.slack/`

Contains `apps.dev.json` and `config.json`, which include installation details for your project.

### `app.js`

`app.js` is the entry point for the application and is the file you'll run to start the server. This project aims to keep this file as thin as possible, primarily using it as a way to route inbound requests.

### `manifest.json`

`manifest.json` is a configuration for Slack apps. With a manifest, you can create an app with a pre-defined configuration, or adjust the configuration of an existing app.

### `app.js`
### `slack.json`

`app.js` is the entry point for the application and is the file you'll run to start the server. This project aims to keep this file as thin as possible, primarily using it as a way to route inbound requests.
Used by the Slack CLI to interact with the project's SDK dependencies. It contains
script hooks that are executed by the CLI and implemented by `@slack/cli-hooks`.
77 changes: 36 additions & 41 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,62 +9,57 @@
socketMode: true,
appToken: process.env.SLACK_APP_TOKEN,
logLevel: LogLevel.DEBUG,
// To opt-out of using the JIT token to make `client` calls in
// function-related callbacks, set attachFunctionToken to false.
// attachFunctionToken: false,
});

/** Sample Function Listener */
app.function('sample_function', async ({ inputs, complete, fail }) => {
app.function('sample_function', async ({ client, inputs, fail }) => {
try {
const { sample_input } = inputs;
const { user_id } = inputs;

// Option 1: Complete the function after business logic is run
complete({ outputs: { sample_output: sample_input } });

// Option 2: Use interactivity (e.g. sending a button) to
// complete the function only after a user takes action.
// To use, add `client` to the callback arguments above.
// await client.chat.postMessage({
// channel: 'YOUR-CHANNEL-ID-HERE',
// blocks: [
// {
// type: 'section',
// text: {
// type: 'mrkdwn',
// text: 'Click the button to signal the function has completed!',
// },
// accessory: {
// type: 'button',
// text: {
// type: 'plain_text',
// text: 'Complete Function',
// },
// action_id: 'sample_button',
// },
// },
// ],
// });
await client.chat.postMessage({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it'd be good to check for ok: true with API calls, even if a bit more verbose...

channel: user_id,
blocks: [
{
type: 'section',
text: {
type: 'mrkdwn',
text: 'Click the button to signal the function has completed',
},
accessory: {
type: 'button',
text: {
type: 'plain_text',
text: 'Complete function',
},
action_id: 'sample_button',
},
},
],
});
} catch (error) {
console.error(error);

Check warning on line 40 in app.js

View workflow job for this annotation

GitHub Actions / build (18.x)

Unexpected console statement

Check warning on line 40 in app.js

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected console statement
fail({ error });
fail({ error: `Failed to handle a function request: ${error}` });
}
});

/** Sample Action Listener */
// For Option 2, commented out above
app.action('sample_button', async ({ ack, context, complete, fail }) => {
await ack();

// If related to a function_executed event, the context contains
// information about the function execution the action is related to.
const { functionExecutionId } = context;
app.action('sample_button', async ({ body, client, complete, fail }) => {
const { channel, message, interactivity: { interactor } } = body;

try {
complete({ function_execution_id: functionExecutionId });
// Functions should be marked as successfully completed using `complete` or
// as having failed using `fail`, else they'll remain in an 'In progress' state.
// Learn more at https://api.slack.com/automation/interactive-messages
await complete({ outputs: { user_id: interactor.id } });
misscoded marked this conversation as resolved.
Show resolved Hide resolved

await client.chat.update({
channel: channel.id,
ts: message.ts,
text: 'Function completed successfully!',
});
} catch (error) {
console.error(error);

Check warning on line 61 in app.js

View workflow job for this annotation

GitHub Actions / build (18.x)

Unexpected console statement

Check warning on line 61 in app.js

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected console statement
fail({ error });
fail({ error: `Failed to handle a function request: ${error}` });
}
});

Expand All @@ -72,8 +67,8 @@
(async () => {
try {
await app.start(process.env.PORT || 3000);
console.log('⚡️ Bolt app is running! ⚡️');

Check warning on line 70 in app.js

View workflow job for this annotation

GitHub Actions / build (18.x)

Unexpected console statement

Check warning on line 70 in app.js

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected console statement
} catch (error) {
console.error('Unable to start App', error);

Check warning on line 72 in app.js

View workflow job for this annotation

GitHub Actions / build (18.x)

Unexpected console statement

Check warning on line 72 in app.js

View workflow job for this annotation

GitHub Actions / build (20.x)

Unexpected console statement
}
})();
26 changes: 12 additions & 14 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"features": {
"app_home": {
"home_tab_enabled": true,
"messages_tab_enabled": false,
"messages_tab_enabled": true,
"messages_tab_read_only_enabled": true
},
"bot_user": {
Expand All @@ -21,9 +21,6 @@
}
},
"settings": {
"event_subscriptions": {
"bot_events": []
},
"interactivity": {
"is_enabled": true
},
Expand All @@ -36,21 +33,22 @@
"title": "Sample function",
"description": "Runs sample function",
"input_parameters": {
"sample_input": {
"type": "string",
"title": "Sample input text",
"description": "Sample input text to use in this step",
"user_id": {
"type": "slack#/types/user_id",
"title": "User",
"description": "Message recipient",
"is_required": true,
"name": "sample_input"
"hint": "Select a user in the workspace",
"name": "user_id"
}
},
"output_parameters": {
"sample_output": {
"type": "string",
"title": "Sample output text",
"description": "Sample output text to use in next step",
"user_id": {
"type": "slack#/types/user_id",
"title": "User",
"description": "User that completed the function",
"is_required": true,
"name": "sample_output"
"name": "user_id"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "bolt-js-template",
"name": "bolt-js-automation-template",
"version": "1.0.0",
"description": "A scaffold template for Slack apps",
"main": "app.js",
Expand Down