[Python] 구글 Open API로 캘린더 활용해보기

hukim·2022년 5월 7일
0

Open API

목록 보기
1/11
post-thumbnail

📆 구글 Open API로 구글 캘린더에 있는 내용을 확인해보기

현재 우리 팀에서는 구글 캘린더로 다음 이미지 처럼 휴가를 사용했을 경우 공유하고 있다.

또한, 작업 후 Pull Request하여 코드 리뷰를 하고 있다.
그래서 이 코드 리뷰를 할 리뷰어들을 2명씩 지정하는 스크립트를 간단히 만들어서 사용중이다.

🔖 리뷰어 지정 스크립트

import sys
import random


project_list = ["1", "2", "3"]
all_name_list = ["리뷰어1", "리뷰어2", "리뷰어3", "리뷰어4", "리뷰어5", "리뷰어6", "리뷰어7"]

input_project = input("""
    Pr프로젝트 입력하세요 : 
     - 프로젝트 1 : 1
     - 프로젝트 2 : 2
     - 프로젝트 3 : 3
""")

if input_project not in project_list:
    sys.exit("잘못된 프로젝트 입력 입니다.")

input_name = input(f"""
    이름을 입력하세요 : 
     - 이름 리스트 : "리뷰어1", "리뷰어2", "리뷰어3", "리뷰어4", "리뷰어5", "리뷰어6", "리뷰어7"
""")

if input_name not in all_name_list:
    sys.exit("잘못된 이름 입력 입니다.")


first_approve_list = []
second_approve_list = []

if input_project == "1":
    first_approve_list = ["리뷰어1", "리뷰어2", "리뷰어3"]
elif input_project == "2":
    first_approve_list = ["리뷰어1", "리뷰어4"]
else:
    first_approve_list = ["리뷰어1", "리뷰어3"]

second_approve_list = list(set(all_name_list) - set(first_approve_list))

try:
    first_approve_list.remove(input_name)
except ValueError:
    pass

try:
    second_approve_list.remove(input_name)
except ValueError:
    pass

print("첫번째 승인자 : {}".format(random.choice(first_approve_list)))
print("두번째 승인자 : {}".format(random.choice(second_approve_list)))

어느 프로젝트를 리뷰받을것인지 정하고 해당 프로젝트에는 고정적으로 리뷰되는 사람들이 first_approve_list에 지정되어있는 상황이다.

여기에 본인 + 고정리뷰어 제외하고 나머지 사람들 중 랜덤으로 지정하여 총 2명의 리뷰어를 뽑게된다.

하지만 현재는 누군가 휴가일 때 해당 인원을 제외하는 로직이 없다.
그래서 구글캘린더에 있는 정보를 이용하여 당일 휴가인 사람들을 제외하고 리뷰어들을 지정하게끔 만들어본다.

🍥 구글 API 연동하기

구글 클라우드 콘솔에서 API 키 생성하기

  1. 구글 클라우드 콘솔
    해당 콘솔에서 라이브러리에 들어간다.

  2. 라이브러리에서 Calendar를 검색해준다.
    Google Calendar API 를 선택해서 사용설정을 해준다.

  3. 사용자 인증 정보 탭에 들어가서 API키를 얻는다.

  4. API 키가 생성완료되었고, 해당 키로 캘린더API만 사용가능하게 제한 사항등을 추가하는 것도 가능하다.

  5. OAuth 클라이언트 ID로 들어가서 클라이언트 ID도 생성한다.

  6. 이미지 맨 오른쪽에서 해당 파일을 json형식으로 다운로드 받을 수 있다.

  7. OAuth 동의 화면 또한 절차에 따라서 생성해준다.

  8. 캘린더 ID는 캘린더의 설정 및 공유에 들어가서 얻을 수 있다.

🗓 구글 캘린더 API 요청하기

캘린더 API 퀵스타트

위 사이트에서 구글 캘린더 API에 접근하는 쉽고 빠른 방법이 자세히 설명되어있다.

  1. 파이썬의 구글 클라이언트 패키지 설치하기
pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
  1. 토큰 생성 샘플 스크립트
    샘플 스크립트
    이 스크립트를 실행할 때 위에서 생성한 클라이언트 ID가 필요하다.
    같은 폴더에 credentials.json 이라는 이름으로 위치시켜 준다.

  2. 위 스크립트를 실행하면 같은 폴더에 token.json이라는 파일이 생성되고 이 파일안에는 API 요청 시
    필요한 token이 포함되어있다.

  3. list 샘플 테스트 링크에 들어가면 이미지처럼 바로 테스트도 가능하게 되어있다.

  4. 위를 이용해서 포스트맨으로 API요청을 해본 결과이다. summary에 있는 값을 활용하면 될 것으로 보인다.

🌴 리뷰어 리스트에서 휴가자 제외하기

휴가자 목록 조회하기

def get_vacationer_list():
    url = f"https://www.googleapis.com/calendar/v3/calendars/{config.calendar_id}/events"

    now = datetime.datetime.now(datetime.timezone.utc)
    now2 = now + datetime.timedelta(hours=1)

    time_min = now.isoformat()
    time_max = now2.isoformat()

    params = {"key": config.google_api_key, "timeMax": time_max, "timeMin": time_min}
    response = requests.get(url, params=params, headers={"Authorization": f"Bearer {config.token}"})

    response = response.json()

    vacationer_list = []
    if response.get("items"):
        for item in response["items"]:
            vacationer_list.append(item.get("summary"))

    return vacationer_list

오늘 날짜 기준으로 휴가인 사람들 목록을 조회해온다.

만약 오늘 휴가자가 리뷰어1, 리뷰어4 연차 + 리뷰어2 오후반차 라고 한다면
vacationer_list['리뷰어1, 리뷰어4 연차', '리뷰어2 오후반차']의 결과 값을 얻을 수 있다.

