AWS Lambda는 HTTPS 끝에서부터 실행할 수 있기 때문에 슬랙봇을 만들어 봅니다

개시하다

vercel부터 디자인slack해서 활용하는 서비스를 어떻게 할지 고민입니다.vercel의 depro에 WebHook가 준비되어 있어서 그 URL만 찼어요.
가장 간단한 것은 slack의 사선 명령을 사용하는 것이다.다만, 누구나 사선 명령을 수행할 수 있고 누가 집행했는지 알 수 없기 때문에 피해야 한다.
거기서만 할 수 있을 것 같아slack bot.다만, 그렇기 때문에 heroku 등지에 서버를 만드는 것도 싫잖아~ 람바다 말이야~그런데 람바다면 API Gateway + Lambda 구성인가요 허리가 무겁군요~ 고민하고 있어요.
바로 이때!!
'AWS Lambda는 HTTPS 끝에서부터 실행할 수 있다'는 뉴스가 갑자기 나왔다.
좋아!Lambda로 오세요!!그렇게 생각해요.
!
이 글은 2022/4시의 실시 방법이다.Lambda는 node입니다.js의 14계로 움직이고 있습니다.vercel의 디자인은 부차적인 것이고, 주로 AWS Lambda 이동slack bot이기 때문에 만들고 싶은 사람slack bot과 만지고 싶은 사람AWS Lambda은 꼭 도전해 보세요.
(slack bot 이후 bot으로 기재)
제작된bot은 다음과 같은 이미지입니다.

GiitHub에 설치됩니다.
https://github.com/fukurose/vercel-deploy-slack-bot-on-lambda
!console.log를 사용하면 Lambda가 CloudWatch 로그에 기록됩니다.잘 작동하지 않을 경우 console.log 디버깅을 사용하세요.

HTTPS 끝에서 실행 가능한 Lambda 만들기


어쨌든 먼저 준비하세요Lambda.
AWS의 콘솔에 들어가서 제작Lambda하세요.만들 때 자세히 설정에서 유효성 함수 URL을 선택하고 NONE을 선택합니다.

만들면 index.js의 이름이 index.mjs로 바뀝니다.이렇게 하면 Lambda에서 ES 모듈을 사용할 수 있습니다.
그리고 index.mjs의 내용을 다시 써서 디자인하세요.
index.mjs
export async function handler(event) {
  const response = {
    statusCode: 200,
    body: JSON.stringify("Hello from Lambda!"),
  };
  return response;
}
디버깅이 완료되면 [함수 개요] 막대 오른쪽 아래에 있는 함수 URL 링크를 클릭하십시오."Hello from Lambda!"가 나타나면 OK입니다.

준비bot


그럼 준비해 드릴게요bot.액세스api slack, 새 App(bot)
제작되면'이벤트 서브스크립트'Event부터 활성화Request URL하고, Lambda에 HTTPS 엔드포인트 URLslack을 넣습니다.
그리하여
Your request URL didn’t respond with the correct challenge value. Update your URL to receive a new request and value.
나는 이런 정보를 표시할 것이라고 생각한다.
시행된 검사slack를 통과하지 못했기 때문이다.index.mjs 입력한 URL에 challeenge 값을 포함하는 요청을 버립니다.받은 사람은 이 challeenge 값을 응답에 그대로 답장해야 합니다. 이로써 슬랙이 정확한 URL임을 검증할 수 있습니다.
그럼 Event Subscriptions의 가격을 청산으로 변경하겠습니다.
index.mjs
export async function handler(event) {
  const body = JSON.parse(event.body);
  let responseBody = "Hello from Lambda!";
  // bodyに challenge がある場合は、それをそのまま返す
  if (body.challenge) {
    responseBody = {
      challenge: body.challenge,
    };
  }

  const response = {
    statusCode: 200,
    body: JSON.stringify(responseBody),
  };
  return response;
}
디버그 후 URL 확인bot을 다시 시도하십시오.이번엔 잘 될 거예요.
그럼 bot 설정을 실시해 봅시다.
우선 Subscribe to bot events 멤버 면을 만들었을 때 반응이 있었으면 해서 app_mentions에 추가bot보존을 했다.

