본문 바로가기

토이 프로젝트

에픽게임즈 무료 게임 이벤트 정보 카톡으로 보내기

 

본 프로젝트는 에픽게임즈 스토어에서 매주 제공되는 무료 게임 이벤트에 대한 정보를 수집하고, 해당 정보를 매주 카카오톡을 통해 사용자에게 알려주는 애플리케이션입니다.

 

 

안녕하세요. 

게임을 아주 좋아하는 픽셀 펭귄입니다.

 

여러분 혹시 에픽게임즈 스토어라고 들어보셨나요?

 

에픽게임즈 스토어는 에픽 게임즈에서 운영하는 디지털 비디오 게임 쇼핑몰로,

다양한 개발사의 게임을 구매하거나 무료로 다운로드할 수 있는 플랫폼이에요.

 

스팀이랑 동일한 장르의 플랫폼이에요!

 

그리고 에픽게임즈는 매주 무료 게임 이벤트를 해요! 

한 주동안 하나의 게임을 무료로 다운받을 수 있는 이벤트이죠!!

 

https://store.epicgames.com/en-US/free-games

 

매주 다양한 게임을 무료로 플레이할 수 있어서 좋은 것 같아요!

 

그런데 저는 매주 웹사이트를 들어가는 것을 깜빡해서 새로운 게임 이벤트를 놓칠 때가 종종 있거든요.

 

그래서 본 프로젝트를 기획했어요.

 

EPIC GAMES KAKAOTALK NOTIFIER

 

그냥 매주 업데이트 되는 무료 게임 이벤트 정보를 카카오톡으로 알람메시지 주는 앱이에요ㅎㅎ

 

 

초간단 기획서

1. 에픽게임즈 스토어 크롤링/Official API/제3자 API

2. 카카오톡 API를 통해 이용자(나)에게 메시지 보내기

3. 클라우드 플랫폼/서비스 통해서 자동화

 

 

1번부터 하는게 정석이지만 

저는 2번을 먼저 해서 틀부터 짜기로 했어요.


 

카카오톡 API를 통해 나에게 메시지 보내기

1. 카카오 개발자 웹사이트에 들어가서 어플을 생성했습니다.

 

공식 문서를 열심히 보니 메시지를 보내기 위해서는

카톡 로그인 후 인가코드(토큰을 받기 위한 코드 값)를 받야하는 것을 알았습니다.

# [문서>카카오 로그인>REST API> 예제]
# 인가코드 요청 URL
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}

 

인가코드를 요청할 때 REST_API_KEY랑 REDIRECT_URI이 필요하군요!

 

[내 애플리케이션>앱 설정>요약]에서 REST API 키 확인

 

[내 애플리케이션>제품 설정>카카오 로그인] 활성화 설정 OFF → ON

 

인가코드를 받는 프로세스 중에 카톡 로그인 과정(Authentication Process)이 포함되어있으니,

카톡 로그인 활성화를 해줘야 합니다.

 

[내 애플리케이션>제품 설정>카카오 로그인] Redirect URI 생성

 

Redirect URI는 하나 생성했습니다.

 

※ Redirect URI는 OAuth 인증 프로세스에서 사용되는 주소로,

인증 서버가 사용자 인증 후 인증 코드나 액세스 토큰을 반환할 위치를 지정합니다.

 

 

[내 애플리케이션>제품 설정>카카오 로그인>동의항목] 카카오톡 메시지 전송의 접근권한을 부여

 

카카오톡 메시지 전송 접근권한을 선택동의로 설정해주었습니다.

 

 

# 인가코드 URL
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}

 

키값들을 파라미터 값에 입력하고 주소창에 입력합니다.

 

카카오톡 로그인 해주고 

 

전체동의 후, 주소창의 code 파라미터 값 확인

 

인가코드(code 파라미터값)을 받았으니,

엑조디아 완성했습니다.

 

[문서>카카오 로그인>REST API>카카오 로그인>토큰 받기]

 

# 토큰 요청 데이터 준비
data = {
    'grant_type': 'authorization_code',
    'client_id': REST_API_KEY,
    'redirect_uri': REDIRECT_URI,
    'code': CODE
}

# 토큰 요청 및 응답 저장
response = requests.post(url, data=data)
tokens = response.json()

# 토큰 파일 저장
with open("token.json", "w") as kakao:
    json.dump(tokens, kakao)

 

 

참고로, 토큰(엑세스)을 한번 받으면 6시간 동안 사용할 수 있습니다. 

그리고 리프레쉬 토큰을 통해 계속 재발급 받을 수 있습니다. 

 

리프레쉬 토큰은 지속기간이 2달이고 1달 이내로 남은 시점에 갱신이 가능합니다. 

그러므로 주기적으로 재발급/갱신을 통해 인가코드 프로세스 생략이 가능합니다.

 

