[Bash Script] REST API 사용하기 - 부제 : Bash Script로 밥대생 API를 활용하여 Slack으로 알림받기

2017-04-12 15:44:30

밥대생이라는 서비스를 작년 말쯤 처음 알았다.

카이스트 학생들이 만든 RESTful 한 API를 이용한 서비스인데 REST이기 때문에 여러 언어에서 필요한 메소드를 호출하여 원하는 정보를 얻을 수도 있다.

그 중 가장 접하기 쉬운 Linux Bash script 언어를 이용하여 발로 개발하여 대학교 식단 정보를 슬랙으로 받아보는 것을 구현하였는데, 해보면서 Rest API 사용법, Bash script 기본 등에 대해 알게 되어 그 내용을 조금 정리해보는 시간을 갖기로 함.

우선 RESTful API가 무엇인가?에 대해 다루려면 그 또한 내용이 많으니 위키피디아에서 참고(https://en.wikipedia.org/wiki/Representational_state_transfer)

http://www.restapitutorial.com/ : 여기서도 설명을 해주고 튜토리얼을 해볼 수 있음

< 사전 지식 >

리눅스 sh 실행 가능?

리눅스 패키지 설치 가능? (jq, cUrl 등)

Slack API - Incoming Webhook

cUrl ?

json ?

그리고 오늘의 주인공 중 하나인 밥대생의 API는 https://github.com/bablabs/bds-openapi 여기에서 확인가능하다.

RESTful API를 사용하려면 OAuth2.0 등을 이용하여 인증을 거쳐야하는데 밥대생에서는 이메일(openapi@bablabs.com)로 key 생성을 요청하도록 되어 있다.

키 발급을 기다리기 힘들면 키 값 대신 “DEBUG” 로 액세스 토큰을 받아서 테스트해볼 수 있다.

키 발급이 완료되었다면 액세스 토큰을 얻기 위해 AuthListApi 를 호출하면 되는데 처음해보는 사람은 어떻게 호출하면 되는지 감조차 안 올 수 있다. (내가 그랬다…)

밥대생과의 첫만남! AuthListApi를 호출해보자!! (Using Bash script)

※ Bash Script 를 만들고 사용하려면 vi, nano 등의 텍스트 편집기를 이용할 줄 알아야하고, .sh 파일에 실행 권한을 주는법과 실행방법 정도는 알아야 됨)

우선 getAccessToken.sh 라는 파일을 만들고 아래와 같이 작성하고 실행.

#!/bin/bash
#writer : Terry
curl -X GET --header "Content-type: application/json"          \
        https://bds.bablabs.com/openapi/v1/auths?key=<이메일로 발급받은 API Key 또는 DEBUG라고 입력>

(설명을 덧붙이면, https 로 시작하는 url 의 auths 이것이 호출주소가 되겠고 , key=xxxx 이 부분이 request parameter인데 아래 그림의 query 안에 들어가는 텍스트가 되어야 한다. Bash Script 가 아닌 다른 언어에서는 사용방법이 조금씩 다를 것이다.)

위 스크립트를 실행하면 아래와 같이 accesstoken이 발급된다. (위 그림의 response 부분과 일치함을 알 수 있다.)

accesstoken이 발급 되었으면 식단을 알고 싶은 대학교의 campus_id 를 찾자.

https://bds.bablabs.com/campuses 에 접속하여 학교이름으로 검색을 해보자

(서울대의 경우 spgIiBzSj0 이다.)

이제 getMenu.sh 라는 파일을 생성하고 bash script로 아래와 같이 코딩한다.

todayY=$(date +%y)
todayM=$(date +%m)
todayD=$(date +%d)

today=20$todayY-$todayM-$todayD

menu=$(curl -X GET --header "Content-type: application/json"       \
            --header "accesstoken: <발급받은 accesstoken 입력>" \
            --header "babsession: <아무문자나입력>"  \
    https://bds.bablabs.com/openapi/v1/campuses/spgIiBzSj0/stores?date=$today)

echo -en "$menu" > sample.json

실행하면 같은 디렉토리에 sample.json 이라는 파일이 생성되고 여기에 서울대학교의 오늘날짜 메뉴가 들어있는 것을 확인할 수 있다.

그러면 이제 이 메뉴를 내가 보기 편하도록 가공을 해줘야 하는데, 리눅스 상에서 여러 패키지가 있겠지만 대표적인 “jq” 라는 패키지를 설치하여 json을 parsing 한다.

menusSeoul0=$(cat sample.json | tr '\n' ' ' | jq '.stores[1].menus[0].description' | tr '\"' ' ')
menusSeoul1=$(cat sample.json | tr '\n' ' ' | jq '.stores[1].menus[1].description' | tr '\"' ' ')

의 형태로… 학교마다 json 객체 구조가 다를 수 있으니 상황에 맞게 parsing 을 해줘야함. 그리고 슬랙으로 쏘기 위해서 겹따옴표(“, double quote) 는 escape 해야하는데 tr 명령어로 텍스트 치환 수행

(※ json parsing 도 좀 더 깔끔하게 할 수 있을 것 같긴 한데 귀찮아서 일단 하드코딩 스타일로…)

만약 학생복지위원회 등 식단메뉴 등록을 하는 주체가 오늘의 메뉴를 등록하지 않았을 경우에 등록되지 않았음을 알려주는 메시지를 변수에 담기.

strNullMsg="식당에서 오늘의 메뉴를 올리지 않았어요."

그 다음 각 메뉴들에 대해서 null 체크를 하고, null일 경우에 메뉴를 null 안내 메시지로 대체.

if [ -n $menusSeoul0 ]
then
menusSeoul0="$strNullMsg"
fi
if [ -n $menusSeoul1 ]
then
menusSeoul1="$strNullMsg"
fi

그 다음 슬랙 API 에서 Incoming Webhook 을 만들고 해당 API 주소를 알아낸 뒤 아래와 같이 코딩 (여러 개의 슬랙으로 보낼 필요가 있어서 배열로~)

destination[0]="https://hooks.slack.com/services/slackapi_1_1/slackapi_1_2/slackapi_1_3"
destination[1]="https://hooks.slack.com/services/slackapi_2_1/slackapi_2_2/slackapi_2_3"  

channel[0]="#eat"
channel[1]="#general"

이제 대망의 슬랙으로 쏘기!

이 부분이 아주 중요한데 payload 를 문법에 맞게 잘 쌓아야한다.

특히 변수를 사용할 때는 ‘“$variable”’ 와 같이 따옴표를 다르게 쓰면 어디서 잘못됐는지 찾기어려워지므로 주의해야한다.

슬랙 API Reference 를 잘 찾아보면서 해야함!

for i in 0 1 2
do

echo "${destination[$i]}"
echo "${channel[$i]}"

curl -g -X POST --data-urlencode \
                    'payload=
                                    {
                                            "channel": "'${channel[$i]}'",
                                            "username": "밥대생",
                                            "icon_emoji": ":rice:",
                                            "attachments": [
                                            {
                                                        "text": "메뉴1 : '"$menusSeoul0"' \n메뉴2 : '"$menusSeoul1"' ",
                                                        "title": "식당이름1",
                                                        "pretext": "오늘의 학생식당 메뉴를 알려드립니다.",
                                                        "color": "#36a64f"
                                            },
                                            {
                                                        "text": "menu1 : '"$menusOther0"' \nmenu2 : '"$menusOther1"' \nmenu3 : '"$menusOther2"' ",
                                                        "title": "식당이름2",
                                                        "color": "#880000"
                                            }
                                            ]
                                    }
                    ' \
                                ${destination[$i]}
done

실행되는지 테스트하고 cron으로 내가 원하는 시간에 받아볼 수 있도록 설정하면 끝~!

(!!! 만약 채널($channel) 수와 목적지($destination) 수가 다르면 for 문 때문에 제대로 동작하지는 않을 것…)

여기까지 따라만 해도 거의 되겠지만, 코드의 의미를 하나씩 하나씩 살펴보면서 진행하니 많은 공부가 되었다.

Comments