이어'앱 홈'에서 설정Display NameScopes.
이어 OAuth & Permissions에서 chat:write에 대한 권한bot을 부여한다.
또'오옥스 앤 퍼미스션스'에는'봇 유저 오옥스 톡'이 있어 수치를 조절해야 한다.
이렇게 완성!!
'인스타 앱 투 유어 팀'install에서 만들자.
하지만 이때 slackbot말을 걸어도 아무런 반응이 없었다.람다한테 답장 주세요.

Bot 이동

bot에 반응을 일으키기 위해서는 http의post처리가 필요하기 때문에 먼저 제작http.mjs합니다.
http.mjs
import https from "https";

export const postRequest = async (url, headers, message) => {
  const options = { method: "POST", headers: headers };

  return new Promise((resolve, reject) => {
    let req = https
      .request(url, options, (res) => {
        res.on("end", () => {
          console.log("completed postRequest");
          resolve(res.statusCode);
        });
      })
      .on("error", (e) => {
        console.log("error postRequest:" + e.message);
        reject(e);
      });
    req.write(message);
    req.end();
  });
};
그럼 bot로 불리면 index.mjs 반응을 바꿔주세요.
index.mjs
import { postRequest } from "./http.mjs";

export async function handler(event) {
  const body = JSON.parse(event.body);
  let responseBody = "Hello from Lambda!";
  // bodyに challenge がある場合は、それをそのまま返す
  if (body.challenge) {
    responseBody = {
      challenge: body.challenge,
    };
  }

  if (body.event.type == "app_mention") {
    const headers = {
      "Content-Type": "application/json",
      Authorization: "Bearer " + process.env["SLACK_BOT_USER_ACCESS_TOKEN"],
    };

    const data = {
      channel: body.event.channel,
      text: responseBody,
    };

    await postRequest(
      process.env["SLACK_POST_MESSAGE_URL"],
      headers,
      JSON.stringify(data)
    );
  }

  const response = {
    statusCode: 200,
    body: JSON.stringify(responseBody),
  };
  return response;
}
일부 정보는 환경 변수에 저장되어 있음을 알 수 있습니다.Lambda 설정→환경 변수에서 다음을 설정하십시오.
SLACK_BOT_USER_ACCESS_TOKEN: Bot User OAuth Token の値SLACK_POST_MESSAGE_URL: https://slack.com/api/chat.postMessage여기서 depro를 진행하고 slack부터 다시 bot말을 걸어보세요.slack위에 Hello from Lambda!답장이 있으면 성공입니다.

Interactive Message

bot 대답할 수 있으니 계속 대화하세요.slackbot 설정 화면에서 "Interactivity & Shortcuts"를 선택하여 Interactivity를 활성화합니다.URL 입력 막대가 표시되므로 Lambda의 끝점 URL을 입력합니다.
다음bot 답장 내용도 짧은 문장이 아닌 버튼 등 동작을 포함하는 정보로 바뀐다.이번에vercel 디자인용이라 다음과 같이 설정했습니다.
https://github.com/fukurose/vercel-deploy-slack-bot-on-lambda/blob/main/slack.mjs
자신의 정보를 만들고 싶은 사람은 슬랙Block Kit Builder을 추천합니다.
그러면 네모난 상자로 구성된 정보를 되돌려줍니다.
index.mjs
import { blocks } from "./slack.mjs";

...

    const data = {
      channel: body.event.channel,
      // ここを text から blocks に変更
      blocks: blocks,
    };