def refresh():
    # 저장된 토큰 로드
    with open('token.json', 'r') as kakao:
        token = json.load(kakao)
    refresh_token = token['refresh_token']
    
    # 토큰 갱신 데이터 준비
    data={
        'grant_type': 'refresh_token',
        'client_id': REST_API_KEY,
        'refresh_token': refresh_token
    }
    response = requests.post(url, data=data)
    tokens = response.json()

    # 새 접근 토큰 저장
    with open("access_token.json", "w") as kakao:
        json.dump(tokens, kakao)

    # 리프레시 토큰 기한 마감이 한달 이내라면 파일 갱신
    # 한달 이내인 경우 'refresh_token'이 생성됨
    if 'refresh_token' in tokens:
        with open("token.json", "w") as kakao:
            json.dump(tokens, kakao)

 

만일 하나 갱신/재발급을 기간 내에 못하더라도

selenium을 통해 인가코드 발급 → 토큰 발급을 자동화할 수 있습니다. 


메시지 템플릿 설정

메시지 템플릿은 총 7가지가 있습니다.

  • 피드 
  • 리스트 
  • 위치
  • 커머스
  • 텍스트
  • 캘린더 
  • 스크랩

 

심사숙고 후, 저는 피드 템플릿을 사용하기로 결정했습니다. 

 

[문서>메시지>메시지 템플릿>메시지 템플릿 구성요소>피드 메시지]

 

[문서>메시지>카카오톡 메시지: REST API> 기본 템플릿으로 메시지 보내기>나에게 보내기]

 

공식 문서를 토대로 메시지 보내는 코드를 짜주었습니다.

import requests
import json
from template import template

def send():
    # 'access_token.json' 파일에서 액세스 토큰을 로드합니다.
    with open("access_token.json", "r") as kakao:
        tokens = json.load(kakao)
    ACCESS_TOKEN = tokens['access_token']
    
    # 요청 헤더를 설정합니다.
    headers = {
        'Authorization': f'Bearer {ACCESS_TOKEN}',  # Bearer 토큰으로 인증
        'Content-Type': 'application/x-www-form-urlencoded'  # 컨텐츠 유형 설정
    }

    # 데이터에 템플릿 객체를 포함시킵니다.
    data = {
        'template_object': template()  # template 함수에서 반환된 템플릿 사용
    }

    # 카카오 API에 POST 요청을 보냅니다.
    response = requests.post("https://kapi.kakao.com/v2/api/talk/memo/default/send", headers=headers, data=data)

    # 응답 상태 코드에 따라 결과를 출력합니다.
    if response.status_code == 200:
        print("메시지가 성공적으로 발송되었습니다!")
    else:
        print("메시지 발송에 실패했습니다.")
        print("상태 코드:", response.status_code)
        print("응답:", response.text)

 

기본 피드 템플릿으로 메시지를 저의 카톡으로 보내봤습니다.

성공!

 

그리고 [웹으로 이동] 버튼을 눌러도 링크로 이동하지 않는 상황이 발생하는데,

사이트 도메인 등록을 해야합니다.

 

[내 애플리케이션>앱 설정>플랫폼]


에픽 게임즈 이벤트 정보 구하기

 

일단 최종 웹사이트 크롤링 할 것을 고려하여 최종 디자인부터 구성했습니다.

 

 

 

그런데 아뿔싸 

에픽게임즈 스토어가 크롤링을 막아놓았습니다...

 

할려면 할수는 있을 것 같은데...

에픽게임즈 스토어의 데이터 수집 정책을 준수하고자 다른 방법을 알아보았습니다.

 

일반적으로 웹에 존재하는 정보를 수집하는 방법은 크게 3가지가 있습니다.

 

 

  • 크롤링: 웹사이트에서 데이터를 수집하는 과정입니다. 에픽게임즈의 웹페이지를 크롤링하면서 웹사이트의 HTML을 분석하고 필요한 정보를 추출합니다.
  • 공식 API: 에픽게임즈가 제공하는 프로그래밍 인터페이스(API)를 사용하여 데이터를 요청하고 받는 방법입니다. 이를 통해 무료 게임의 정보를 가져올 수 있습니다.
  • 제3자 API: 에픽게임즈의 정보를 제공하는 외부 서비스의 API를 사용하여 데이터를 가져오는 방법입니다. 이를 활용하여 무료 게임 정보를 쉽게 얻을 수 있습니다.

 

크롤링은 막혔고,

공식 API는 존재하나 무료게임 이벤트에 대한 정보 관련한 내용은 없었습니다.

 

아쉽지만, 저는 제3자 API를 선택했습니다. 

 

에픽게임즈 무료 이벤트에 대한 API가 RAPID API에 하나 등록되어 있더라고요. 

[Free Epic Games]

 