이름만 추출하기

def convert_reviewer(vacationer_list):
    status_list = ["연차", "오후반차", "오전반차", "오전반반차", "오후반반차"]

    for i, vacationer in enumerate(vacationer_list):
        for vacation in status_list:
            if vacationer.find(vacation) != -1:
                vacationer_list[i] = vacationer.replace(f" {vacation}", "").split(",")

    reviewer_list = list(itertools.chain(*vacationer_list))
    return [review.strip() for review in reviewer_list]

해당 summary(캘린더에 등록한 일정내용)에 휴가 상태(연차, 오후반차 등)가 포함되어 있는지 확인을 한다.
일정이 휴가에 대한 일정이 맞다면 앞에 있는 내용들을 휴가자들로 간주하고 리스트에 담는다.
그렇게되면 결과 값이 [['리뷰어1', ' 리뷰어4'], ['리뷰어2']] 이런 형태로 반환된다.

그 다음 리스트들의 원소를 합치는 list(itertools.chain(*vacationer_list))를 이용하여 하나로 합치고
' 리뷰어4'같은 경우처럼 앞에 공백이 들어가는 것을 방지하기 위해 마지막에 한번 더 strip()으로 공백을 제거해준다.

전체코드

import itertools
import sys
import random
import requests
import datetime
import config


def get_vacationer_list():
    url = f"https://www.googleapis.com/calendar/v3/calendars/{config.calendar_id}/events"

    now = datetime.datetime.now(datetime.timezone.utc)
    now2 = now + datetime.timedelta(hours=1)

    time_min = now.isoformat()
    time_max = now2.isoformat()

    params = {"key": config.google_api_key, "timeMax": time_max, "timeMin": time_min}
    response = requests.get(url, params=params, headers={"Authorization": f"Bearer {config.token}"})

    response = response.json()

    vacationer_list = []
    if response.get("items"):
        for item in response["items"]:
            vacationer_list.append(item.get("summary"))

    return vacationer_list

def convert_reviewer(vacationer_list):
    status_list = ["연차", "오후반차", "오전반차", "오전반반차", "오후반반차"]

    for i, vacationer in enumerate(vacationer_list):
        for vacation in status_list:
            if vacationer.find(vacation) != -1:
                vacationer_list[i] = vacationer.replace(f" {vacation}", "").split(",")

    reviewer_list = list(itertools.chain(*vacationer_list))
    return [review.strip() for review in reviewer_list]


vacationer_list = get_vacationer_list()
reviewer_list = convert_reviewer(vacationer_list)

project_list = ["1", "2", "3"]
all_name_list = ["리뷰어1", "리뷰어2", "리뷰어3", "리뷰어4", "리뷰어5", "리뷰어6", "리뷰어7"]

input_project = input("""
    Pr프로젝트 입력하세요 : 
     - 프로젝트 1 : 1
     - 프로젝트 2 : 2
     - 프로젝트 3 : 3
""")

if input_project not in project_list:
    sys.exit("잘못된 프로젝트 입력 입니다.")

input_name = input(f"""
    이름을 입력하세요 : 
     - 이름 리스트 : "리뷰어1", "리뷰어2", "리뷰어3", "리뷰어4", "리뷰어5", "리뷰어6", "리뷰어7"
""")

if input_name not in all_name_list:
    sys.exit("잘못된 이름 입력 입니다.")


first_approve_list = []
second_approve_list = []

if input_project == "1":
    first_approve_list = ["리뷰어1", "리뷰어2", "리뷰어3"]
elif input_project == "2":
    first_approve_list = ["리뷰어1", "리뷰어4"]
else:
    first_approve_list = ["리뷰어1", "리뷰어3"]

all_name_list = list(set(all_name_list) - set(reviewer_list))
first_approve_list = list(set(first_approve_list) - set(reviewer_list))
second_approve_list = list(set(all_name_list) - set(first_approve_list))

try:
    first_approve_list.remove(input_name)
except ValueError:
    pass

try:
    second_approve_list.remove(input_name)
except ValueError:
    pass

first_reviewer = None
second_reviewer = None

if first_approve_list:
    first_reviewer = random.choice(first_approve_list)
    second_reviewer = random.choice(second_approve_list)
else:
    first_reviewer = random.choice(second_approve_list)
    second_approve_list.remove(first_reviewer)
    second_reviewer = random.choice(second_approve_list)

print(f"첫번째 승인자 : {first_reviewer}")
print(f"두번째 승인자 : {second_reviewer}")

후기

처음엔 페이지를 크롤링해서 데이터를 얻으면 되지않을까 생각하고 검색해봤는데 마침 OpenAPI가 있어서 이용해보게 되었다.
원래 3시간이면 후다닥 끝나는 줄 알았으나...
현실은 이것저것 걸림돌이 꽤 있었다.

위 코드도 아직 모자란게 산더미이다.
1시간주기로 구글에서 제공해주는 token이 만료가되는데 이걸 계속해서 갱신해야하는 점도 아직 미해결로 남았고
반차나 반반차의 경우에는 시간을 지정하여 해당 시간만 제외하고는 리뷰어로 남을 수 있게 하는 기능도 아직이다.
삽질의 시간에 비해서 가성비는 좋지않다.
구글 콘솔에서부터 개인용도이외에 사용하기엔 무리(보안상 + 번거로움)라는 건 눈치챘으나 이왕 시작해서 끝까지 코딩은 해봤다.

구글 API를 이용하기 위해서는 보안관련해서 체크하고 넘어가는 것이 너무많고
단순 실행 스크립트인데 연동때문에 설치해야되는 패키지도 있는 점이 단점이다.

0개의 댓글