...
이렇게 하면 버튼이 있는 정보bot가 답장합니다.하지만 지금은 버튼을 눌러도 아무 일도 일어나지 않기 때문에 버튼을 눌렀을 때 상응하는 대응을 한다.
버튼을 눌렀을 때의 요청content-typex-www-form-urlencoded입니다.(이전에는 json여기서부터 설치가 복잡해지기 때문에 분리해서 처리하는 것이 가장 좋다.위에서 말한 바와 같이 content-typejsonx-www-form-urlencoded 두 가지가 있기 때문에 추가handleJsonhandleUrlEncoded입니다.
index.mjs
import { postRequest } from "./http.mjs";
import { blocks } from "./slack.mjs";

export async function handler(event) {
  const contentType = event.headers["content-type"];

  let responseBody = "Hello from Lambda!";
  
  //contentType により処理を分ける
  if (contentType == "application/json") {
    responseBody = await handleJSON(event.body);
  } else if (contentType == "application/x-www-form-urlencoded") {
    responseBody = await handleUrlEncoded(event.body);
  }

  const response = {
    statusCode: 200,
    body: JSON.stringify(responseBody),
  };
  return response;
}

const handleUrlEncoded = async (requestBody) => {
  // 後で実装する
  console.log(requestBody);
};

const handleJSON = async (requestBody) => {
  const body = JSON.parse(requestBody);

  if (body.challenge) {
    const responseBody = {
      challenge: body.challenge,
    };
    return responseBody;
  }

  if (body.event.type == "app_mention") {
    const headers = {
      "Content-Type": "application/json",
      Authorization: "Bearer " + process.env["SLACK_BOT_USER_ACCESS_TOKEN"],
    };

    const data = {
      channel: body.event.channel,
      blocks: blocks,
    };

    await postRequest(
      process.env["SLACK_POST_MESSAGE_URL"],
      headers,
      JSON.stringify(data)
    );

    return "messageを送信しました";
  }
};
그럼 실시handleUrlEncoded하겠습니다.실제 데이터는 인코딩되었습니다base64. 먼저 인코딩한 다음querystring로 URL 조회 매개 변수 형식을 지웁니다.데이터를 체크 아웃하면handleAction 버튼을 누른 정보로 연결됩니다.
index
import querystring from "querystring";

...

const handleUrlEncoded = async (requestBody) => {
  const queryParameter = Buffer.from(requestBody, "base64").toString();
  const body = querystring.parse(queryParameter);
  const payload = JSON.parse(body.payload);
  console.log(JSON.stringify(payload));

  const headers = {
    "Content-Type": "application/json",
  };

  const result = handleAction(payload);
  const data = {
    text: result,
  };
  await postRequest(payload.response_url, headers, JSON.stringify(data));

  return result;
};

...

const handleAction = (payload) => {
  const user = payload.user.username;
  switch (payload.actions[0].action_id) {
    case "main":
      return `<@${user}> が本番環境をデプロイしました。`;
    case "staging":
      return `<@${user}> がステージング環境をデプロイしました。`;
    case "cancel":
      return "キャンセルしました。";
    default:
      return "よう分からんわ。";
  }
};
이렇게 버튼을 누르면 bot 반응이 나온다.지금까지 거의 완성되지 않았고 나머지는 handleAction 실시한 처리에만 썼다.
이번에 실시하고 싶은 처리는 vercel의 프로그램 설계이기 때문에 그것을 추가합니다.
index.mjs
const handleAction = (payload) => {
  // WebHook を Kick するだけなので、設定不要
  const headers = {};
  const data = "";

  const user = payload.user.username;
  switch (payload.actions[0].action_id) {
    case "main":
      postRequest(process.env["MAIN_WEBHOOK_URL"], headers, data);
      return `<@${user}> が本番環境をデプロイしました。`;
    case "staging":
      postRequest(process.env["STAGING_WEBHOOK_URL"], headers, data);
      return `<@${user}> がステージング環境をデプロイしました。`;
    case "cancel":
      return "キャンセルしました。";
    default:
      return "よう分からんわ。";
  }
};
내가 완성할게!!
수고하셨습니다.AWS Lambda 지원단점 덕분에 HTTPS 제작이 간단해졌어요.(단지 API Gateway는 필요 없음)
여러분도 다양한 bot 만들어서 같이 즐겨요!!

좋은 웹페이지 즐겨찾기