저는 한달에 4번 요청이 갈텐데

매달 요청 50건수까지 무료길래, 이것으로 선택했습니다.

 


프로젝트를 마무리하고 생각이 난 것인데, 

정보 수집 방법이 하나 더 있었습니다.

 

바로

여러 게임 플랫폼의 무료 게임 및 할인 정보를 추적하는 웹사이트를 크롤링 하는 것입니다.

 

다음과 같은 웹사이트가 있습니다.

  1. GG.deals: GG.deals는 다양한 게임 플랫폼의 할인 정보와 무료 게임 이벤트를 추적하고 제공합니다. 이 웹사이트에서는 사용자들이 원하는 플랫폼에서 무료 게임 및 할인 상품을 쉽게 찾을 수 있습니다.
  2. IsThereAnyDeal: IsThereAnyDeal은 여러 게임 디지털 배포 플랫폼의 할인 정보를 한 곳에서 모아 제공하는 서비스입니다. 이 웹사이트를 통해 사용자들은 원하는 게임을 어떤 플랫폼에서 가장 싸게 구매할 수 있는지 확인할 수 있습니다.
  3. CheapShark: CheapShark는 게임의 가격 추적 및 비교를 제공하는 웹사이트로, 다양한 디지털 게임 스토어의 할인 정보를 제공합니다. 무료 게임 이벤트와 함께 할인된 게임에 대한 정보도 제공됩니다.
  4. IndieGameBundles: IndieGameBundles는 인디 게임 번들 판매와 무료 게임 이벤트 정보를 제공합니다. 이 웹사이트는 다양한 인디 게임 번들 판매 정보뿐만 아니라 무료로 제공되는 게임들도 추적하고 소개합니다.

제 3자 API는 서비스 중단 리스크가 커서, 이 방법에 대해서 뒤늦게 알았다는 점이 아쉽네요.

크롤링은 내 목적에 맞는 정보를 알맞게 구할 수 있다는 장점이 또 있죠.

 

나중에 시간나면 바꾸든가 해야겠습니다.

 

아직 위 웹사이트가 크롤링이 되는지 아직 확인해보진 않았습니다. 


# API 요청 URL 설정
url = "https://free-epic-games.p.rapidapi.com/free"

# API 헤더에 RapidAPI 키와 호스트 정보를 추가
headers = {
	"X-RapidAPI-Key": keyring.get_password('RAPIDAPI', 'KEY'),
	"X-RapidAPI-Host": keyring.get_password('RAPIDAPI', 'HOST')
}

# API 요청을 보내고 응답을 JSON 형태로 받음
response = requests.get(url, headers=headers)
info = response.json()

def to_kr(date):
    # UTC 시간을 한국 시간(KST)으로 변환
    date_format = "%Y-%m-%dT%H:%M:%S.%fZ"
    date_obj = datetime.strptime(date, date_format)
    date_kr = date_obj + timedelta(hours=9)
    date_YMD = date_kr.strftime("%Y-%m-%d")
    return date_YMD

def title():
    # 게임 제목 반환
    title = info['freeGames']['current'][0]['title']
    return title

def description():
    # 게임 설명 반환
    description = info['freeGames']['current'][0]['description']
    return description

def release_date():
    # 게임 출시일 반환
    release_date = info['freeGames']['current'][0]['effectiveDate']
    release_date_YMD = to_kr(release_date)
    return release_date_YMD

def image():
    # 게임 이미지 URL 반환
    image = info['freeGames']['current'][0]['keyImages'][0]['url']
    return image

def price():
    # 게임 원래 가격 반환
    price_original = info['freeGames']['current'][0]['price']['totalPrice']['fmtPrice']['originalPrice']
    return price_original

def event_start():
    # 이벤트 시작 시간 반환
    event_start = info['freeGames']['current'][0]['promotions']['promotionalOffers'][0]['promotionalOffers'][0]['startDate']
    event_start_YMD = to_kr(event_start)
    return event_start_YMD

def event_end():
    # 이벤트 종료 시간 반환
    event_end =  info['freeGames']['current'][0]['promotions']['promotionalOffers'][0]['promotionalOffers'][0]['endDate']
    event_end_YMD = to_kr(event_end)
    return event_end_YMD

 

제가 원하는 정보들이 다 포함되어 있지 않아서 아숩네요...

그래도 API를 통해 최대한 정보를 받아서 템플릿의 적재적소에 넣어줍니다.

 

그리고 전송(send)!

완성!


클라우드 서비스를 통한 어플 자동화

 

 

어떤 클라우드 서비스/플랫폼을 사용할 지 상당히 고민이 됐습니다...

 

전에는 이런 간단한 어플의 경우, 헤로쿠를 이용하여 무료로 배포 가능했는데 말이죠..

 

