노드로 슬랙봇을 만들어보았다. w/허키로
요구 사항
- 월요일 아침 10시 50분 마다 페어 매칭 공지
1-1. 현재 채널에 있는 구성원 목록 가져오기
1-2. 가져온 사람 수가 홀수면 한 조는 3인, 나머지은 2인으로 짝을 짓고, 짝수면 2인씩 짝짓는다.
1-3. 월요일 아침 10시 50분에 슬랙 채널에 공지한다. - 명령어 받아서 페어 명단 관리하기
2-1. 채널에 명령어 '/페어' 입력 시 금주의 페어 목록 출력
2-2. 채널에 명령어 '/제외 ooo' 입력 시 특정 인물 차주 페어 명단에서 제외 - 배포
slash commands로 명령어를 받아오기 위해서 아래와 같이 작성했다.
app.post('/', (req, res) => {
if(req.body.command.split('/')[1] === '페어') {
res.send(`금주의 페어는 ${pairList}입니다`)
} else if(req.body.command.split('/')[1] === '제외'){
excluded.push(req.body.text);
res.end(`${req.body.text}은/는 제외되었습니다`);
} else {
res.end('해당하는 명령어가 없습니다');
}
})라우팅을 /페어로 받아오는 줄 알고 한참 삽질을 하다가 해결...ㅠㅠ
또 하나 주의할 점은,
const bodyParser = require('body-parser');
app.use(bodyParser.json());이렇게 body-parser 모듈을 사용해야 req.body.command 안에 /페어를 파싱해줄 수 있다.
슬랙 채널에 메시지를 보내주는 로직 관련 코드는 아래와 같다.
const { WebClient, ErrorCode } = require('@slack/web-api');
const { scheduleJob } = require('node-schedule');
const schedule = require('node-schedule');
const token = process.env.SLACK_BOT_TOKEN;
const web = new WebClient(token);
const noticePair = async () => {
try {
const userList = await getUserList();
const pairList = await makePair(userList);
const result = await web.chat.postMessage({
channel: conversationId, text: `이번 주 페어 명단은 ${pairList}입니다.`
});
} catch (err) {
console.log(err)
}
}
schedule.scheduleJob('50 01 * * mon', noticePair);페어 매칭은 다음과 같이 명단이 담긴 배열을 섞어서, 앞에서부터 둘씩 pair 배열로 끊어 pairs 배열에 저장하고,
마지막에 3개 요소가 남았을 때 pair 배열에 담아 마찬가지로 pairs 배열에 넣고 반복문을 종료했다.
더 나은 코드가 충분히 있겠지만, 일단 빠르게 구현을 하고 싶었다.
const makePair = (usernames) => {
try {
const shuffle = (usernames) => {
const copyUsernames = usernames.slice();
return copyUsernames.sort(() => Math.random() - 0.5);
}
const shuffledUsernames = shuffle(usernames);
let pairs = [];
for(let i = 0; i < shuffledUsernames.length; i += 2) {
let pair = shuffledUsernames.slice(i, i + 2);
if(i === shuffledUsernames.length - 3) {
pair = shuffledUsernames.slice(-3);
pairs.push(pair);
break;
}
pairs.push(pair);
}
const pairsToJSON = JSON.stringify(pairs);
return pairsToJSON;
} catch (error) {
console.log(error);
}
};전체적으로 함수 모듈화에 나름 신경을 쓴다고 썼는데, 전역변수를 피하지 못했다.
in-memory로만 페어 명단을 관리하다보니, 서버가 예기치 않은 버그를 만나 재실행된다면, 기존에 /제외 명령어로 빼둔 유저 목록이 다시 리셋될 위험이 있다는 점도 마음에 걸린다.
redis를 붙여서 캐싱도 해보고 싶다.
일단, 슬랙봇 처음 만들어본 걸로 기쁘다.
배포 시 서버 시간이 9시간 이르기 때문에, scheduler에 인자로 전달하는 시간에서 -9를 해주었다.
파이프라인 만들어서 자동화도 해보고 싶다.
'JavaScript > Node.js' 카테고리의 다른 글
| node.js로 파일 확장자명에 따라 분류하기 (0) | 2022.02.03 |
|---|