Skip to content

Commit

Permalink
Merge pull request #18 from TUS-OSK/slack
Browse files Browse the repository at this point in the history
Slack
  • Loading branch information
ilim0t authored Jul 23, 2019
2 parents 5453141 + fab703b commit 2bd9beb
Show file tree
Hide file tree
Showing 10 changed files with 499 additions and 47 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,12 @@ typings/

# End of https://www.gitignore.io/api/node

# env dile
.envrc

# photo, video file
*.png
*.jpeg
*.jpg
hls/
*.m3u8
*.ts
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,11 @@ ngrok で得られる URL はは変動するので,[API Gateway](https://aws.a
│ └─ GET
├─ /photo-viewer
│ └─ GET
├─ /slack
│ └ /{path+}
│ ├─ GET
│ └─ POST
├─ /stream
│ ├─ GET
│ └ /{file+}
│ └─ GET
└─ /viewer
Expand All @@ -77,6 +80,19 @@ Bot User メニューにて Redirect URLs は
`https://[RESOURCE_ID].execute-api.[REGION].amazonaws.com/prod/oauth-redirect`のみに設定し,
Scopes に`identity.basic`を追加してください。

### Slack bot

[Slash Commands](https://api.slack.com/slash-commands)に従い slack api ページにて,
Command: `/bushitsu-photo`
Request URL: `https://[AWS_REST_API_ID].execute-api.[REGION].amazonaws.com/prod/slack/photo`
Escape channels, users, and links sent to your app を有効
に設定します。

### Slack interactive message

[Making messages interactive](https://api.slack.com/interactive-messages) に従い設定します。
Request URL は`https://[AWS_REST_API_ID].execute-api.[REGION].amazonaws.com/prod/slack/actions/`を設定してください。

### 環境変数

`NGROK_TOKEN`: Tunnel Authtoken, 無料プランでプランでも動作します
Expand All @@ -86,6 +102,13 @@ Scopes に`identity.basic`を追加してください。
`SLACK_CLIENT_ID`: Slack Apps の Client ID
`SLACK_CLIENT_SECRET`: Slack Apps の Client Secret

`SLACK_BOT_ACCESS_TOKEN`: Slack Apps の OAuth Access Token
`SLACK_SIGNING_SECRET`: Slack Apps の Signing Secret

`CONTACT_CHANNEL`: Slack でのメッセージにのせる問い合せ先の channel ID

> 参考: [Formatting text in messages](https://api.slack.com/messaging/composing/formatting#linking-channels)
`LIVE_PRIVATE_KEY`: live streaming に認証をかけるための key, 暗に用いるので頑強であれば何でも良い

`WORKSTATION_ID`: Slack の WorkSpace の ID
Expand All @@ -98,11 +121,19 @@ export AWS_REST_API_ID="h7c..."
export SLACK_CLIENT_ID="179..."
export SLACK_CLIENT_SECRET="38b..."
export SLACK_BOT_ACCESS_TOKEN="xoxb-3814..."
export SLACK_SIGNING_SECRET="fb36..."
export CONTACT_CHANNEL="JCP..."
export PRIVATE_KEY="presetprivatekey"
export WORKSTATION_ID="VOW38CP2D"
```

> `IS_MAC`, `DEBUG` この2つの変数で flag を立てることもできます
> `true`, `false`, `0`, `1` で指定可能です。
[direnv](https://direnv.net/)なら以上のように設定されているはずです。

## ffmpeg
Expand Down
21 changes: 17 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Server = require('./server');
const aws = require('./aws');
const Stream = require('./stream');
const { daemon } = require('./utils');
const slack = require('./slack');

const config = {
restApiId: process.env.AWS_REST_API_ID,
Expand All @@ -13,10 +14,13 @@ const config = {
ngrokToken: process.env.NGROK_TOKEN,
slackClientId: process.env.SLACK_CLIENT_ID,
slackClientSecret: process.env.SLACK_CLIENT_SECRET,
slackBotAccessToken: process.env.SLACK_BOT_ACCESS_TOKEN,
slackSigningSecret: process.env.SLACK_SIGNING_SECRET,
contactChannel: process.env.CONTACT_CHANNEL,
wsId: process.env.WORKSTATION_ID,
privateKey: process.env.PRIVATE_KEY,
debug: Boolean(process.env.DEBUG),
isMac: Boolean(process.env.IS_MAC),
debug: process.env.DEBUG && Boolean(JSON.parse(process.env.DEBUG)),
isMac: process.env.IS_MAC && Boolean(JSON.parse(process.env.IS_MAC)),
};

const liveServer = new RtmpServer(1935);
Expand All @@ -36,14 +40,13 @@ disk
console.log(`Please put HLS files in ${mountPath}`);
let input;
if (config.isMac) {
input = 'ffmpeg -f avfoundation -framerate 30 -re -i 0 -r 10';
input = 'ffmpeg -f avfoundation -re -i 0 -r 10';
} else {
input = 'ffmpeg -i /dev/video0';
}
daemon(
`${input} -vcodec libx264 -pix_fmt yuv420p -preset veryfast -tune zerolatency,stillimage,film -vb 2500k -vf "drawtext=text='%{localtime}':[email protected]:x=0:y=h-lh*1.2:fontsize=24" -f flv rtmp://localhost:${1935}/live/bushitsuchan`,
);

daemon(
`ffmpeg -i rtmp://localhost:1935/live/bushitsuchan -hls_flags delete_segments -g 40 -f hls ${mountPath}/output.m3u8`,
);
Expand All @@ -69,6 +72,16 @@ disk
config,
`rtmp://localhost:1935/live/${'bushitsuchan'}`,
);
server.app.use(
'/slack',
slack(
awsUrl,
config.contactChannel,
`rtmp://localhost:${1935}/live/bushitsuchan`,
config.slackBotAccessToken,
config.slackSigningSecret,
),
);
server.run(3000).then(() => console.log(`Express app listening on port ${3000}`));
})
.catch((e) => {
Expand Down
44 changes: 26 additions & 18 deletions aws.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,38 @@ const util = require('util');
const exec = util.promisify(childProcess.exec);

module.exports.run = async (config, url) => {
exec(`aws apigateway get-resources --rest-api-id ${config.restApiId}`)
.then((result) => {
const { stdout } = result;
return JSON.parse(stdout);
})
.then(resources => Promise.all(
resources.items.map((item) => {
let command = `aws apigateway put-integration --rest-api-id ${config.restApiId} --resource-id ${item.id} --http-method GET --type HTTP_PROXY --integration-http-method GET`;
command += ` --uri ${url}${item.path.replace(/{([^}+]+)\+}/, '{$1}')}`;
const isMatch = item.path.match(/{([^}+]+)\+}/);
const resources = await exec(
`aws apigateway get-resources --rest-api-id ${config.restApiId}`,
).then((result) => {
const { stdout } = result;
return JSON.parse(stdout);
});
const commands = [];

resources.items.forEach((resource) => {
if (!resource.resourceMethods) {
return;
}
Array.prototype.push.apply(
commands,
Object.keys(resource.resourceMethods).map((method) => {
let command = `aws apigateway put-integration --rest-api-id ${config.restApiId} --resource-id ${resource.id} --http-method ${method} --type HTTP_PROXY --integration-http-method ${method}`;
command += ` --uri ${url}${resource.path.replace(/{([^}+]+)\+}/, '{$1}')}`;
const isMatch = resource.path.match(/{([^}+]+)\+}/);
if (isMatch) {
command += ` --request-parameters integration.request.path.${
isMatch[1]
}=method.request.path.${isMatch[1]}`;
}
return exec(command);
return command;
}),
))
.then(() => {
exec(`aws apigateway create-deployment --rest-api-id ${config.restApiId} --stage-name prod`);
})
.catch((e) => {
console.error(e);
});
);
});
await Promise.all(commands.map(command => exec(command)));

await exec(
`aws apigateway create-deployment --rest-api-id ${config.restApiId} --stage-name prod`,
);

const region = await exec('aws configure get region').then((result) => {
const { stdout } = result;
Expand Down
104 changes: 104 additions & 0 deletions block_template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
[
{
"type": "image",
"title": {
"type": "plain_text",
"text": "部室の写真"
},
"image_url": "${photo_image}",
"alt_text": "部室の写真"
},
{
"type": "actions",
"block_id": "action_block",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "削除"
},
"value": "delete",
"action_id": "delete_button",
"style": "danger",
"confirm": {
"title": {
"type": "plain_text",
"text": "メッセージ削除"
},
"text": {
"type": "plain_text",
"text": "削除しますか?"
},
"confirm": {
"type": "plain_text",
"text": "削除実行"
},
"deny": {
"type": "plain_text",
"text": "キャンセル"
}
}
} /** ,
{
"type": "overflow",
"options": [
{
"text": {
"type": "plain_text",
"text": "slection1"
},
"value": "slection1"
},
{
"text": {
"type": "plain_text",
"text": "slection2"
},
"value": "slection2"
}
],
"action_id": "overflow"
} */
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "${expired-time}"
}
]
},
{
"type": "divider"
},

{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "📷 View photo with `/bushitsu-photo`"
}
]
},
{
"type": "context",
"elements": [
{
"type": "mrkdwn",
"text": "<${viewer-url}|WEB-配信動画版>"
},
{
"type": "mrkdwn",
"text": "<${photo-viewer-url}|WEB-画像版>"
},
{
"type": "mrkdwn",
"text": "*問い合せ*: <#${contact-channel}>"
}
]
}
]
Loading

0 comments on commit 2bd9beb

Please sign in to comment.