AI가 들어서서 이제 '전력난이다, 에너지 부족이다' 해서

무료인 클라우드 플랫폼을 찾기가 상당히 어려워졌습니다. 

(혹시 무료로 플랫폼 사용하시는 거 있으시면 메시지 좀 부탁드리겠습니다ㅎㅎ)

 

 

저는 고민 끝에 네이버 클라우드를 사용해 보기로 했습니다.

이런 것이 있더라구요! AWS EC2 무료 1년은 다 써버렸는지라ㅠㅠ

 

만약 저처럼 1년 무료로 사용하실 분은 꼭

1년 끝나기 전에 서버 종료하셔야 합니다!! (1년지난 시점에 과금 엄청 나올 수 있어요!)

 

Micro 서버 사용하시려면 Rocky Linux서버 선택하셔야 돼요.

 

 

뚝딱뚝딱해서 만들어줍니다.

 

서버 관리자 비밀번호 확인하고,

공인 IP 생성해주었습니다.

 

연결은 putty로만 가능한 것 같아서 

다운받고 서버에 연결해주었습니다

 

비번 어려워서 2번이나 틀렸습니다. 바로 들어가자마자 비번부터 바꿨습니다.

 

Rocky Linux는 Debian 기반이 아닌 RHEL(Red Hat Enterprise Linux) 기반의 배포판입니다.

패키지 관리에는 dnf(command)을 사용합니다.

 

Rocky Linux는 처음이였지만 Linux는 처음이 아니라 어려운 점은 없었습니다. 

 

 

Filezilla 프로그램 사용하면, 한꺼번에 보낼 수 있지만

파일 몇 개 없어서 수기로 복붙해서 생성했습니다.

 

 

일단은 확인용으로 스케쥴러 포함하지 않고,

app.py를 실행해 주었습니다.

 

이런저런 모듈 없다는 에러를 통해

없는 모듈 확인하고 모두 인스톨해줍니다. 

 

Finally,

성공! 메시지도 카톡으로 확인!

 

 

app.py를 수정하여 스케쥴러를 포함시켜 줍니다.

from kakao import token, refresh
from send import send
from datetime import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.interval import IntervalTrigger

def app():
    try:
        refresh()  # 토큰을 새로고침을 시도합니다.
    except Exception as e:
        # 토큰 새로고침에 실패할 경우, 새로운 토큰을 받아 다시 새로고침을 시도합니다.
        print(f"오류 발생: {e}. 새 토큰을 가져와 다시 시도합니다.")
        token()
        refresh()
    finally:
        # 최종적으로 메시지를 보냅니다.
        send()

if __name__ == "__main__":
    scheduler = BlockingScheduler()

    # 스케줄 시작 날짜 설정 (하루 시간 버퍼)
    start_date = datetime(2024, 4, 13)

    # 매주 한 번씩 실행되는 트리거 설정
    trigger = IntervalTrigger(weeks=1, start_date=start_date)

    # 스케줄러에 작업 추가
    scheduler.add_job(app, trigger)

    # 앱이 언제부터 매 7일마다 실행되는지 출력
    print(f"앱이 {start_date.strftime('%Y-%m-%d')}부터 매 7일마다 실행됩니다.")

    try:
        # 스케줄러 시작
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        # 키보드 인터럽트나 시스템 종료 시 스케줄러를 종료합니다.
        scheduler.shutdown()

 

연결 인스턴스 종료해도 파일이 계속 작동할 수 있도록, 

nohup python3 app.py & 입력

 

 

 

이렇게 프로젝트가 완료되었습니다!!

 

저의 Full Code는 저의 Github페이지에서 보실 수 있습니다. 

https://github.com/BeatKraQ/Epic-Games-Event/tree/main

 

GitHub - BeatKraQ/Epic-Games-Event: 이 프로젝트는 에픽게임즈 스토어에서 매주 제공되는 무료 게임 이벤

이 프로젝트는 에픽게임즈 스토어에서 매주 제공되는 무료 게임 이벤트에 대한 정보를 수집하고, 해당 정보를 매주 카카오톡을 통해 사용자에게 알려주는 애플리케이션입니다. - GitHub - BeatKraQ/E

github.com

 

카카오톡 메시지 전송으로 결과물을 매주 받는 방식으로 자동화를 이루어냈는데,

노션의 위젯 형식으로 만드는 방법도 재미있을 것 같네요. 

 

나중에 기회가 되면 한번 해봐야겠습니다. 


-일주일 후-

 

정확한 시간에 오긴했는데, 업데이트가 안됐습니다.

 

시간 버퍼를 더 줘야겠네요...

아무래도 제3자 API를 사용하다보니 시간 공백이 있는 것 같습니다;;

스케쥴 시작날짜를 14일 오전 9시로 설정하겠습니다.

 

성공!!