티스토리 뷰
개요
Slack 에서 다른 timezone 의 팀원과 대화를 나누는 경우,
업무시간이 지났는데 말을 거는건 아닌가 싶어서 팀원의 현재시간이 궁금할때가 많았다.
이때 간단한 Slack Slash Command 로 해당 timezone 의 현재시간을 확인할 수 있도록 구현해 본다.
목표
1./tz [zoneName or Time] 입력을 받으면 정규식으로 변환해서 찾아내기
- 예를 들어 시드니의 현재 시간을 알고 싶으면 /tz syd 만 치면 되도록 한다.
2./tzn, /tzs 뉴욕시간, 서울시간 바로 나타내기
3. 월-금 업무시간인지 여부를 색깔로 표시하기
- 국가별 공휴일과 근무시간까지 체크하는 건 너무 오버인듯 하여 월-금, 9 to 6 만 체크한다.
참고 링크
Timezone database name: https://www.wikiwand.com/en/List_of_tz_database_time_zones
GitHub 구현코드 링크: https://github.com/nicewook/slack-timezone-current-time
* 기존에 구현했던 Slack Slash Command - 영한 번역
: 대부분의 내용은 아래 링크와 중복되는 부분이 있어서, 가능한 개념 위주로 정리하려 함
https://jusths.tistory.com/136
https://jusths.tistory.com/137
https://jusths.tistory.com/138
구현 개념도
1) https://api.slack.com/apps/new 에서 slack slash command 를 만들어준다.
- 원하는 명령어와, 명령이 실행되었을때에 이를 처리해줄 HTTP Server 위치를 설정해준다.
- 이렇게 만든 Slack App 은 명령이 실행되면 HTTP Request 를 생성해서, 설정해준 HTTP Server 로 보내고, 또 그 결과를 돌려받는다.
2) 생성이 완료되었으며 slack Workspace에 install 해준다.
- 1) 에서 만든 Slack APP 이 설치되었으므로
- Workspace 에서 명령이 실행되면 HTTP Request 가 지정한 HTTP Server 로 날아가게 된다.
3) HTTP Server 를 구현하고 돌려놓는다.
- 우선은 Local PC 에도 동작하도록 하지만 이후 구글의 Cloud function 을 사용한다.
- 수신한 Slack 의 HTTP request 를 처리하여 그 결과를 Slack App에게 response 한다.
Slack Slash Command 를 만들어보자.
자세한 사항은 링크를 참고한다 https://jusths.tistory.com/136
1) App Name 을 TimeZoneCurrentTime 으로 정하고 Slack Slash Command 3개를 만들었다.
- https://api.slack.com/apps/new 에서 만들 수 있다.
- /tz: 뒤에 timezone name 을 넣으면 해당 timezone 의 현재시간을 회신해준다.
- /tzn: 협업 엔지니어는 현재 뉴저지에 있으며 timezone 은 "America/New_York" 이다.
- /tzs: 나의 현재 위치는 한국이므로 timezone "Asia/Seoul" 의 현재시간을 리턴해준다.
2) Command 가 실행되었을때에 HTTP Request 를 보낼 HTTP Server 의 Request URL 을 설정해준다.
- serveo.net 이라는 사이트의 포트포워딩 서비스를 이용하면, 개발중인 로컬 PC 를 사용할 수 있다.
- $ssh -o ServerAliveInterval=60 -R 80:localhost:8080 serveo.net 라고만 치면 된다.
- 이때 자동 할당되는 url 을 Request URL 로 설정하면 된다.
- xxx.serveo.net 이라고 생성되는데 각각의 Slack Slash Command 에 대해서 endpoint 를 설정해주면 된다.
예를 들어 alpha.serveo.net 이라고 생성되었다면 - /tz 의 경우: alpha.serveo.net/tz - /tzn 의 경우: alpha.serveo.net/tzn - /tns 의 경우: alpha.serveo.net/tzs |
3) 원하는 Slack Workspace에 생성한 App 을 install 하면 Slack 에서 HTTP Request 를 보낼 준비는 끝이다.
- Workspace에 가 없다면 하나 만들어두면 된다.
4) 마지막으로 App 의 Signing Secret 을 메모해두자.
- Slack 이 App 을 통해 HTTP Request 를 보낼때에 이 Signing Secret 으로 (말그대로) 싸인을 한다.
- 우리가 만드는 HTTP Server 는 이 정보를 가지고 실제 우리의 Slack App 이 보낸 메시지가 맞는지 검증한다.
로컬에서 동작할 HTTP Server 를 만들어보자.
자세한 사항은 링크를 참고한다 https://jusths.tistory.com/136
실제 구현은 GitHub 을 참고한다 https://github.com/nicewook/slack-timezone-current-time
환경변수 설정
환경변수 SLACK_SIGNING_SECRET 에 위에서 메모해둔 App 의 Signing Secret 을 설정해준다.
- 윈도우라면 $set SLACK_SIGNING_SECRET=<Signing Secret of your Slack App> 라고 해주거나,
- 아예 윈도우 설정에서 환경변수로 설정할 수 있겠다.
- 설정된 값은$set SLACK_SIGNING_SECRET 으로 확인할 수 있다.
verifySlackSignature()
timezone-calc.go 의 verify 관련 부분부터 보자
Slack App 에서 생성한 HTTP Request 는 signature 를 가지고 있는데
SLACK_SIGNING_SECRET 을 이용하면 우리의 Slack App 에서 보내온 것인지를 검증할 수 있다.
자세한 설명은 링크를 참고하고 ( https://jusths.tistory.com/136 ) 이와 관련한 함수들은 아래와 같다.
init() verifySlackSignature() checkMAC() abs64() |
Web Server 와 Mux
main.go 를 보자
Golang 의 유명한 HTTP Router 로는 gorilla/mux 또는 httprouter 등이 있는데
어짜피 우리 구현은 단순하므로 Standard library 인 net/http 를 이용하도록 한다.
- Golang 을 쓰다보니 큰 무리가 없으면 순정을 사용하는게 좋다고 느.낀.다. (근거없음)
|
별 내용이 없다.
1) http.NewServerMux() 로 핸들러를 생성한 다음 2) /tz, /tzn, /tzs 각각의 endpoint 로 들어오는 HTTP request 에 대해 - 각각의 함수가 handle 하도록 설정하는 것이 전부이다.
3) 그리고 http.ListenAndServer() 를 돌려서 수신 준비 완료
*참고 링크: https://gist.github.com/reagent/043da4661d2984e9ecb1ccb5343bf438 |
|
참고로, go.mod 는 자동 생성한 다음 왼쪽과 같이 replace 를 먹여서 api 패키지의 상대 주소를 가리키게 하였다. |
Timezone Database Name
|
api 폴더의 timezone-name.go 파일에 Timezone Database Name 정보를 미리 넣어두었다.
데이터는 여기에서 추출하였다. - https://www.wikiwand.com/en/List_of_tz_database_time_zones
이 문자열을 Golang 의 time.LoadLocation() 함수에 넣어주면 *Location 타입의 리턴값을 얻을 수 있고, 이것을 Time 의 리시버인 In() 함수에 넣어주면 해당 Timezone 의 시간으로 변환해준다.
|
Timezone Current Time
이제 가장 핵심인 원하는 Timezone 의 현재시간을 얻어내는 방법을 알아보자.
timezone-calc.go 에서 /tz 을 핸들링하는 부분만 보자.
- /tzn, /tzs 는 더욱 간결하다.
|
1) verifySlackSignature()
- 우리의 Slack App에서 보내온 HTTP Request 인지를 verify 한다.
2) slack.SlashCommandParse()
- github.com/nlopes/slack 패키지를 이용하여 - Slack 이 보내온 메시지를 parsing 한다. - 우리에게 필요한 것은 s.Text 이다. 사용자가 원하는 timezone 정보이다.
3) Timezone database name 얻기
- 우리가 가진 데이터인 timezoneNameArray 의 값들이 - Slack App 이 보내온 s.Text 를 포함하고 있는지를 regexpMatchString() 으로 찾아내어 - 이때 ToLower() 를 이용하여 대소문자를 무시하고 찾도록 해준다. - 우리가 만든 makeResponse() 를 이용하여 양식에 맞춰 Timezone 의 Current time 을 리턴하도록 한다. - regexp 를 만족하는 Timezone Database Name 이 여럿이면 계속 이어붙이도록 한다.
4) Response
- Slack App 에 회신할 response 를 보내느 부분이다. - 만약 만족하는 timezone 이 하나도 없을 경우의 처리도 구현하고 - &slack.Msg 에 응답을 작성한 다음, json.Marshal() 로 직렬화하여 보내면 된다. |
|
* makeResponse() 도 checkTime() 도 네이밍에 너무 성의가 없는것 같긴 하다.
1) time.LoadLocation() 으로 *Location 타입을 loc에 리턴 받으면
2) time.Now().In(loc) 은 현재시간을 loc 의 시간으로 바꿔준다.
3) 그리고 checkTime() 함수를 통해 업무시간인지를 확인한다. - 월-금, 9 to 6 인지의 체크
4) 업무시간에 따라 response message 의 내용을 다르게 구성하고 5) time.Time 의 리시버 함수인 Format() 함수를 이용하여 포맷을 다듬는다. |
|
checkTime() 은 별 것 없다.
- time.Time 의 Weekday(), Hour() 리시버 함수를 이용하여 - 월 - 금, 9 to 6 인지를 확인하여 bool 값을 회신해준다.
|
구현을 확인하기
1) $ssh -o ServerAliveInterval=60 -R 80:localhost:8080 serveo.net 가 실행된 상황에서
- Local PC 의 Port Forwarding 이다.
2) go run main.go 로 Http Server 를 구동시킨다.
3) Slack App 이 install 된 Workspace 에서 Slack Slash Command 를 실행해본다.
|
각각 /tzn, /tzs 가 실행된 결과이다 |
|
/tz syd 를 실행한 결과이다
- "Australia/Sydney" 를 찾아낸 것이 보인다. |
|
/tz mos 를 실행한 결과이다
- mos 를 포함하는 두 시간대의 현재시간이 출력된다. |
To be Continued on "Slack Slash Command - timezone current time 2/2"
다음에는 간략히 Google Cloud Functions 에 올려보겠다.
Google Cloud Functions 의 경우 endpoint 하나당 하나의 Cloud Function 을 실행해야 하는 부분이 마음에 안들어서
Heroku 에 올리고, 겸사겸사 Travis CI 까지 복습할까 했지만 (toy project 로는) 일이 너무 커지고 곁가지로 빠지는 것 같고,
Heroku 가 무료 사용인 경우 일정시간 sleep 에 빠지는 것이 마음에 들지 않아 Cloud functions 를 선택하였다.
→ 개인적으로 작은 Workspace 에서 그리 자주 쓰지 않는 Slack app 을 대응해주는 경우라면 비용은 거의 들지 않는다.
'golang' 카테고리의 다른 글
Go Slice Tricks (0) | 2019.12.27 |
---|---|
Slack Slash Command - timezone current time 2/2 (0) | 2019.09.19 |
xid: golang GUID 생성 package 둘러보기 (0) | 2019.08.16 |
Go runtime AND goroutine (0) | 2019.07.23 |
Golang 의 동시성을 이용한 소수 찾기 (0) | 2019.07.22 |
- Total
- Today
- Yesterday
- 오블완
- 2023
- 독서후기
- Shortcut
- 제이펍
- notion
- golang
- strange
- 잡학툰
- Bug
- 영화
- 체호프
- 티스토리챌린지
- solid
- bun
- API
- github
- ChatGPT
- OpenAI
- Gin
- folklore
- intellij
- websocket
- clean agile
- 인텔리제이
- 클린 애자일
- 독서
- agile
- 노션
- go
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |