이번 프로젝트에서 구글 캔린더 API를 디스코드 명령어를 통해 실행하는 기능을 담당했다.
처음 써 보는 API 기능이라 구글 공식 문서와 여러 블로그를 참고하여 일단 캘린더 목록을 조회하는 기능을 하는 코드를 작성 했다.
구글 캘린더 API를 사용하기 위해서는 필수적으로 거쳐야 하는 과정이 몇 가지 있었다.
우선 구글 클라우드 플랫폼에서 새 프로젝트를 생성한다.
그 다음 구글 캘린더 API를 검색하여 ‘사용’을 누른다.
다음으로 사용자 인증 정보를 만드는데 용도에 맞게 설정하면 된다.
이 다음이 중요한 OAuth 이다.
처음 이 개념을 이해하는 데 상당히 많은 시간이 걸렸던거 같다.
OAuth에 대한 개념은 찾아보면 상당히 많으니 생략하고 넘어가도록 하겠다. 간단히 설명하면 다른 서비스의 회원 정보를 안전하게 사용하기 위한 방법이다.
@client.command()
async def list(ctx, *, msg):
# 서버안의 유저 id
user_id = ctx.author.discriminator
# db 접속 정보
db_connect = pymysql.connect(host='호스트 주소', user='유저id', password='비밀번호', db='데이터베이스 이름', charset='utf8')
cur = db_connect.cursor()
# 디스코드 유저 id가 테이블에 존재하는지 확인
cur.execute(f"SELECT EXISTS (SELECT * from test where user_id={user_id} limit 1) as success")
user_result = cur.fetchall()
# 유저가 존재할 경우
if user_result[0][0] == 1:
db_connect = pymysql.connect(host='호스트 주소', user='유저id', password='비밀번호', db='데이터베이스 이름', charset='utf8')
cur = db_connect.cursor()
# 유저 id를 통해 저장된 토큰 값을 불러옴
cur.execute(f"SELECT token FROM test WHERE user_id={user_id}")
user_token = cur.fetchall()
user_token = json.loads(user_token[0][0])
# 불러온 토큰 정보를 통해 인증을 진행
creds = Credentials.from_authorized_user_info(user_token, SCOPES)
else:
# 유저가 존재하지 않을 경우
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
creds = flow.run_local_server(port=0) # 아마 이 부분때문에 인증 페이지가 로컬 서버에서만 표시되는 듯
token_json = json.dumps(creds.to_json())
db_connect = pymysql.connect(host='호스트 주소', user='유저id', password='비밀번호', db='데이터베이스 이름', charset='utf8')
cur = db_connect.cursor()
# 유저 id와 토큰 값을 db에 저장
cur.execute(f"INSERT INTO test (user_id, token) VALUES ({user_id}, {token_json})")
db_connect.commit()
위 코드처럼 구글 인증에 대한 부분을 진행하고 캘린더에 관련된 명령어를 하나씩 만들어 나갔다.
보통 token을 파일로 저장하지만 팀원의 아이디어로 mysql에 token값을 저장하는 테이블을 만들어서 진행하였다.

다른 팀원이 개발한 기능처럼 디스코드 임베드 안에 버튼을 활용 해 볼까 생각도 했지만 버튼을 사용하면 거쳐야 할 과정이 많아질 것 같았고, 그렇게 되면 오히려 더욱 불편할것 같아서, 결국 명령어로 기능을 구현하게 되었다.

위와같이 임베드에 이벤트의 내용을 텍스트로 표시하는 기능을 구현했다.
인증과 관련된 부분 외에는 크게 어렵게 막힌 부분은 없었던 것 같다.
대부분 Event 객체에 담겨진 내용을 불러와 적절히 배치하여 표시해주는 과정이었다.
막혔던 부분을 정리하자면, 첫 번째는 디스코드에서 입력받은 명령어에서 명령어, 시간, 날짜, 년도, 이벤트 제목 등을 구분해서 나누는 작업이었고 두 번째는 datetime을 사용하는 방법이었다. 크게 어려운 부분이 아니라서 금방 해결 할 수 있었다. 세 번째는 사용자가 이벤트를 생성할 때 시간을 지정한 경우 / 지정하지 않은 경우의 구분이었다. 이벤트의 시작과 종료 날짜의 키값이 달라져서 해당 부분에서 조금 어려움을 겪었다. 그리고 나중에 이벤트 제목이 지정되지 않았을 경우에도 리스트를 불러오지 못하는 문제가 발생했는데, 이벤트의 키값이 달라지는 문제를 겪고나니 금방 해결할 수 있었다.
하지만 결국 인증 문제 때문에 해당 기능을 배포하지 못하게 되었다.
토큰을 저장하기 위해서는 브라우저에서 인증 과정을 거쳐야 하는데, 해당 인증 페이지가 사용자에게 표시되지 않고, 개발자에게만 표시가 되었기 때문이다. 그래서 디스코드 서버에서 해당 인증 페이지가 표시돼서 인증을 진행할 방법을 찾지 못했다.
웹 프레임 워크로 구현했다면 어렵지 않게 해결되었을 문제지만, 디스코드 봇으로 구현하다보니 어려움이 있었다.
여러가지 방향으로 구글링 해서 시도 해 봤지만, 결국 해당 부분을 해결하지 못했다. (다른 팀원의 말 처럼 먼저 웹 프레임워크로 구현 해본 뒤에 디스코드에 적용해 봤어야 했다.)
그리고 코드를 완성하고 다시 보니 좀 더 코드를 간결하고 직관적으로 짤 수 있었다는 사실을 알게 되었다. 프로젝트가 끝나더라도 개인적으로 코드를 유지보수 해 보도록 해야겠다.